import type { BrandProfile, Project } from "@/types/workflow";
import type { WebsiteIntelligence } from "./website-intelligence";
import type { StoryAct } from "./context-library";
import { getActLabel, getActTag } from "./context-library";
import {
  deriveSeoKeywords,
  formatSeoKeywordsLine,
  resolveContentCategoryForBeat,
} from "@/lib/generation/content-strategist";
import { getNarrativeScaffold } from "./narrative-scaffold";
import type { StoryArcBeat } from "./story-types";
import {
  resolveDynamicProductConfig,
  type DynamicProductConfiguration,
} from "@/lib/generation/dynamic-product-config";

function companyLabel(brand: BrandProfile, project: Project, website?: WebsiteIntelligence | null): string {
  return brand.companyName?.trim() || website?.companyName?.trim() || project.name?.trim() || "Your Company";
}

function industryLabel(brand: BrandProfile, project: Project, website?: WebsiteIntelligence | null): string {
  const candidates = [
    brand.industry?.trim(),
    project.industry?.trim(),
    website?.keywords?.[0]?.trim(),
  ].filter(Boolean) as string[];
  for (const c of candidates) {
    if (!looksLikeMarketingSloganDump(c)) return c;
  }
  // Fall back to cleaned vertical / offering — never a raw slogan
  if (website?.vertical === "fax") return "B2B communication";
  if (website?.vertical === "email") return "email marketing";
  if (website?.vertical === "sms") return "SMS marketing";
  const service = website?.primaryService?.trim();
  if (service) return cleanServiceName(service);
  return "";
}

/** Prefer brand tagline; avoid stuffing long scraped slogans into every section. */
function taglineLabel(
  brand: BrandProfile,
  company: string,
  website?: WebsiteIntelligence | null,
): string {
  const brandLine = brand.tagline?.trim();
  if (brandLine) return brandLine;
  const site = website?.tagline?.trim() || "";
  if (site && !looksLikeMarketingSloganDump(site) && site.length <= 90) return site;
  return company;
}

function serviceLabels(website?: WebsiteIntelligence | null, brand?: BrandProfile): string[] {
  const fromSite = website?.services?.map((s) => s.label).filter(Boolean) ?? [];
  if (fromSite.length) return fromSite;
  if (website?.headings?.length) {
    return website.headings.filter((h) => !looksLikeMarketingSloganDump(h)).slice(0, 5);
  }
  if (brand?.tagline?.trim() && !looksLikeMarketingSloganDump(brand.tagline)) {
    return [brand.tagline.trim()];
  }
  if (website?.primaryService?.trim()) return [cleanServiceName(website.primaryService)];
  return [];
}

/** Short product name for natural prose — not a full scraped marketing headline. */
function primaryOffering(
  website: WebsiteIntelligence | null | undefined,
  brand: BrandProfile,
  company: string,
): string {
  const raw =
    website?.primaryService?.trim() ||
    website?.services?.[0]?.label?.trim() ||
    brand.tagline?.trim() ||
    company;
  return cleanServiceName(raw) || company;
}

function looksLikeMarketingSloganDump(text: string): boolean {
  const t = text.trim();
  if (t.length > 70) return true;
  if (/market your (service|business)/i.test(t)) return true;
  if (/best ever|next level|revolutioniz|game.?chang|cutting.?edge|transform(ing|ation) your/i.test(t)) {
    return true;
  }
  if ((t.match(/-/g) || []).length >= 2 && t.length > 40) return true;
  return false;
}

/** Concrete industries readers recognize — avoid vague “B2B Communications / eFax”. */
function audienceIndustries(industry: string, website?: WebsiteIntelligence | null): string {
  const hay = `${industry} ${website?.description || ""} ${(website?.keywords || []).join(" ")}`.toLowerCase();
  const hits: string[] = [];
  if (/health|hospital|hipaa|clinic|medical/.test(hay)) hits.push("healthcare");
  if (/legal|law|attorney|counsel/.test(hay)) hits.push("legal");
  if (/insur|claims|underwrit/.test(hay)) hits.push("insurance");
  if (/finance|bank|fintech|lending/.test(hay)) hits.push("finance");
  if (hits.length >= 2) {
    const last = hits[hits.length - 1]!;
    return `${hits.slice(0, -1).join(", ")}, and ${last}`;
  }
  if (hits.length === 1) return hits[0]!;
  if (website?.vertical === "fax") {
    return "healthcare, legal, insurance, and finance";
  }
  return industry?.trim() && !/b2b communications?|efax|e-fax/i.test(industry)
    ? industry.trim()
    : "healthcare, legal, insurance, finance, and enterprise operations";
}

function scenarioLine(
  website?: WebsiteIntelligence | null,
  product?: DynamicProductConfiguration,
): string {
  if (product?.solutionCategory === "dnc") {
    return "When a sales team dials a restricted or duplicate record buried in a cluttered master list, one avoidable friction point becomes an enterprise compliance risk.";
  }
  if (product?.solutionCategory === "call_tracking") {
    return "When inbound spikes surge without clear source attribution, marketing spend keeps rising while leadership cannot see which campaigns actually connect.";
  }
  if (product?.solutionCategory === "dialer") {
    return "When agents sit idle between manual dials while queues stall, high-volume outreach quietly loses an entire shift of opportunities.";
  }
  const v = website?.vertical || product?.solutionCategory || "generic";
  if (v === "fax") {
    return "When a contract approval sits unanswered or a compliance document reaches the wrong inbox, communication delays quickly become operational risks.";
  }
  if (v === "email") {
    return "When a time-sensitive proposal lands in spam or a follow-up chain stalls unanswered, pipeline velocity becomes an operational risk.";
  }
  if (v === "sms") {
    return "When urgent customer notices are delayed or blocked by carrier filters, response gaps turn into retention and compliance risks.";
  }
  return "When a contract approval sits unanswered or a critical document misses the right stakeholder, communication delays quickly become operational risks.";
}

function capabilityPhrase(
  website?: WebsiteIntelligence | null,
  product?: DynamicProductConfiguration,
): string {
  if (product?.scrapedFeatures.length) {
    return product.scrapedFeatures.slice(0, 3).join(", ");
  }
  if (product?.primaryValueProp) return product.primaryValueProp;
  const v = website?.vertical || "generic";
  if (v === "fax") {
    return "secure document delivery, compliant outreach, and reliable business continuity";
  }
  if (v === "email") {
    return "authenticated deliverability, compliant campaigns, and measurable inbox reach";
  }
  if (v === "sms") {
    return "compliant messaging, delivery control, and reliable high-volume outreach";
  }
  return "reliable communication, secure document workflows, and operational continuity";
}

function cleanServiceName(raw: string): string {
  let t = raw.trim();
  // "B2B E-Faxing - Market your service using Faxes" → "B2B e-faxing"
  const dashParts = t.split(/\s[-–—]\s/);
  if (dashParts.length > 1 && looksLikeMarketingSloganDump(t)) {
    t = dashParts[0]!.trim();
  }
  if (t.length > 48) t = t.slice(0, 48).replace(/\s+\S*$/, "").trim();
  return t;
}

function truncateAtWord(text: string, max: number): string {
  const trimmed = text.trim();
  if (trimmed.length <= max) return trimmed;
  const slice = trimmed.slice(0, max);
  const sp = slice.lastIndexOf(" ");
  return (sp > 40 ? slice.slice(0, sp) : slice).trim();
}

function verticalFriction(
  website?: WebsiteIntelligence | null,
  product?: DynamicProductConfiguration,
): {
  channel: string;
  failureMode: string;
  consequence: string;
  modernPath: string;
} {
  if (product) {
    return {
      channel: product.humanFrictionHook,
      failureMode: product.narrativeContrast,
      consequence: "missed opportunities, delayed handoffs, compliance anxiety, and slower growth",
      modernPath: `${product.solutionName}: ${product.primaryValueProp}`,
    };
  }
  const v = website?.vertical || "generic";
  switch (v) {
    case "fax":
      return {
        channel: "crowded email and digital outreach",
        failureMode: "inboxes ignore messages and campaigns lose momentum",
        consequence: "slower replies, missed partner documents, and delayed deal cycles",
        modernPath: "secure digital document exchange when traditional channels are not enough",
      };
    case "email":
      return {
        channel: "high-volume email that lands in spam or gets buried",
        failureMode: "deliverability slips and engagement quietly drops",
        consequence: "lower open rates, wasted list spend, and weaker campaign ROI",
        modernPath: "authenticated, high-deliverability email workflows teams can trust",
      };
    case "sms":
      return {
        channel: "SMS and messaging that feel noisy or poorly timed",
        failureMode: "recipients tune out or carriers block poorly managed traffic",
        consequence: "missed conversions, compliance risk, and rising cost per reply",
        modernPath: "compliant, high-volume messaging with clear delivery control",
      };
    default:
      return {
        channel: "overcrowded digital outreach",
        failureMode: "decision-makers are harder to reach and responses slow down",
        consequence: "fewer qualified conversations, delayed revenue, and weaker pipeline confidence",
        modernPath: "reliable communication and operations workflows that restore everyday control",
      };
  }
}

function serviceDetail(website?: WebsiteIntelligence | null, index = 0): string {
  const service = website?.services?.[index];
  if (service?.detail?.trim() && !looksLikeMarketingSloganDump(service.detail)) {
    return service.detail.trim();
  }
  if (website?.benefits?.[index]?.trim()) return website.benefits[index]!.trim();
  if (website?.description?.trim()) {
    const sentence = website.description.split(/[.!?]/)[index]?.trim();
    if (sentence && !looksLikeMarketingSloganDump(sentence)) return sentence;
  }
  return "";
}

/**
 * Five distinct narrative angles — not the same scraped slogan repeated five times.
 * Titles are human friction themes; details stay grounded in live website/brand data.
 */
function beatAnglesFromSources(
  website: WebsiteIntelligence | null | undefined,
  brand: BrandProfile,
  offering: string,
  product?: DynamicProductConfiguration,
): Array<{ title: string; detail: string }> {
  const friction = verticalFriction(website, product);
  const services = (website?.services ?? [])
    .map((s) => ({
      title: cleanServiceName(s.label || ""),
      detail: s.detail?.trim() || "",
    }))
    .filter((s) => s.title.length >= 3);

  const themes = [
    {
      title: "Crowded outreach channels",
      detail:
        services[0]?.detail ||
        serviceDetail(website, 0) ||
        `Many teams still rely on ${friction.channel}, only to watch ${friction.failureMode}.`,
    },
    {
      title: "Changing buyer habits",
      detail:
        services[1]?.detail ||
        serviceDetail(website, 1) ||
        `Communication preferences, regulations, and platform rules keep shifting — strategies that once worked now stall.`,
    },
    {
      title: "Operational communication gaps",
      detail:
        services[2]?.detail ||
        serviceDetail(website, 2) ||
        `When documents and follow-ups stall, ${friction.consequence}.`,
    },
    {
      title: "Proof before more spend",
      detail:
        website?.benefits?.[0] ||
        services[3]?.detail ||
        `Leaders want proof that a calmer channel will restore response rates before they increase spend.`,
    },
    {
      title: "Sustainable reach",
      detail:
        brand.tagline?.trim() && !looksLikeMarketingSloganDump(brand.tagline)
          ? brand.tagline.trim()
          : `Long-term growth needs a dependable path to decision-makers — not another crowded inbox tactic.`,
    },
  ];

  // Enrich titles with real service names when unique and clean
  return themes.map((theme, i) => {
    const svc = services[i];
    if (svc?.title && svc.title.toLowerCase() !== offering.toLowerCase()) {
      return {
        title: theme.title,
        detail: `${theme.detail} Related capability: ${svc.title}${svc.detail ? ` — ${truncateAtWord(svc.detail, 100)}` : ""}.`,
      };
    }
    return theme;
  });
}

function hashtagsForBeat(
  _angleTitle: string,
  website?: WebsiteIntelligence | null,
  company?: string,
): string {
  // Curated tags only — never split angle titles into weak tags like #Changing / #buyer.
  const companyTag = company ? `#${company.replace(/\s+/g, "")}` : "";
  const core =
    website?.vertical === "fax"
      ? ["#EFax", "#B2BCommunication", "#BusinessCommunication", "#Compliance", "#DigitalTransformation"]
      : website?.vertical === "email"
        ? ["#EmailMarketing", "#B2BCommunication", "#BusinessCommunication", "#DigitalTransformation", "#Compliance"]
        : website?.vertical === "sms"
          ? ["#SMSMarketing", "#B2BCommunication", "#BusinessCommunication", "#DigitalTransformation", "#Compliance"]
          : ["#B2BCommunication", "#BusinessCommunication", "#DigitalTransformation", "#Compliance"];

  const keywordTags = (website?.keywords ?? [])
    .map((k) => k.replace(/\s+/g, ""))
    .filter((k) => k.length >= 4 && k.length <= 24 && !/^(changing|buyer|market|service|best|next)$/i.test(k))
    .slice(0, 2)
    .map((k) => `#${k}`);

  const merged = [...core, companyTag, ...keywordTags].filter(Boolean);
  const seen = new Set<string>();
  const unique: string[] = [];
  for (const tag of merged) {
    const key = tag.toLowerCase();
    if (seen.has(key)) continue;
    seen.add(key);
    unique.push(tag);
  }
  return unique.slice(0, 6).join(" ");
}

/**
 * 10/10 scoring targets:
 * Clarity (why it hurts) → market shift → concrete business cost → natural brand fix.
 * Never paste the same scraped slogan into Problem, Impact, and Brand response.
 */
function buildProblem(
  act: StoryAct,
  company: string,
  industry: string,
  offering: string,
  website: WebsiteIntelligence | null | undefined,
  angle: { title: string; detail: string },
  product?: DynamicProductConfiguration,
): string {
  const friction = verticalFriction(website, product);
  const audiences = audienceIndustries(industry, website);
  const scenario = scenarioLine(website, product);
  void angle;
  void offering;
  void company;

  switch (act) {
    case "challenge":
      return `Teams in ${audiences} still rely on ${friction.channel}, then watch ${friction.failureMode}. Strategies that once reached decision-makers reliably now stall under shifting buyer expectations and tighter compliance pressure.`;
    case "recognition":
      return `The friction is adaptation — not a shortage of tools. Buyer habits and compliance expectations moved; inbox-first playbooks did not. ${scenario}`;
    case "solution":
      return `Leaders in ${audiences} need a practical channel when email and chat are overcrowded. They need ${friction.modernPath} without adding more noise to already-ignored threads.`;
    case "proof":
      return `Before increasing spend, ${audiences} buyers want proof that a quieter path restores response quality. ${scenario}`;
    case "path_forward":
      return `Sustainable growth in ${audiences} assumes ${friction.channel} will stay crowded. Reliability and compliance matter more than another generic campaign slogan.`;
    default:
      return scenario;
  }
}

function buildImpact(
  act: StoryAct,
  company: string,
  industry: string,
  offering: string,
  website: WebsiteIntelligence | null | undefined,
  angle: { title: string; detail: string },
  product?: DynamicProductConfiguration,
): string {
  const friction = verticalFriction(website, product);
  const audiences = audienceIndustries(industry, website);
  const benefit = website?.benefits?.[0]?.trim();
  const capability = capabilityPhrase(website, product);
  void angle;

  switch (act) {
    case "challenge":
      return `The cost shows up as ${friction.consequence}. Pipeline momentum fades, outreach confidence drops, and teams spend more effort for fewer meaningful conversations.`;
    case "recognition":
      return `${audiences} teams feel the hit as missed leads, delayed document handoffs, growing compliance anxiety, and declining trust in outreach strategy. Doing nothing quietly compounds each quarter.`;
    case "solution":
      return `When ${company} backs ${capability}, relief is operational: faster document delivery, cleaner follow-up loops, and less dependence on ignored inboxes${benefit && !looksLikeMarketingSloganDump(benefit) ? ` — ${truncateAtWord(benefit, 90)}` : ""}.`;
    case "proof":
      return `Credible proof looks like restored response rates, fewer stalled handoffs, and leadership confidence that communication spend ties to real outcomes across ${audiences}.`;
    case "path_forward":
      return `Teams that stabilize secure document and partner communication early protect lead flow. Those that wait pay in slower cycles, weaker engagement, and rising uncertainty about what still works.`;
    default:
      return `Without a clearer path, organizations absorb ${friction.consequence}.`;
  }
}

function buildBrandResponse(
  act: StoryAct,
  company: string,
  industry: string,
  offering: string,
  tagline: string,
  website?: WebsiteIntelligence | null,
  product?: DynamicProductConfiguration,
): string {
  const audiences = audienceIndustries(industry, website);
  const capability = capabilityPhrase(website, product);
  const serviceDetail =
    website?.services?.[0]?.detail?.trim() &&
    !looksLikeMarketingSloganDump(website.services[0]!.detail)
      ? truncateAtWord(website.services[0]!.detail, 90)
      : "";
  // Never append slogan taglines (e.g. "Revolutionizing B2B Fax Communication").
  void tagline;
  void offering;

  const concrete =
    serviceDetail ||
    `secure document delivery, compliant communication, and reliable outreach for ${audiences}`;

  switch (act) {
    case "challenge":
    case "recognition":
      return `${company} helps ${audiences} teams keep high-stakes documents moving with ${capability} — a practical channel when traditional inboxes are no longer enough.`;
    case "solution":
      return `${company} supports ${concrete}, so operations keep contracts, claims, and compliance files on schedule without depending on crowded digital channels alone.`;
    case "proof":
      return `${company} gives leadership a measurable alternative: ${capability} that can be evaluated on delivery reliability and operational outcomes, not vanity activity.`;
    case "path_forward":
      return `Build the next chapter with ${company}: use ${capability} to protect business continuity when chat and email cannot carry regulated documents alone.`;
    default:
      return `${company} provides ${capability} for ${audiences}.`;
  }
}

function buildTitle(beatIndex: number, angleTitle: string): string {
  return `Post ${beatIndex + 1} — ${angleTitle}`;
}

function buildSummary(
  scaffold: ReturnType<typeof getNarrativeScaffold>,
  offering: string,
): string {
  // Full sentences only — never mid-word truncation (was producing "tied to t").
  return `${scaffold.phase}: ${truncateAtWord(scaffold.lesson, 110)} Focus: ${offering}.`;
}

function buildEngagementQuestion(
  act: StoryAct,
  company: string,
  industry: string,
  angleTitle: string,
  offering: string,
): string {
  const industryHint = industry || "your";
  const templates: Record<StoryAct, string> = {
    challenge: `Where is crowded outreach hurting ${industryHint} reply rates the most right now?`,
    recognition: `What changed in your market that made the old playbook stop working?`,
    solution: `Would a quieter channel like ${offering} from ${company} help your team reach decision-makers again?`,
    proof: `What proof would convince leadership to diversify beyond inbox-only outreach?`,
    path_forward: `Is your communication plan built for this quarter's noise — or for the next five years?`,
  };
  void angleTitle;
  return templates[act];
}

/**
 * Synthesize a story beat from company URL scrape + brand profile.
 * Targets the 10/10 LinkedIn formula:
 * Real-world observation → Market shift → Business consequence → Brand solution.
 */
export function buildCreativeBriefBeat(input: {
  brand: BrandProfile;
  project: Project;
  beatIndex: number;
  website?: WebsiteIntelligence | null;
}): StoryArcBeat {
  const { brand, project, beatIndex, website } = input;
  const company = companyLabel(brand, project, website);
  const industry = industryLabel(brand, project, website);
  const tagline = taglineLabel(brand, company, website);
  const product = resolveDynamicProductConfig({ brand, project, website });
  const offering = product.solutionName || primaryOffering(website, brand, company);
  const scaffold = getNarrativeScaffold(beatIndex);
  const angles = beatAnglesFromSources(website, brand, offering, product);
  const angle = angles[beatIndex] ?? angles[0]!;
  const act = scaffold.act;
  const services = serviceLabels(website, brand);

  const problem = buildProblem(act, company, industry, offering, website, angle, product);
  const impactLine = buildImpact(act, company, industry, offering, website, angle, product);
  const brandResponse = buildBrandResponse(
    act,
    company,
    industry,
    offering,
    tagline,
    website,
    product,
  );

  const prevAngle = beatIndex > 0 ? angles[beatIndex - 1]?.title : null;
  const nextAngle = beatIndex < angles.length - 1 ? angles[beatIndex + 1]?.title : null;
  const category = resolveContentCategoryForBeat(beatIndex, act);
  const seoKeywords = deriveSeoKeywords({
    website,
    companyName: company,
    industry,
    offering,
  });

  return {
    act: getActLabel(act),
    title: buildTitle(beatIndex, angle.title),
    summary: buildSummary(scaffold, offering),
    tag: getActTag(act),
    bridgeFromPrevious: prevAngle
      ? `Continues from "${prevAngle}" — now focusing on ${angle.title.toLowerCase()}.`
      : "",
    bridgeToNext: nextAngle
      ? `Next: "${nextAngle}" — advancing the campaign from ${company}'s live offer.`
      : "Sequence loops to Post 1 for the next campaign rotation.",
    campaignStory: `${scaffold.lesson} ${company} — ${offering}. ${truncateAtWord(website?.description || tagline, 140)}`,
    background: `${company}${industry ? ` (${industry})` : ""}${website?.url ? ` — ${website.url.replace(/^https?:\/\//i, "")}` : ""}. Services: ${services.slice(0, 3).join(", ") || offering}.`,
    audience: `Decision-makers evaluating ${offering}${industry ? ` in ${industry}` : ""}.`,
    problem,
    causeEventEffect: [
      `Context: ${angle.title}`,
      `Offering: ${offering}`,
      `Phase: ${scaffold.phase}`,
      website?.ok ? `Source: company website scrape` : `Source: brand profile (add website URL for richer context)`,
    ],
    impact: [impactLine],
    brandResponse,
    keyTheme: `${getActTag(act)} · ${angle.title}`,
    engagementQuestion: buildEngagementQuestion(act, company, industry, angle.title, offering),
    hashtags: hashtagsForBeat(angle.title, website, company.replace(/\s+/g, "")),
    contentCategory: category.label,
    seoKeywords: formatSeoKeywordsLine(seoKeywords),
  };
}

/** Build all 5 beats for a project from live website + brand sources. */
export function buildStoryArcFromSources(
  brand: BrandProfile,
  project: Project,
  website?: WebsiteIntelligence | null,
): StoryArcBeat[] {
  return [0, 1, 2, 3, 4].map((index) =>
    buildCreativeBriefBeat({ brand, project, beatIndex: index, website }),
  );
}
