package ai

import (
	"context"
	"strings"

	"github.com/jackc/pgx/v5/pgxpool"

	"github.com/ultisuite/ulti-backend/internal/ai/cost"
	"github.com/ultisuite/ulti-backend/internal/llm"
)

// QuotaService wraps cost policy and metering for backward compatibility.
type QuotaService struct {
	db     *pgxpool.Pool
	policy *cost.PolicyService
	meter  *cost.Meter
}

func NewQuotaService(db *pgxpool.Pool) *QuotaService {
	return &QuotaService{
		db:     db,
		policy: cost.NewPolicyService(db),
		meter:  cost.NewMeter(db),
	}
}

func (s *QuotaService) Check(ctx context.Context, externalUserID string) (SpendStatus, error) {
	orgBilling, _ := s.usesOrgBilling(ctx, externalUserID)
	status, err := s.policy.GetStatus(ctx, externalUserID, orgBilling)
	if err != nil {
		return SpendStatus{}, err
	}
	return status, nil
}

func (s *QuotaService) AssertAvailable(ctx context.Context, externalUserID string, provider llm.Provider, useOrgSettings bool) error {
	scope := ResolveBillingScope(ctx, s.db, externalUserID, provider, useOrgSettings)
	return s.policy.AssertAvailable(ctx, externalUserID, scope)
}

func (s *QuotaService) RecordUsage(ctx context.Context, in cost.RecordInput) error {
	return s.meter.RecordUsage(ctx, in)
}

func (s *QuotaService) usesOrgBilling(ctx context.Context, externalUserID string) (bool, error) {
	settings, err := LoadEffectiveLLMSettings(ctx, s.db, externalUserID)
	if err != nil {
		return true, err
	}
	org, err := loadOrgLLMPolicy(ctx, s.db)
	if err != nil {
		return true, err
	}
	if org.EnforceOrgProviders || len(settings.Providers) == 0 {
		return true, nil
	}
	user, err := loadUserLLMSettings(ctx, s.db, externalUserID)
	if err != nil {
		return true, err
	}
	return len(user.Providers) == 0, nil
}

// ResolveBillingScope determines whether usage is billed to org or user's own key.
func ResolveBillingScope(ctx context.Context, db *pgxpool.Pool, externalUserID string, provider llm.Provider, useOrgSettings bool) string {
	if useOrgSettings {
		return cost.BillingScopeOrg
	}
	org, err := loadOrgLLMPolicy(ctx, db)
	if err != nil || org.EnforceOrgProviders {
		return cost.BillingScopeOrg
	}
	user, err := loadUserLLMSettings(ctx, db, externalUserID)
	if err != nil || len(user.Providers) == 0 {
		return cost.BillingScopeOrg
	}
	apiKey := strings.TrimSpace(provider.APIKey)
	for _, op := range org.Providers {
		if op.ID == provider.ID && strings.TrimSpace(op.APIKey) == apiKey && apiKey != "" {
			return cost.BillingScopeOrg
		}
	}
	for _, up := range user.Providers {
		if up.ID == provider.ID && strings.TrimSpace(up.APIKey) != "" {
			return cost.BillingScopeUser
		}
	}
	return cost.BillingScopeOrg
}

// SpendStatus is the user-facing quota/spend response.
type SpendStatus = cost.SpendStatus

// ErrQuotaExceeded aliases cost limit error for backward compatibility.
var ErrQuotaExceeded = cost.ErrCostLimitExceeded
