import modelData from "@/data/bad-ads-model.json";
import type { Business } from "@/lib/types";

export interface BadAdsModel {
  version: number;
  trainedAt: string;
  source: string;
  sourceUrl: string;
  paperUrl: string;
  sampleCount: number;
  global: { avgBadScore: number; avgGoodScore: number; avgRating: number };
  labelMeans: Record<string, number>;
  copyTriggers: Record<string, { weight: number; avoid: string; fix: string }>;
  worstClusters: Array<{ clusterId: string; avgBad: number; avgRating: number; topNegative: string[] }>;
  contentLabelRisk: Array<{ label: string; ads: number; avgBad: number; avgRating: number }>;
  topNegativeLabels: Array<{ label: string; meanScore: number }>;
  topPositiveLabels: Array<{ label: string; meanScore: number }>;
}

export interface AdCopyRiskSignal {
  label: string;
  score: number;
  triggered: boolean;
  avoid: string;
  fix: string;
}

export interface AdCopyMLScore {
  badScore: number;
  goodScore: number;
  predictedRating: number;
  riskLevel: "low" | "medium" | "high";
  signals: AdCopyRiskSignal[];
  recommendations: string[];
}

export interface MLStrategyBrief {
  model: Pick<BadAdsModel, "source" | "sampleCount" | "paperUrl" | "sourceUrl" | "trainedAt">;
  adCopyScore?: AdCopyMLScore;
  industryAdGuidance: string[];
  trustAndCreativeRules: string[];
  whatToDoNext: string[];
  revenuePotential: string;
  executiveSummary: string;
}

const model = modelData as BadAdsModel;

const COPY_PATTERNS: Record<string, RegExp[]> = {
  clickbait: [
    /you won'?t believe/i,
    /one weird trick/i,
    /doctors hate/i,
    /click here/i,
    /shocking/i,
    /secret(s)? (they|nobody)/i,
    /before it's too late/i,
  ],
  deceptive: [
    /free(?!\s+(estimate|consult|inspection))/i,
    /no catch/i,
    /100%\s*(guaranteed|free)/i,
    /limited time only/i,
    /act now/i,
    /lowest price/i,
  ],
  manipulative: [
    /don'?t miss out/i,
    /last chance/i,
    /you'?re missing/i,
    /everyone is switching/i,
    /fomo/i,
  ],
  bad_design: [/!!!+/],
  unclear: [/best in town/i, /quality service/i, /leading provider/i, /\bsolutions\b/i],
  boring: [/welcome to our website/i, /we are committed/i],
  untrustworthy: [/trust us/i, /#1 rated(?!\s+by)/i],
};

function clamp(n: number, min = 0, max = 1) {
  return Math.min(max, Math.max(min, n));
}

function clampRange(n: number, min: number, max: number) {
  return Math.min(max, Math.max(min, n));
}

export function getBadAdsModel(): BadAdsModel {
  return model;
}

export function scoreAdCopy(text: string): AdCopyMLScore {
  const signals: AdCopyRiskSignal[] = [];
  let badScore = model.global.avgBadScore;
  let goodScore = model.global.avgGoodScore;

  for (const [key, patterns] of Object.entries(COPY_PATTERNS)) {
    const trigger = model.copyTriggers[key];
    if (!trigger) continue;
    const triggered = patterns.some((p) => p.test(text));
    const baseMean = model.labelMeans[key === "untrustworthy" ? "deceptive" : key] ?? 0.15;
    const score = triggered ? clamp(baseMean * trigger.weight * 2) : baseMean * 0.5;
    if (triggered) badScore += score * 0.15;
    else goodScore += (model.labelMeans.simple ?? 0.2) * 0.05;

    signals.push({
      label: key,
      score,
      triggered,
      avoid: trigger.avoid,
      fix: trigger.fix,
    });
  }

  if (/\d+\s*(★|star|review)/i.test(text) || /licensed|insured|certified/i.test(text)) {
    goodScore += 0.12;
  }
  if (text.length > 20 && text.length < 280) goodScore += 0.05;

  badScore = clamp(badScore);
  goodScore = clamp(goodScore);
  const predictedRating = clampRange(2 + (goodScore - badScore) * 4 + model.global.avgRating / 7, 1, 7);

  const riskLevel: AdCopyMLScore["riskLevel"] =
    badScore > 0.35 ? "high" : badScore > 0.22 ? "medium" : "low";

  const recommendations = signals
    .filter((s) => s.triggered)
    .map((s) => s.fix)
    .slice(0, 4);

  if (recommendations.length === 0) {
    recommendations.push(
      model.copyTriggers.unclear.fix,
      `Emphasize ${model.topPositiveLabels[0]?.label.replace(/_/g, " ") ?? "trustworthy"} cues — under-indexed in bad ads dataset`,
    );
  }

  return {
    badScore: Math.round(badScore * 100) / 100,
    goodScore: Math.round(goodScore * 100) / 100,
    predictedRating: Math.round(predictedRating * 10) / 10,
    riskLevel,
    signals: signals.sort((a, b) => Number(b.triggered) - Number(a.triggered) || b.score - a.score),
    recommendations,
  };
}

function topOpportunity(business: Business) {
  return [...business.opportunities].sort((a, b) => b.estimatedValue - a.estimatedValue)[0];
}

function buildDraftAdCopy(business: Business): string {
  const rec = business.recommendations[0];
  const opp = topOpportunity(business);
  return [
    rec?.adConcept,
    rec?.socialPost,
    rec?.landingHeadline,
    opp?.recommendedAction,
    business.profile.brandPositioning,
  ]
    .filter(Boolean)
    .join(" ");
}

export function generateMLStrategy(business: Business, question: string): MLStrategyBrief {
  const q = question.toLowerCase();
  const opp = topOpportunity(business);
  const draftCopy = buildDraftAdCopy(business);
  const adScore = scoreAdCopy(draftCopy || question);

  const isAdQuestion =
    q.includes("ad") ||
    q.includes("marketing") ||
    q.includes("content") ||
    q.includes("brand") ||
    q.includes("grow") ||
    q.includes("competitor") ||
    q.includes("promote") ||
    q.includes("campaign");

  const topNeg = model.topNegativeLabels.slice(0, 3).map((l) => l.label.replace(/_/g, " "));
  const topPos = model.topPositiveLabels.slice(0, 3).map((l) => l.label.replace(/_/g, " "));

  const industryAdGuidance = [
    `Dataset insight: users most often dislike ads labeled ${topNeg.join(", ")} (n=${model.sampleCount} ads, CHI 2021).`,
    `Winning patterns in the dataset: ${topPos.join(", ")} — aim above global avg good score (${model.global.avgGoodScore.toFixed(2)}).`,
    `High-risk ad types in training data: ${model.contentLabelRisk.slice(0, 3).map((c) => c.label).join(", ")} — extra proof required if you use these formats.`,
  ];

  const trustAndCreativeRules = adScore.signals
    .filter((s) => s.triggered)
    .slice(0, 3)
    .map((s) => `Avoid ${s.label.replace(/_/g, " ")}: ${s.avoid} → ${s.fix}`);

  if (trustAndCreativeRules.length === 0) {
    trustAndCreativeRules.push(
      `Your draft scores ${adScore.riskLevel} risk (bad ${adScore.badScore}, good ${adScore.goodScore}, predicted ${adScore.predictedRating}/7 vs dataset avg ${model.global.avgRating.toFixed(1)}/7).`,
      model.copyTriggers.deceptive.fix,
      model.copyTriggers.clickbait.fix,
    );
  }

  const whatToDoNext = [
    opp?.recommendedAction ?? business.recommendations[0]?.whatToDoNext ?? "Ship one focused campaign this week",
    ...adScore.recommendations.slice(0, 2),
    business.socialMediaAnalysis
      ? `Social pick-share ${business.socialMediaAnalysis.yourPickSharePercent}% — lead with ${business.socialMediaAnalysis.trust.strongerChannel === "social" ? "authentic social proof" : "website trust signals"} in ads`
      : "Run social media analysis to align ad trust with your strongest channel",
  ];

  const revenuePotential = opp
    ? `$${opp.estimatedValue.toLocaleString()} from "${opp.title}" if ad copy passes ML risk check (predicted rating ${adScore.predictedRating}/7)`
    : `$${business.metrics.revenuePotential.toLocaleString()} pipeline — poor ads underperform dataset baseline`;

  const executiveSummary = isAdQuestion
    ? `ML strategy (trained on ${model.sampleCount} annotated ads): Your current messaging has ${adScore.riskLevel} bad-ad risk. Focus on ${topPos[0] ?? "trust"} and eliminate ${topNeg[0] ?? "clickbait"} patterns before scaling spend.`
    : `ML-backed growth strategy for ${business.input.businessName}: ${opp?.title ?? business.metrics.topPriorityToday}. Ad perception model flags ${adScore.riskLevel} creative risk — fix before paid amplification.`;

  return {
    model: {
      source: model.source,
      sampleCount: model.sampleCount,
      paperUrl: model.paperUrl,
      sourceUrl: model.sourceUrl,
      trainedAt: model.trainedAt,
    },
    adCopyScore: isAdQuestion || draftCopy.length > 30 ? adScore : undefined,
    industryAdGuidance,
    trustAndCreativeRules,
    whatToDoNext,
    revenuePotential,
    executiveSummary,
  };
}

export function formatMLStrategyBrief(brief: MLStrategyBrief): string {
  const lines = [
    `ML Strategy Engine — ${brief.model.source}`,
    `Trained on ${brief.model.sampleCount} ads (CHI 2021: ${brief.model.paperUrl})`,
    ``,
    `What is happening: ${brief.executiveSummary}`,
    ``,
    `Why it matters: Bad ads in the dataset averaged ${getBadAdsModel().global.avgRating.toFixed(1)}/7 rating. Worst clusters scored ${getBadAdsModel().worstClusters[0]?.avgRating.toFixed(1)}/7.`,
  ];

  if (brief.adCopyScore) {
    lines.push(
      ``,
      `Your ad copy ML score: bad ${brief.adCopyScore.badScore} · good ${brief.adCopyScore.goodScore} · predicted ${brief.adCopyScore.predictedRating}/7 · risk ${brief.adCopyScore.riskLevel.toUpperCase()}`,
    );
  }

  lines.push(
    ``,
    `Dataset insights:`,
    ...brief.industryAdGuidance.map((g) => `• ${g}`),
    ``,
    `Creative rules (from ML):`,
    ...brief.trustAndCreativeRules.map((r) => `• ${r}`),
    ``,
    `What to do next:`,
    ...brief.whatToDoNext.map((w) => `• ${w}`),
    ``,
    `Revenue potential: ${brief.revenuePotential}`,
    ``,
    `Source dataset: ${brief.model.sourceUrl}`,
  );

  return lines.join("\n");
}
