package repository

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

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

type postgresUsageRecordRepository struct {
	db *pgxpool.Pool
}

func NewPostgresUsageRecordRepository(db *pgxpool.Pool) domain.UsageRecordRepository {
	return &postgresUsageRecordRepository{db: db}
}

func (r *postgresUsageRecordRepository) Create(ctx context.Context, record *domain.UsageRecord) error {
	query := `INSERT INTO usage_records (id, company_id, year, month, candidates_used, created_at, updated_at)
	          VALUES ($1, $2, $3, $4, $5, $6, $7)`
	_, err := r.db.Exec(ctx, query, record.ID, record.CompanyID, record.Year, record.Month, record.CandidatesUsed, record.CreatedAt, record.UpdatedAt)
	return err
}

func (r *postgresUsageRecordRepository) GetByID(ctx context.Context, id uuid.UUID) (*domain.UsageRecord, error) {
	query := `SELECT id, company_id, year, month, candidates_used, created_at, updated_at
	          FROM usage_records WHERE id = $1`
	var record domain.UsageRecord
	err := r.db.QueryRow(ctx, query, id).Scan(&record.ID, &record.CompanyID, &record.Year, &record.Month, &record.CandidatesUsed, &record.CreatedAt, &record.UpdatedAt)
	if err != nil {
		return nil, err
	}
	return &record, nil
}

func (r *postgresUsageRecordRepository) GetByCompanyAndPeriod(ctx context.Context, companyID uuid.UUID, year, month int) (*domain.UsageRecord, error) {
	query := `SELECT id, company_id, year, month, candidates_used, created_at, updated_at
	          FROM usage_records WHERE company_id = $1 AND year = $2 AND month = $3`
	var record domain.UsageRecord
	err := r.db.QueryRow(ctx, query, companyID, year, month).Scan(&record.ID, &record.CompanyID, &record.Year, &record.Month, &record.CandidatesUsed, &record.CreatedAt, &record.UpdatedAt)
	if err != nil {
		return nil, err
	}
	return &record, nil
}

func (r *postgresUsageRecordRepository) ListByCompany(ctx context.Context, companyID uuid.UUID) ([]domain.UsageRecord, error) {
	query := `SELECT id, company_id, year, month, candidates_used, created_at, updated_at
	          FROM usage_records WHERE company_id = $1 ORDER BY year DESC, month DESC`
	rows, err := r.db.Query(ctx, query, companyID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var records []domain.UsageRecord
	for rows.Next() {
		var record domain.UsageRecord
		if err := rows.Scan(&record.ID, &record.CompanyID, &record.Year, &record.Month, &record.CandidatesUsed, &record.CreatedAt, &record.UpdatedAt); err != nil {
			return nil, err
		}
		records = append(records, record)
	}
	return records, nil
}

func (r *postgresUsageRecordRepository) Update(ctx context.Context, record *domain.UsageRecord) error {
	query := `UPDATE usage_records SET candidates_used = $1, updated_at = $2 WHERE id = $3`
	_, err := r.db.Exec(ctx, query, record.CandidatesUsed, time.Now(), record.ID)
	return err
}

func (r *postgresUsageRecordRepository) IncrementUsage(ctx context.Context, companyID uuid.UUID, year, month int, count int) error {
	query := `INSERT INTO usage_records (id, company_id, year, month, candidates_used, created_at, updated_at)
	          VALUES ($1, $2, $3, $4, $5, $6, $7)
	          ON CONFLICT (company_id, year, month)
	          DO UPDATE SET candidates_used = usage_records.candidates_used + $5, updated_at = $7`
	id := uuid.New()
	now := time.Now()
	_, err := r.db.Exec(ctx, query, id, companyID, year, month, count, now, now)
	return err
}
