package economy

import "context"

// LoadCatalog کاتالوگ را از دیتابیس خوانده و در حافظه کش می‌کند.
// در شروع برنامه و پس از هر ویرایشِ ادمین فراخوانی می‌شود.
func (s *Service) LoadCatalog(ctx context.Context) error {
	var c Catalog

	rows, err := s.db.QueryContext(ctx,
		`SELECT id, title, coins, vip_days, price_toman, bonus_pct, sku FROM coin_packages WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return err
	}
	for rows.Next() {
		var p CoinPackage
		if err := rows.Scan(&p.ID, &p.Title, &p.Coins, &p.VIPDays, &p.PriceToman, &p.BonusPct, &p.SKU); err != nil {
			rows.Close()
			return err
		}
		c.CoinPackages = append(c.CoinPackages, p)
	}
	rows.Close()

	rows, err = s.db.QueryContext(ctx,
		`SELECT id, title, tickets, price_toman, sku FROM ticket_packages WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return err
	}
	for rows.Next() {
		var p TicketPackage
		if err := rows.Scan(&p.ID, &p.Title, &p.Tickets, &p.PriceToman, &p.SKU); err != nil {
			rows.Close()
			return err
		}
		c.TicketPackages = append(c.TicketPackages, p)
	}
	rows.Close()

	rows, err = s.db.QueryContext(ctx,
		`SELECT id, title, price_coins FROM card_skins WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return err
	}
	for rows.Next() {
		var p CardSkin
		if err := rows.Scan(&p.ID, &p.Title, &p.PriceCoins); err != nil {
			rows.Close()
			return err
		}
		c.CardSkins = append(c.CardSkins, p)
	}
	rows.Close()

	rows, err = s.db.QueryContext(ctx,
		`SELECT id, title, multiplier, hours, price_toman, sku FROM boosters WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return err
	}
	for rows.Next() {
		var p Booster
		if err := rows.Scan(&p.ID, &p.Title, &p.Multiplier, &p.Hours, &p.PriceToman, &p.SKU); err != nil {
			rows.Close()
			return err
		}
		c.Boosters = append(c.Boosters, p)
	}
	rows.Close()

	rows, err = s.db.QueryContext(ctx,
		`SELECT id, title, months, price_toman, sku FROM vip_packages WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return err
	}
	for rows.Next() {
		var p VIPPackage
		if err := rows.Scan(&p.ID, &p.Title, &p.Months, &p.PriceToman, &p.SKU); err != nil {
			rows.Close()
			return err
		}
		c.VIPPackages = append(c.VIPPackages, p)
	}
	rows.Close()

	rows, err = s.db.QueryContext(ctx,
		`SELECT id, title, hands, entry, prize, xp, trophy, rank_reward FROM table_tiers WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return err
	}
	for rows.Next() {
		var p TableTier
		if err := rows.Scan(&p.ID, &p.Title, &p.Hands, &p.Entry, &p.Prize, &p.XP, &p.Trophy, &p.RankReward); err != nil {
			rows.Close()
			return err
		}
		c.TableTiers = append(c.TableTiers, p)
	}
	rows.Close()

	s.mu.Lock()
	s.cat = c
	s.mu.Unlock()
	return nil
}

// Catalog کپیِ کشِ فعلیِ کاتالوگ را برمی‌گرداند.
func (s *Service) Catalog() Catalog {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.cat
}

func (s *Service) findCoinPackage(id string) *CoinPackage {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for i := range s.cat.CoinPackages {
		if s.cat.CoinPackages[i].ID == id {
			p := s.cat.CoinPackages[i]
			return &p
		}
	}
	return nil
}

func (s *Service) findTicketPackage(id string) *TicketPackage {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for i := range s.cat.TicketPackages {
		if s.cat.TicketPackages[i].ID == id {
			p := s.cat.TicketPackages[i]
			return &p
		}
	}
	return nil
}

func (s *Service) findCardSkin(id string) *CardSkin {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for i := range s.cat.CardSkins {
		if s.cat.CardSkins[i].ID == id {
			p := s.cat.CardSkins[i]
			return &p
		}
	}
	return nil
}

func (s *Service) findBooster(id string) *Booster {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for i := range s.cat.Boosters {
		if s.cat.Boosters[i].ID == id {
			p := s.cat.Boosters[i]
			return &p
		}
	}
	return nil
}

func (s *Service) findVIPPackage(id string) *VIPPackage {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for i := range s.cat.VIPPackages {
		if s.cat.VIPPackages[i].ID == id {
			p := s.cat.VIPPackages[i]
			return &p
		}
	}
	return nil
}

// FindTier نوع میز را از کش برمی‌گرداند (برای لایه بازی).
func (s *Service) FindTier(id string) *TableTier {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for i := range s.cat.TableTiers {
		if s.cat.TableTiers[i].ID == id {
			t := s.cat.TableTiers[i]
			return &t
		}
	}
	return nil
}
