package seatbilling

import (
	"context"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

func (store *Store) ListActivePlans(ctx context.Context) ([]SeatPlan, error) {
	db, err := store.requireDB()
	if err != nil {
		return nil, err
	}
	rows, err := db.Query(ctx, `
SELECT
  id,
  plan_key,
  name,
  billing_period,
  unit_price_cents,
  currency,
  managed_agents_per_seat,
  min_seat_quantity,
  max_seat_quantity,
  self_service_enabled,
  status,
  COALESCE(CAST(metadata_json AS CHAR), '{}') AS metadata_json,
  created_at,
  updated_at
FROM organization_seat_plans
WHERE status = 'active'
ORDER BY
  CASE plan_key WHEN 'team' THEN 1 WHEN 'enterprise' THEN 2 WHEN 'max' THEN 3 ELSE 9 END,
  CASE billing_period WHEN 'month' THEN 1 WHEN 'quarter' THEN 2 WHEN 'year' THEN 3 ELSE 9 END,
  id
`)
	if err != nil {
		return nil, fmt.Errorf("list active seat plans: %w", err)
	}
	defer rows.Close()

	plans := make([]SeatPlan, 0)
	for rows.Next() {
		plan, err := scanSeatPlan(rows)
		if err != nil {
			return nil, err
		}
		plans = append(plans, plan)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate active seat plans: %w", err)
	}
	return plans, nil
}

func (store *Store) LoadSelfServicePlan(ctx context.Context, planKey string, billingPeriod string) (SeatPlan, error) {
	db, err := store.requireDB()
	if err != nil {
		return SeatPlan{}, err
	}
	return loadSelfServicePlan(ctx, db, planKey, billingPeriod)
}

func loadSelfServicePlan(ctx context.Context, queryer coredb.QueryRower, planKey string, billingPeriod string) (SeatPlan, error) {
	trimmedPlanKey := strings.TrimSpace(planKey)
	trimmedBillingPeriod := strings.TrimSpace(billingPeriod)
	if trimmedPlanKey == "" {
		return SeatPlan{}, storeerr.BadRequest("planKey is required")
	}
	if trimmedBillingPeriod == "" {
		return SeatPlan{}, storeerr.BadRequest("billingPeriod is required")
	}
	plan, err := scanSeatPlan(queryer.QueryRow(ctx, `
SELECT
  id,
  plan_key,
  name,
  billing_period,
  unit_price_cents,
  currency,
  managed_agents_per_seat,
  min_seat_quantity,
  max_seat_quantity,
  self_service_enabled,
  status,
  COALESCE(CAST(metadata_json AS CHAR), '{}') AS metadata_json,
  created_at,
  updated_at
FROM organization_seat_plans
WHERE plan_key = $1
  AND billing_period = $2
  AND status = 'active'
  AND self_service_enabled = TRUE
`, trimmedPlanKey, trimmedBillingPeriod))
	if err != nil {
		if coredb.IsNotFound(err) {
			return SeatPlan{}, storeerr.NotFound("seat plan not found")
		}
		return SeatPlan{}, err
	}
	return plan, nil
}

type seatPlanScanner interface {
	Scan(...any) error
}

func scanSeatPlan(scanner seatPlanScanner) (SeatPlan, error) {
	var plan SeatPlan
	if err := scanner.Scan(
		&plan.ID,
		&plan.PlanKey,
		&plan.Name,
		&plan.BillingPeriod,
		&plan.UnitPriceCents,
		&plan.Currency,
		&plan.ManagedAgentsPerSeat,
		&plan.MinSeatQuantity,
		&plan.MaxSeatQuantity,
		&plan.SelfServiceEnabled,
		&plan.Status,
		&plan.MetadataJSON,
		&plan.CreatedAt,
		&plan.UpdatedAt,
	); err != nil {
		return SeatPlan{}, fmt.Errorf("scan seat plan: %w", err)
	}
	return plan, nil
}
