/**
 * Analysis Action Extractor
 * ──────────────────────────
 * Extracts actionable items from a structured Analysis object.
 * These can later be converted into Execution Hub tasks.
 *
 * Only extracts actions that are backed by real analysis evidence.
 * No generic filler recommendations.
 */

import type { Analysis, Finding, AnalysisRecommendation, Caveat, Prediction } from "./analysis-schema";

// ─── Extracted Action Schema ────────────────────────────────────────────────

export interface ExtractedAction {
  id: string;
  title: string;
  description: string;
  sourceSection: "finding" | "recommendation" | "caveat" | "prediction";
  sourceId: string;
  analysisJobId: string;
  brandId: string;

  // Classification
  priority: "critical" | "high" | "medium" | "low";
  effort: "low" | "medium" | "high";
  actionType: "investigate" | "fix" | "monitor" | "configure" | "create_content" | "connect_source";

  // Context
  affectedPage?: string;
  affectedMetric?: string;
  evidence: string;

  // Signals Center taxonomy (derived client-side in ReviewPanel)
  category?: "issue" | "opportunity" | "win";
  revenueImpact?: "high" | "medium" | "low";

  // Branding context
  clientName: string;
  clientDomain: string;
}

// ─── Extractor ──────────────────────────────────────────────────────────────

export function extractActions(analysis: Analysis): ExtractedAction[] {
  const actions: ExtractedAction[] = [];
  const base = {
    analysisJobId: analysis.id,
    brandId: analysis.brandId,
    clientName: analysis.branding?.clientName ?? "",
    clientDomain: analysis.branding?.clientDomain ?? "",
  };

  // ── From Findings ──
  for (const f of analysis.findings) {
    const action = findingToAction(f, base);
    if (action) actions.push(action);
  }

  // ── From Recommendations ──
  for (const r of analysis.recommendations) {
    actions.push(recommendationToAction(r, base));
  }

  // ── From Caveats (only actionable ones) ──
  for (const c of analysis.caveats) {
    const action = caveatToAction(c, base);
    if (action) actions.push(action);
  }

  // ── From Predictions (only those implying action) ──
  for (const p of analysis.predictions) {
    const action = predictionToAction(p, base);
    if (action) actions.push(action);
  }

  // Sort by priority
  const order: Record<string, number> = { critical: 0, high: 1, medium: 2, low: 3 };
  actions.sort((a, b) => (order[a.priority] ?? 4) - (order[b.priority] ?? 4));

  return actions;
}

// ─── Finding → Action ───────────────────────────────────────────────────────

function findingToAction(f: Finding, base: ActionBase): ExtractedAction | null {
  // Only extract actions from anomalies and risks, not stable/info findings
  if (f.type === "insight" && f.severity === "info") return null;
  if (f.title === "Performance is stable") return null;

  return {
    id: `action_finding_${f.id}`,
    title: f.type === "anomaly" ? `Investigate: ${f.title}` : f.type === "risk" ? `Address: ${f.title}` : `Review: ${f.title}`,
    description: f.description + (f.impact ? ` Impact: ${f.impact}` : ""),
    sourceSection: "finding",
    sourceId: f.id,
    priority: f.severity === "info" ? "low" : f.severity as ExtractedAction["priority"],
    effort: f.type === "anomaly" ? "medium" : "high",
    actionType: f.type === "anomaly" ? "investigate" : f.type === "risk" ? "fix" : "monitor",
    affectedMetric: f.affectedMetric,
    evidence: f.evidence ?? f.description,
    ...base,
  };
}

// ─── Recommendation → Action ────────────────────────────────────────────────

function recommendationToAction(r: AnalysisRecommendation, base: ActionBase): ExtractedAction {
  return {
    id: `action_rec_${r.relatedFinding ?? Math.random().toString(36).slice(2, 8)}`,
    title: r.title,
    description: r.description + (r.expectedImpact ? ` Expected: ${r.expectedImpact}` : ""),
    sourceSection: "recommendation",
    sourceId: r.relatedFinding ?? "",
    priority: r.priority,
    effort: r.effort,
    actionType: "fix",
    evidence: r.expectedImpact ?? r.description,
    ...base,
  };
}

// ─── Caveat → Action (only actionable) ──────────────────────────────────────

function caveatToAction(c: Caveat, base: ActionBase): ExtractedAction | null {
  // Only "data_gap" and "staleness" caveats are actionable — they imply connecting a source or re-running
  if (c.type === "data_gap") {
    return {
      id: `action_caveat_${c.type}_${Math.random().toString(36).slice(2, 8)}`,
      title: `Connect missing source: ${c.title}`,
      description: c.description,
      sourceSection: "caveat",
      sourceId: c.type,
      priority: c.severity === "critical" ? "high" : "medium",
      effort: "low",
      actionType: "connect_source",
      evidence: c.description,
      ...base,
    };
  }

  if (c.type === "staleness") {
    return {
      id: `action_caveat_stale_${Math.random().toString(36).slice(2, 8)}`,
      title: `Re-sync stale data: ${c.title}`,
      description: c.description,
      sourceSection: "caveat",
      sourceId: c.type,
      priority: "medium",
      effort: "low",
      actionType: "configure",
      evidence: c.description,
      ...base,
    };
  }

  return null;
}

// ─── Prediction → Action (only declining) ───────────────────────────────────

function predictionToAction(p: Prediction, base: ActionBase): ExtractedAction | null {
  // Only create an action if the prediction shows decline
  if (p.predicted >= p.current) return null;

  const declinePct = Math.round(((p.current - p.predicted) / p.current) * 100);

  return {
    id: `action_pred_${p.metric.replace(/\s+/g, "_").toLowerCase()}`,
    title: `Monitor: ${p.metric} projected to decline ${declinePct}%`,
    description: `${p.metric} is projected to drop from ${p.current.toLocaleString()} to ${p.predicted.toLocaleString()} over ${p.timeframe}. ${p.basis}`,
    sourceSection: "prediction",
    sourceId: p.metric,
    priority: declinePct > 20 ? "high" : "medium",
    effort: "low",
    actionType: "monitor",
    affectedMetric: p.metric,
    evidence: p.basis + (p.caveat ? ` Note: ${p.caveat}` : ""),
    ...base,
  };
}

// ─── Types ──────────────────────────────────────────────────────────────────

type ActionBase = Pick<ExtractedAction, "analysisJobId" | "brandId" | "clientName" | "clientDomain">;
