package repository

import (
	"context"
	"lune/talentscale/internal/domain"
	"time"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgxpool"
)

type postgresPaymentRepository struct {
	db *pgxpool.Pool
}

func NewPostgresPaymentRepository(db *pgxpool.Pool) domain.PaymentRepository {
	return &postgresPaymentRepository{db: db}
}

func (r *postgresPaymentRepository) CreateTransaction(ctx context.Context, tx *domain.PaymentTransaction) error {
	query := `INSERT INTO payment_transactions (id, company_id, user_id, order_id, external_id, amount, currency, payment_method, status, paid_at, expired_at, payload, created_at)
	          VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`
	_, err := r.db.Exec(ctx, query, tx.ID, tx.CompanyID, tx.UserID, tx.OrderID, tx.ExternalID, tx.Amount, tx.Currency, tx.PaymentMethod, tx.Status, tx.PaidAt, tx.ExpiredAt, tx.Payload, tx.CreatedAt)
	return err
}

func (r *postgresPaymentRepository) GetTransactionByOrderID(ctx context.Context, orderID string) (*domain.PaymentTransaction, error) {
	query := `SELECT id, company_id, user_id, order_id, external_id, amount, currency, payment_method, status, paid_at, expired_at, payload, created_at
	          FROM payment_transactions WHERE order_id = $1`
	var tx domain.PaymentTransaction
	err := r.db.QueryRow(ctx, query, orderID).Scan(&tx.ID, &tx.CompanyID, &tx.UserID, &tx.OrderID, &tx.ExternalID, &tx.Amount, &tx.Currency, &tx.PaymentMethod, &tx.Status, &tx.PaidAt, &tx.ExpiredAt, &tx.Payload, &tx.CreatedAt)
	if err != nil {
		return nil, err
	}
	return &tx, nil
}
func (r *postgresPaymentRepository) UpdateTransactionStatus(ctx context.Context, orderID string, status string, paidAt *time.Time) error {
	query := `UPDATE payment_transactions SET status = $1, paid_at = $2 WHERE order_id = $3`
	_, err := r.db.Exec(ctx, query, status, paidAt, orderID)
	return err
}

func (r *postgresPaymentRepository) ListTransactionsByCompany(ctx context.Context, companyID uuid.UUID) ([]domain.PaymentTransaction, error) {
	query := `SELECT id, company_id, user_id, order_id, external_id, amount, currency, payment_method, status, paid_at, expired_at, payload, created_at
	          FROM payment_transactions WHERE company_id = $1 ORDER BY created_at DESC`
	rows, err := r.db.Query(ctx, query, companyID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var list []domain.PaymentTransaction
	for rows.Next() {
		var tx domain.PaymentTransaction
		if err := rows.Scan(&tx.ID, &tx.CompanyID, &tx.UserID, &tx.OrderID, &tx.ExternalID, &tx.Amount, &tx.Currency, &tx.PaymentMethod, &tx.Status, &tx.PaidAt, &tx.ExpiredAt, &tx.Payload, &tx.CreatedAt); err != nil {
			return nil, err
		}
		list = append(list, tx)
	}
	return list, nil
}

func (r *postgresPaymentRepository) CreateHistory(ctx context.Context, history *domain.PaymentHistory) error {
	query := `INSERT INTO payment_history (id, company_id, package_id, amount, status, payment_transaction_id, type, created_at, updated_at)
	          VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`
	_, err := r.db.Exec(ctx, query, history.ID, history.CompanyID, history.PackageID, history.Amount, history.Status, history.PaymentTransactionID, history.Type, history.CreatedAt, history.UpdatedAt)
	return err
}

func (r *postgresPaymentRepository) ListHistoryByCompany(ctx context.Context, companyID uuid.UUID) ([]domain.PaymentHistory, error) {
	query := `SELECT id, company_id, package_id, amount, status, payment_transaction_id, type, created_at, updated_at
	          FROM payment_history WHERE company_id = $1 AND deleted_at IS NULL ORDER BY created_at DESC`
	rows, err := r.db.Query(ctx, query, companyID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var historyList []domain.PaymentHistory
	for rows.Next() {
		var h domain.PaymentHistory
		if err := rows.Scan(&h.ID, &h.CompanyID, &h.PackageID, &h.Amount, &h.Status, &h.PaymentTransactionID, &h.Type, &h.CreatedAt, &h.UpdatedAt); err != nil {
			return nil, err
		}
		historyList = append(historyList, h)
	}
	return historyList, nil
}

func (r *postgresPaymentRepository) GetHistoryByID(ctx context.Context, id uuid.UUID) (*domain.PaymentHistory, error) {
	query := `SELECT id, company_id, package_id, amount, status, payment_transaction_id, type, created_at, updated_at
	          FROM payment_history WHERE id = $1 AND deleted_at IS NULL`
	var h domain.PaymentHistory
	err := r.db.QueryRow(ctx, query, id).Scan(&h.ID, &h.CompanyID, &h.PackageID, &h.Amount, &h.Status, &h.PaymentTransactionID, &h.Type, &h.CreatedAt, &h.UpdatedAt)
	if err != nil {
		return nil, err
	}
	return &h, nil
}
