"use client";

import Link from "next/link";
import { FormEvent, useEffect, useRef, useState } from "react";
import { ArrowRight, Check, ChevronRight, LockKeyhole, RotateCcw, ShieldCheck } from "lucide-react";
import type { FormDefinition } from "@/lib/comando";
import { dataLayerExperimentAttribution, leadExperimentAttribution } from "@/lib/experiments";
import { useExperiment } from "@/app/components/Experimentation";

type ConsentCopy = Record<string, { required: boolean; copy: string }>;

type ConsentWindow = Window & {
  dataLayer?: Array<Record<string, unknown>>;
  gtag?: (...args: unknown[]) => void;
};

function storedConsent() {
  try {
    return JSON.parse(localStorage.getItem("comando_consent") || "{}") as { analytics?: boolean; advertising?: boolean; version?: string };
  } catch {
    return {};
  }
}

function publishConsent(mode: "default" | "update", analytics: boolean, advertising: boolean) {
  const globalWindow = window as ConsentWindow;
  const consent = {
    analytics_storage: analytics ? "granted" : "denied",
    ad_storage: advertising ? "granted" : "denied",
    ad_user_data: advertising ? "granted" : "denied",
    ad_personalization: advertising ? "granted" : "denied",
    functionality_storage: "granted",
    security_storage: "granted",
  };
  globalWindow.dataLayer = globalWindow.dataLayer || [];
  globalWindow.dataLayer.push({ event: `consent_mode_${mode}`, ...consent });
  globalWindow.gtag?.("consent", mode, consent);
}

function analyticsConsentGranted() {
  return storedConsent().analytics === true;
}

export function pushAnalyticsEvent(event: Record<string, unknown>) {
  if (!analyticsConsentGranted()) return false;
  const globalWindow = window as ConsentWindow;
  globalWindow.dataLayer = globalWindow.dataLayer || [];
  globalWindow.dataLayer.push(event);
  return true;
}

const segmentByJourney: Record<string, string> = {
  waitlist: "waitlist", masterclass: "event", corporate: "corporate", partner: "partner",
  mentorship: "mentorship", support: "support", vip: "vip",
};

function trackingParams() {
  const query = new URLSearchParams(window.location.search);
  return {
    source: query.get("utm_source") ?? "", medium: query.get("utm_medium") ?? "",
    campaign: query.get("utm_campaign") ?? "", content: query.get("utm_content") ?? "",
    term: query.get("utm_term") ?? "",
  };
}

export function DataLayerBridge({ route }: { route: string }) {
  const { assignment, ready } = useExperiment();
  const emittedKey = useRef("");
  useEffect(() => {
    if (!sessionStorage.getItem("comando_consent_bootstrapped")) {
      const consent = storedConsent();
      publishConsent("default", false, false);
      if (consent.version) publishConsent("update", consent.analytics === true, consent.advertising === true);
      sessionStorage.setItem("comando_consent_bootstrapped", "true");
    }
    const emitPageView = () => {
      if (!ready || !analyticsConsentGranted()) return;
      const attribution = dataLayerExperimentAttribution(assignment);
      const key = `${route}:${attribution.experiment_id}:${attribution.variant}:${attribution.assignment_method}`;
      if (emittedKey.current === key) return;
      pushAnalyticsEvent({ event: "page_view_ready", page_path: route, ...attribution });
      emittedKey.current = key;
    };
    emitPageView();
    window.addEventListener("comando:consent-updated", emitPageView);
    return () => window.removeEventListener("comando:consent-updated", emitPageView);
  }, [assignment, ready, route]);
  return null;
}

export function DynamicLeadForm({ name, definition, consents, preset }: { name: string; definition: FormDefinition; consents: ConsentCopy; preset?: string }) {
  const [state, setState] = useState<"idle" | "sending" | "error">("idle");
  const [error, setError] = useState("");
  const { assignment } = useExperiment();
  const consentKeys = definition.consents || definition.consents_when_email || ["privacy_required"];

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setState("sending"); setError("");
    const form = new FormData(event.currentTarget);
    const details = Object.fromEntries([...form.entries()].filter(([key]) => !key.startsWith("consent_") && key !== "website"));
    const first = String(form.get("first_name") || form.get("name") || "").trim();
    const last = String(form.get("last_name") || "").trim();
    const email = String(form.get("email") || form.get("work_email") || "").trim();
    const phone = String(form.get("mobile") || form.get("phone") || "").trim();
    const body = {
      journey: name,
      fullName: [first, last].filter(Boolean).join(" "), email, phone,
      segment: segmentByJourney[name] || "waitlist",
      role: String(form.get("role") || ""), company: String(form.get("organisation") || ""),
      consentService: form.get("consent_privacy_required") === "on",
      consentEmailMarketing: form.get("consent_email_marketing_optional") === "on",
      consentWhatsapp: form.get("consent_whatsapp_marketing_optional") === "on",
      consentSms: form.get("consent_sms_marketing_optional") === "on",
      website: form.get("website"), sourcePath: window.location.pathname,
      creativeId: new URLSearchParams(window.location.search).get("cid") ?? "",
      utm: trackingParams(), details: { ...details, preset: preset || "" },
      ...leadExperimentAttribution(assignment),
    };
    try {
      const response = await fetch("/api/leads", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });
      const result = (await response.json()) as { error?: string };
      if (!response.ok) throw new Error(result.error || "Não foi possível registar o pedido.");
      pushAnalyticsEvent({ event: "generate_lead", form_name: name, page_path: window.location.pathname, ...dataLayerExperimentAttribution(assignment) });
      window.location.assign(definition.success_route);
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Não foi possível registar o pedido.");
      setState("error");
    }
  }

  return (
    <form className="dynamic-form" onSubmit={submit}>
      <div className="dynamic-form-grid">
        {definition.fields.filter((field) => !["hidden", "radio_matrix"].includes(field.type)).map((field) => {
          const required = field.required === true;
          if (field.type === "textarea") return <label className="wide" key={field.id}><span>{field.label}</span><textarea name={field.id} required={required} maxLength={field.maxlength} rows={5} /></label>;
          if (field.type === "select") return <label key={field.id}><span>{field.label}</span><select name={field.id} required={required} defaultValue=""><option value="" disabled>Selecione</option>{field.options?.map((option) => <option value={option} key={option}>{option}</option>)}</select></label>;
          if (field.type === "radio") return <fieldset className="wide radio-field" key={field.id}><legend>{field.label}</legend>{field.options?.map((option, index) => <label key={option}><input type="radio" name={field.id} value={option} required={required && index === 0} /><span>{option}</span></label>)}</fieldset>;
          const type = ["email", "tel"].includes(field.type) ? field.type : "text";
          return <label key={field.id}><span>{field.label}</span><input name={field.id} type={type} required={required} autoComplete={field.autocomplete} maxLength={field.maxlength} /></label>;
        })}
      </div>
      <div className="hp" aria-hidden="true"><label>Website<input name="website" tabIndex={-1} autoComplete="off" /></label></div>
      <div className="dynamic-consents">
        {consentKeys.map((key) => {
          const consent = consents[key];
          if (!consent) return null;
          return <label key={key}><input type="checkbox" name={`consent_${key}`} required={consent.required} /><span>{consent.copy}</span></label>;
        })}
      </div>
      {error && <p className="form-error" role="alert">{error}</p>}
      <button className="solid-button" disabled={state === "sending"}>{state === "sending" ? "A registar…" : definition.submit_label}<ArrowRight /></button>
      <p className="form-fineprint">O pedido é registado no sistema COMANDO. Nenhum consentimento comercial opcional vem pré-selecionado.</p>
    </form>
  );
}

type DiagnosisConfig = {
  disclaimer: string;
  scale: Record<string, string>;
  questions: Array<{ id: string; dimension: string; copy: string }>;
  results: Record<string, { title: string; summary: string; exercise: string; cta: string; destination: string }>;
};

export function DiagnosisTool({ config }: { config: DiagnosisConfig }) {
  const [answers, setAnswers] = useState<Record<string, number>>({});
  const [error, setError] = useState("");
  const { assignment } = useExperiment();
  function calculate() {
    if (Object.keys(answers).length !== config.questions.length) { setError("Responda às 12 afirmações para calcular o seu foco sugerido."); return; }
    const totals: Record<string, number> = {};
    config.questions.forEach((question) => { totals[question.dimension] = (totals[question.dimension] || 0) + answers[question.id]; });
    const ordered = Object.entries(totals).sort((a, b) => a[1] - b[1]);
    const focus = ordered[0][0]; const strength = ordered[ordered.length - 1][0];
    sessionStorage.setItem("comando_diagnosis", JSON.stringify({ focus, strength, calculatedAt: new Date().toISOString() }));
    pushAnalyticsEvent({ event: "diagnosis_completed", page_path: window.location.pathname, ...dataLayerExperimentAttribution(assignment) });
    window.location.assign(`/diagnostico/resultado?foco=${encodeURIComponent(focus)}&recurso=${encodeURIComponent(strength)}`);
  }
  return (
    <div className="diagnosis-tool">
      <p className="diagnosis-disclaimer"><ShieldCheck />{config.disclaimer}</p>
      {config.questions.map((question, index) => <fieldset className="diagnosis-question" key={question.id}><legend><span>{String(index + 1).padStart(2, "0")}</span>{question.copy}</legend><div>{Object.entries(config.scale).map(([value, label]) => <label key={value} title={label}><input type="radio" name={question.id} value={value} checked={answers[question.id] === Number(value)} onChange={() => setAnswers((current) => ({ ...current, [question.id]: Number(value) }))} /><span>{value}<small>{label}</small></span></label>)}</div></fieldset>)}
      {error && <p className="form-error" role="alert">{error}</p>}
      <button type="button" className="solid-button" onClick={calculate}>Ver o meu foco sugerido <ArrowRight /></button>
      <p className="form-fineprint">O cálculo é feito neste dispositivo. As respostas não são enviadas nem guardadas no servidor.</p>
    </div>
  );
}

export function DiagnosisResult({ config, focus, strength }: { config: DiagnosisConfig; focus?: string; strength?: string }) {
  const [localResult] = useState<{ focus?: string; strength?: string }>(() => {
    if (focus) return { focus, strength };
    if (typeof window === "undefined") return {};
    try { return JSON.parse(sessionStorage.getItem("comando_diagnosis") || "{}"); } catch { return {}; }
  });
  const result = localResult.focus ? config.results[localResult.focus] : undefined;
  const resource = localResult.strength ? config.results[localResult.strength] : undefined;
  if (!result) return <div className="result-empty"><RotateCcw /><h3>O resultado não está disponível neste dispositivo.</h3><p>Faça novamente o Mapa de Comando. As respostas não ficam guardadas no servidor.</p><Link className="solid-button" href="/diagnostico">Refazer o mapa <ArrowRight /></Link></div>;
  return <div className="result-panel"><p className="result-label">Foco sugerido</p><h3>{result.title}</h3><p>{result.summary}</p><div className="result-exercise"><b>Exercício imediato</b><p>{result.exercise}</p></div>{resource && <p className="strength-note"><b>Recurso percebido:</b> {resource.title.replace("O seu primeiro movimento: ", "")}</p>}<Link className="solid-button" href={result.destination}>{result.cta}<ArrowRight /></Link></div>;
}

export function CookiePreferences() {
  const [saved, setSaved] = useState(false);
  const [analytics, setAnalytics] = useState(() => { if (typeof window === "undefined") return false; try { return JSON.parse(localStorage.getItem("comando_consent") || "{}").analytics === true; } catch { return false; } });
  const [advertising, setAdvertising] = useState(() => { if (typeof window === "undefined") return false; try { return JSON.parse(localStorage.getItem("comando_consent") || "{}").advertising === true; } catch { return false; } });
  function save() {
    localStorage.setItem("comando_consent", JSON.stringify({ essential: true, analytics, advertising, version: "2026-08-31.v1", savedAt: new Date().toISOString() }));
    publishConsent("update", analytics, advertising);
    window.dispatchEvent(new CustomEvent("comando:consent-updated", { detail: { analytics, advertising } }));
    setSaved(true);
  }
  return <div className="cookie-panel"><label><input type="checkbox" checked disabled /><span><b>Essenciais</b><small>Sessão, segurança e preferências pedidas.</small></span></label><label><input type="checkbox" checked={analytics} onChange={(event) => setAnalytics(event.target.checked)} /><span><b>Medição</b><small>Ajuda a compreender o uso quando houver ferramentas configuradas.</small></span></label><label><input type="checkbox" checked={advertising} onChange={(event) => setAdvertising(event.target.checked)} /><span><b>Publicidade</b><small>Permite medir campanhas e limitar repetição quando houver plataformas ativas.</small></span></label><button className="solid-button" type="button" onClick={save}>{saved ? <><Check /> Preferências guardadas</> : <>Guardar preferências <ArrowRight /></>}</button></div>;
}

type PaymentResult = {
  status: "paid";
  reference: string;
  ticketTier: string;
  amountTotal: number;
  currency: string;
  email?: string | null;
};

export function PaymentConfirmation({ sessionId }: { sessionId?: string }) {
  const [state, setState] = useState<"verifying" | "processing" | "paid" | "error">(sessionId ? "verifying" : "error");
  const [result, setResult] = useState<PaymentResult | null>(null);
  const [message, setMessage] = useState(sessionId ? "" : "A ligação não contém uma referência de pagamento válida.");

  useEffect(() => {
    if (!sessionId) return;
    let cancelled = false;
    let timer: ReturnType<typeof setTimeout> | undefined;
    async function verify(attempt: number) {
      try {
        const response = await fetch(`/api/checkout/status?session_id=${encodeURIComponent(sessionId!)}`, { headers: { accept: "application/json" } });
        const payload = (await response.json()) as PaymentResult & { error?: string; status?: "paid" | "processing" };
        if (cancelled) return;
        if (response.status === 202 && attempt < 3) {
          setState("processing");
          timer = setTimeout(() => void verify(attempt + 1), 1800);
          return;
        }
        if (!response.ok || payload.status !== "paid") throw new Error(payload.error || "O pagamento ainda não foi confirmado.");
        setResult(payload);
        setState("paid");
      } catch (error) {
        if (cancelled) return;
        setMessage(error instanceof Error ? error.message : "Não foi possível confirmar o pagamento.");
        setState("error");
      }
    }
    void verify(0);
    return () => { cancelled = true; if (timer) clearTimeout(timer); };
  }, [sessionId]);

  if (state === "paid" && result) {
    const price = new Intl.NumberFormat("pt-PT", { style: "currency", currency: result.currency.toUpperCase() }).format(result.amountTotal / 100);
    return <div className="state-card payment-confirmation success"><Check /><span>Pagamento confirmado</span><h1>A sua compra foi reconciliada.</h1><p>Bilhete <b>{result.ticketTier}</b> · {price}. Referência: <code>{result.reference}</code>.</p>{result.email && <small>A informação de acesso será enviada para {result.email} depois de a edição e o hub estarem operacionais.</small>}<Link className="solid-button" href="/contactos-acessibilidade">Apoio ao participante <ArrowRight /></Link></div>;
  }
  return <div className="state-card payment-confirmation"><LockKeyhole /><span>{state === "error" ? "Confirmação não concluída" : "A verificar pagamento"}</span><h1>{state === "error" ? "Não emitimos um bilhete sem validação." : "Aguarde enquanto conciliamos a sessão."}</h1><p>{state === "error" ? message : "A página consulta o pagamento e o registo server-side. Atualizar ou visitar esta rota, por si só, nunca cria uma compra."}</p>{state === "error" && <Link className="solid-button" href="/contactos-acessibilidade">Pedir apoio <ArrowRight /></Link>}</div>;
}

export function CommerceGate({ mode = "checkout" }: { mode?: "checkout" | "tickets" | "referral" | "recovery" }) {
  const copy = mode === "tickets" ? "Os níveis estão estruturados, mas preços, benefícios, inventário e lotes só serão publicados depois de validação comercial, fiscal, jurídica e operacional." : mode === "referral" ? "Não existe uma oferta de recomendação ativa neste momento." : mode === "recovery" ? "A recuperação só funciona para uma sessão de checkout real e assinada. Nenhuma sessão válida foi apresentada." : "A venda ainda não está aberta. O checkout permanece tecnicamente fechado até entidade, datas, recinto, preços, impostos, termos e webhook de pagamento estarem verificados.";
  return <div className="commerce-gate"><LockKeyhole /><div><b>{mode === "tickets" ? "Oferta em validação" : "Acesso protegido"}</b><p>{copy}</p><Link href="/?origem=comercio#lista">Receber a abertura oficial <ChevronRight /></Link></div></div>;
}

export function ProtectedHub({ modules }: { modules: Array<{ id: string; title: string; copy: string }> }) {
  return <div className="protected-hub"><div className="protected-intro"><LockKeyhole /><div><p>Acesso verificado</p><h2>O hub só abre com um bilhete confirmado.</h2><span>Nenhum dado pessoal, QR ou benefício é exposto sem sessão autenticada.</span></div></div><div className="hub-modules">{modules.map((module) => <article key={module.id}><span>{module.id}</span><h3>{module.title}</h3><p>{module.copy}</p></article>)}</div></div>;
}

export function TicketLevels({ tiers }: { tiers: Array<{ id: string; label: string; draft_inclusions: string[] }> }) {
  return <div><div className="ticket-levels">{tiers.map((tier, index) => <article key={tier.id}><span>0{index + 1}</span><h3>{tier.label}</h3><p>Condições em validação</p><ul>{tier.draft_inclusions.slice(0, 2).map((item) => <li key={item}>{item}</li>)}</ul></article>)}</div><CommerceGate mode="tickets" /></div>;
}
