/**
 * Runs one audit against an IT Glue record.
 *
 * Phase 4 supported only Application (flexible_asset) audits, all-time
 * scoped. Phase 4.1 generalizes:
 *   - assetType: 'flexible_asset' | 'configuration'
 *   - ticketScopeAnalysisId: when set, ticket evidence is the single source
 *     analysis only ("ticket-first" mode).
 *
 * Flow:
 *   1. buildAssetAuditContext() — pulls everything; redacted.
 *   2. callLLMStage() — single shot using the deep-analysis tier model for
 *      the requested provider (Sonnet for Anthropic, V4 Pro for OpenRouter).
 *   3. insertAssetAudit() — persists the row, including ticket linkage.
 */

import { callLLMStage } from '@/lib/services/llm/call';
import {
  type Provider,
  stageModelsFor,
} from '@/lib/services/llm/models';
import { AssetAuditResponse } from '@/lib/types/analyzer';
import {
  buildAssetAuditContext,
  type AuditAssetType,
} from './data-builder';
import { getSystemPrompt, buildAssetAuditUserPayload } from './prompt';
import {
  insertAssetAudit,
  insertFailedAssetAudit,
} from './persistence';

const STAGE_MAX_TOKENS = 8_000;

export interface RunAssetAuditInput {
  assetType: AuditAssetType;
  assetId: number | string;
  generatedByUserId: string | null;
  provider?: Provider;
  /** Phase 4.1: when set, ticket evidence narrows to just this analysis. */
  ticketScopeAnalysisId?: string;
}

export interface RunAssetAuditResult {
  auditId: string;
  status: 'complete' | 'failed';
  ticketCount: number;
  errorMessage?: string;
}

export async function runAssetAudit(
  input: RunAssetAuditInput
): Promise<RunAssetAuditResult> {
  const provider: Provider = input.provider ?? 'anthropic';
  const model = stageModelsFor(provider).deep_analysis;

  const ctx = await buildAssetAuditContext({
    assetType: input.assetType,
    assetId: input.assetId,
    ticketScopeAnalysisId: input.ticketScopeAnalysisId,
  });
  const ticketCount = ctx.ticket_evidence.length;

  const assetSnapshot = {
    id: ctx.asset.id,
    name: ctx.asset.name,
    organization_id: ctx.asset.organization_id,
    organization_name: ctx.asset.organization_name,
    asset_type: ctx.asset_type,
    type_id: ctx.type_id,
    type_name: ctx.type_name,
    fields: ctx.asset.traits,
  };

  const triggeredByTicketNumber = ctx.ticket_scope?.ticket_number ?? null;
  const triggeredByAnalysisId = ctx.ticket_scope?.analysis_id ?? null;

  const { payload } = buildAssetAuditUserPayload(ctx);
  const systemPrompt = getSystemPrompt(ctx);

  try {
    const result = await callLLMStage({
      model,
      system: systemPrompt,
      user: payload,
      schema: AssetAuditResponse,
      maxTokens: STAGE_MAX_TOKENS,
    });

    const inserted = await insertAssetAudit({
      asset_type: ctx.asset_type,
      asset_id: ctx.asset.id,
      asset_type_id: ctx.type_id,
      organization_id: ctx.asset.organization_id,
      generated_by_user_id: input.generatedByUserId,
      provider,
      model_used: model,
      asset_snapshot: assetSnapshot,
      ticket_count: ticketCount,
      response: result.data,
      estimated_cost_usd: result.estimated_cost_usd,
      total_input_tokens: result.usage.input_tokens,
      total_output_tokens: result.usage.output_tokens,
      triggered_by_ticket_number: triggeredByTicketNumber,
      triggered_by_analysis_id: triggeredByAnalysisId,
    });

    return {
      auditId: inserted.id,
      status: 'complete',
      ticketCount,
    };
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err);
    const failed = await insertFailedAssetAudit({
      asset_type: ctx.asset_type,
      asset_id: ctx.asset.id,
      asset_type_id: ctx.type_id,
      organization_id: ctx.asset.organization_id,
      generated_by_user_id: input.generatedByUserId,
      provider,
      model_used: model,
      asset_snapshot: assetSnapshot,
      ticket_count: ticketCount,
      error_message: message,
      triggered_by_ticket_number: triggeredByTicketNumber,
      triggered_by_analysis_id: triggeredByAnalysisId,
    });
    return {
      auditId: failed.id,
      status: 'failed',
      ticketCount,
      errorMessage: message,
    };
  }
}
