/**
 * Cost guards for analyzer LLM operations.
 *
 * Spec: docs/ticket-analyzer-phase2-spec.md → Section D.8.
 *
 * Three thresholds:
 *   • $5 per request  → require explicit confirmation in UI
 *   • $20 per user/day → soft warn (returned in preflight; UI can surface)
 *   • $50 per user/day → hard block (unless user is in override list)
 *
 * Override env var: ANALYZER_DAILY_COST_OVERRIDE_USERS (comma-separated user ids)
 */

import postgresClient from '@/lib/services/postgres-client';

export const REQUIRES_CONFIRMATION_USD = 5.0;
export const SOFT_WARN_DAILY_USD = 20.0;
export const HARD_BLOCK_DAILY_USD = 50.0;

export type CostDecision =
  | 'approved'
  | 'requires_confirmation'
  | 'blocked'
  | 'overridden';

export interface CostEvaluation {
  estimatedCost: number;
  dailySpendBefore: number;
  decision: CostDecision;
  decisionReason: string | null;
  softWarn: boolean;
  hardBlocked: boolean;
  requiresConfirmation: boolean;
  isOverride: boolean;
}

/**
 * Pessimistic cost estimate for an aggregate report. Assumes Sonnet pricing
 * and a payload size proportional to the number of fingerprints (each ~2KB
 * after compaction). Conservative — actual cost is usually lower.
 */
export function estimateAggregateReportCost(input: {
  ticketCount: number;
  includeItglueContext: boolean;
}): number {
  // Inputs:
  //   per-fingerprint input tokens ≈ 700 (compacted JSON) → 700 * N
  //   distributions + system prompt ≈ 2000 tokens
  //   IT Glue context (if included): up to 200 doc titles * 50 tokens = 10K tokens
  // Outputs: cap ≈ 6K tokens (we set max_tokens 16K but real outputs are smaller).
  const inputTokens =
    700 * input.ticketCount +
    2000 +
    (input.includeItglueContext ? 10_000 : 0);
  const outputTokens = 6_000;
  // Sonnet pricing per Phase 1 pricing table: $3/$15 per 1M tokens.
  const cost = (inputTokens / 1_000_000) * 3 + (outputTokens / 1_000_000) * 15;
  return Math.round(cost * 10_000) / 10_000;
}

function getOverrideUsers(): Set<string> {
  return new Set(
    (process.env.ANALYZER_DAILY_COST_OVERRIDE_USERS ?? '')
      .split(',')
      .map((s) => s.trim())
      .filter(Boolean)
  );
}

export async function getUserDailySpend(userId: string | null): Promise<number> {
  if (!userId) return 0;
  // Sum from analyzer_aggregate_reports + analyzer_analyses for the trailing 24h.
  const res = await postgresClient.query<{ total: string }>(
    `SELECT COALESCE(SUM(amt), 0)::text AS total FROM (
       SELECT estimated_cost_usd AS amt
         FROM analyzer_aggregate_reports
        WHERE generated_by_user_id = $1
          AND generated_at >= NOW() - INTERVAL '24 hours'
          AND estimated_cost_usd IS NOT NULL
       UNION ALL
       SELECT estimated_cost_usd AS amt
         FROM analyzer_analyses
        WHERE triggered_by_user_id = $1
          AND triggered_at >= NOW() - INTERVAL '24 hours'
          AND status = 'complete'
     ) x`,
    [userId]
  );
  return Number(res.rows[0]?.total ?? 0);
}

export async function evaluateCost(input: {
  userId: string | null;
  estimatedCost: number;
  confirmedCost: boolean;
}): Promise<CostEvaluation> {
  const dailySpendBefore = await getUserDailySpend(input.userId);
  const projectedDailySpend = dailySpendBefore + input.estimatedCost;
  const overrideUsers = getOverrideUsers();
  const isOverride = input.userId !== null && overrideUsers.has(input.userId);

  const softWarn = projectedDailySpend >= SOFT_WARN_DAILY_USD;
  const hardBlocked = projectedDailySpend >= HARD_BLOCK_DAILY_USD;
  const requiresConfirmation =
    input.estimatedCost > REQUIRES_CONFIRMATION_USD && !input.confirmedCost;

  let decision: CostDecision;
  let decisionReason: string | null = null;
  if (hardBlocked && !isOverride) {
    decision = 'blocked';
    decisionReason = `Projected daily spend $${projectedDailySpend.toFixed(2)} would exceed hard limit $${HARD_BLOCK_DAILY_USD.toFixed(2)}`;
  } else if (hardBlocked && isOverride) {
    decision = 'overridden';
    decisionReason = `Override allowed (user in ANALYZER_DAILY_COST_OVERRIDE_USERS); projected $${projectedDailySpend.toFixed(2)}`;
  } else if (requiresConfirmation) {
    decision = 'requires_confirmation';
    decisionReason = `Per-request cost $${input.estimatedCost.toFixed(2)} > confirmation threshold $${REQUIRES_CONFIRMATION_USD.toFixed(2)}`;
  } else {
    decision = 'approved';
  }

  return {
    estimatedCost: input.estimatedCost,
    dailySpendBefore,
    decision,
    decisionReason,
    softWarn,
    hardBlocked,
    requiresConfirmation,
    isOverride,
  };
}

export async function recordCostAuditDecision(input: {
  userId: string | null;
  action: string;
  evaluation: CostEvaluation;
  context?: Record<string, unknown>;
}): Promise<void> {
  await postgresClient.query(
    `INSERT INTO analyzer_cost_audit
       (user_id, action, estimated_cost, daily_spend_before,
        decision, decision_reason, context)
     VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
    [
      input.userId,
      input.action,
      input.evaluation.estimatedCost,
      input.evaluation.dailySpendBefore,
      input.evaluation.decision,
      input.evaluation.decisionReason,
      JSON.stringify(input.context ?? {}),
    ]
  );
}
