package economy

import "context"

// ChatPack یک بسته‌ی پیام/شکلکِ چت. Owned یعنی کاربر می‌تواند از آن استفاده کند
// (رایگان، یا VIP برای بسته‌ی vip، یا خریداری‌شده).
type ChatPack struct {
	ID         string   `json:"id"`
	Title      string   `json:"title"`
	Kind       string   `json:"kind"` // text | emoji
	PriceCoins int64    `json:"price_coins"`
	VIP        bool     `json:"vip"` // برای VIP رایگان است
	Owned      bool     `json:"owned"`
	Messages   []string `json:"messages"`
}

// ChatPacks بسته‌های فعال را همراه پیام‌ها و وضعیتِ مالکیتِ کاربر برمی‌گرداند.
func (s *Service) ChatPacks(ctx context.Context, userID int64) ([]ChatPack, error) {
	rows, err := s.db.QueryContext(ctx,
		`SELECT id, title, kind, price_coins, vip FROM chat_packs WHERE enabled = 1 ORDER BY sort`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var packs []ChatPack
	for rows.Next() {
		var p ChatPack
		var vip int
		if err := rows.Scan(&p.ID, &p.Title, &p.Kind, &p.PriceCoins, &vip); err != nil {
			return nil, err
		}
		p.VIP = vip == 1
		packs = append(packs, p)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}

	owned, err := s.ownedChatPacks(ctx, userID)
	if err != nil {
		return nil, err
	}
	isVIP := s.isVIP(ctx, userID)

	for i := range packs {
		p := &packs[i]
		// رایگان (بدون قیمت و غیرِ vip)، یا VIP برای بسته‌ی vip، یا خریداری‌شده.
		p.Owned = (p.PriceCoins == 0 && !p.VIP) || (p.VIP && isVIP) || owned[p.ID]
		msgs, err := s.packMessages(ctx, p.ID)
		if err != nil {
			return nil, err
		}
		p.Messages = msgs
	}
	return packs, nil
}

func (s *Service) packMessages(ctx context.Context, packID string) ([]string, error) {
	rows, err := s.db.QueryContext(ctx,
		`SELECT body FROM chat_messages WHERE pack_id = ? ORDER BY sort, id`, packID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	msgs := []string{}
	for rows.Next() {
		var b string
		if err := rows.Scan(&b); err != nil {
			return nil, err
		}
		msgs = append(msgs, b)
	}
	return msgs, rows.Err()
}

func (s *Service) ownedChatPacks(ctx context.Context, userID int64) (map[string]bool, error) {
	rows, err := s.db.QueryContext(ctx,
		`SELECT pack_id FROM user_chat_packs WHERE user_id = ?`, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	owned := map[string]bool{}
	for rows.Next() {
		var id string
		if err := rows.Scan(&id); err != nil {
			return nil, err
		}
		owned[id] = true
	}
	return owned, rows.Err()
}

// BuyChatPack یک بسته‌ی چت را با سکه باز می‌کند. بسته‌های رایگان/قبلاً‌مالک خطا
// می‌دهند؛ بسته‌ی VIP برای کاربرِ VIP خودبه‌خود در دسترس است (نیازی به خرید نیست).
func (s *Service) BuyChatPack(ctx context.Context, userID int64, packID string) error {
	var price int64
	var vip, enabled int
	err := s.db.QueryRowContext(ctx,
		`SELECT price_coins, vip, enabled FROM chat_packs WHERE id = ?`, packID).
		Scan(&price, &vip, &enabled)
	if err != nil || enabled != 1 {
		return ErrNotFound
	}

	tx, err := s.db.BeginTx(ctx, nil)
	if err != nil {
		return err
	}
	defer tx.Rollback()

	var exists int
	_ = tx.QueryRowContext(ctx,
		`SELECT 1 FROM user_chat_packs WHERE user_id = ? AND pack_id = ?`, userID, packID).Scan(&exists)
	if exists == 1 {
		return ErrAlreadyOwned
	}
	if price > 0 {
		if err := adjustTx(ctx, tx, userID, CurrencyCoin, -price, "buy_chat_pack", packID); err != nil {
			return err
		}
	}
	if _, err := tx.ExecContext(ctx,
		`INSERT INTO user_chat_packs (user_id, pack_id) VALUES (?, ?)`, userID, packID); err != nil {
		return err
	}
	return tx.Commit()
}
