'use client';

import { useEffect, useMemo, useState } from 'react';
import { Check, Copy, ExternalLink, LineChart, Linkedin, Send, Sparkles, X } from 'lucide-react';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/Dialog';
import { Button } from '@/components/ui/Button';
import { useCsrf } from '@/hooks/useCsrf';
import { useTranslation } from '@/hooks/useTranslation';
import { showToast } from '@/components/ui/Toast';

type Card = { language: 'en' | 'de'; qrTitle: string; label: string; title: string; totalScans?: number; totalUniqueScans: number; milestoneThreshold: number; trend: { points: Array<{ at: string; total: number }>; startLabel: string; endLabel: string; target: number; ceiling: number } | null };
type Milestone = { id: string; qrTitle: string; threshold: number; defaultXHandle: string | null; preview: string; shareUrl: string; language: 'en' | 'de'; card: Card; brandStatus: string; brandPostUrl: string | null; brandPostError: string | null };
type BrandState = { brandStatus: string; brandPostUrl: string | null; brandPostError: string | null; selfSharedAt: string | null };

function Trend({ trend, locale }: { trend: NonNullable<Card['trend']>; locale: 'en' | 'de' }) {
  const ceiling = trend.target <= 5 ? 5 : trend.target * 1.25;
  const ticks = trend.target <= 5
    ? [1, 2, 3, 4, 5]
    : Array.from({ length: 5 }, (_, index) => trend.target * (index + 1) / 4);
  const first = new Date(trend.points[0].at).getTime();
  const last = Math.max(new Date(trend.points[trend.points.length - 1].at).getTime(), first + 1);
  const points = trend.points.map(point => {
    const x = 60 + ((new Date(point.at).getTime() - first) / (last - first)) * 410;
    const y = 142 - (point.total / ceiling) * 126;
    return `${x},${y}`;
  }).join(' ');
  const targetY = 142 - (trend.target / ceiling) * 126;
  const number = new Intl.NumberFormat(locale === 'de' ? 'de-DE' : 'en-US', { maximumFractionDigits: 2 });
  return <svg viewBox="0 0 480 184" className="w-full" role="img" aria-label="Cumulative unique scan trend">
    {ticks.map(tick => {
      const y = 142 - (tick / ceiling) * 126;
      return <g key={tick}><text x="48" y={y + 4} textAnchor="end" fontSize="11" fontWeight={tick === trend.target ? 700 : 500} fill={tick === trend.target ? '#0256ff' : '#64748b'}>{number.format(tick)}</text><line x1="60" x2="470" y1={y} y2={y} stroke={tick === trend.target ? '#bfdbfe' : '#e2e8f0'} strokeWidth={tick === trend.target ? 1.6 : 1} /></g>;
    })}
    <polyline points={points} fill="none" stroke="#0256ff" strokeWidth="3.5" strokeLinejoin="round" strokeLinecap="round" />
    <circle cx="470" cy={targetY} r="4.5" fill="#ffffff" stroke="#0256ff" strokeWidth="3" />
    <text x="60" y="176" fontSize="11" fontWeight="600" fill="#45617f">{trend.startLabel}</text>
    <text x="470" y="176" textAnchor="end" fontSize="11" fontWeight="600" fill="#45617f">{trend.endLabel}</text>
  </svg>;
}

async function copyShareText(text: string) {
  try {
    await navigator.clipboard.writeText(text);
    return;
  } catch {
    const textarea = document.createElement('textarea');
    textarea.value = text;
    textarea.style.position = 'fixed';
    textarea.style.opacity = '0';
    document.body.appendChild(textarea);
    textarea.focus();
    textarea.select();
    const copied = document.execCommand('copy');
    textarea.remove();
    if (!copied) throw new Error('Copying is blocked by this browser');
  }
}

export function SocialMilestoneDialog() {
  const { fetchWithCsrf } = useCsrf();
  const { locale } = useTranslation();
  const [milestone, setMilestone] = useState<Milestone | null>(null);
  const [withName, setWithName] = useState(false);
  const [xHandle, setXHandle] = useState('');
  const [saving, setSaving] = useState<'brand' | 'self' | 'copy' | null>(null);
  const [brand, setBrand] = useState<BrandState | null>(null);

  useEffect(() => {
    fetch(`/api/social-milestones?locale=${locale}`).then(async response => {
      if (response.ok) {
        const next = (await response.json()).milestone as Milestone | null;
        setMilestone(next);
        if (next) setBrand({ brandStatus: next.brandStatus, brandPostUrl: next.brandPostUrl, brandPostError: next.brandPostError, selfSharedAt: null });
      }
    }).catch(() => undefined);
  }, [locale]);
  useEffect(() => setXHandle(milestone?.defaultXHandle || ''), [milestone]);
  useEffect(() => {
    if (!milestone || !['approved', 'processing'].includes(brand?.brandStatus || '')) return;
    const poll = async () => {
      const response = await fetch(`/api/social-milestones/${milestone.id}`);
      if (response.ok) setBrand((await response.json()).milestone);
    };
    const timer = window.setInterval(poll, 3000);
    void poll();
    return () => window.clearInterval(timer);
  }, [milestone, brand?.brandStatus]);

  const copy = milestone?.language === 'de'
    ? { heading: 'Ein echter Erfolg', subtitle: 'hat einen Scan-Meilenstein erreicht.', consent: 'Darf QR Master diesen Erfolg auf dem eigenen X-Account veröffentlichen?', name: 'Meinen X-Handle nennen', decline: 'Nicht jetzt', self: 'Selbst teilen', approve: 'Auf QR Master posten', queued: 'Wird auf X veröffentlicht …', posted: 'Auf X veröffentlicht', failed: 'Veröffentlichung fehlgeschlagen' }
    : { heading: 'A real milestone', subtitle: 'just reached a scan milestone.', consent: 'May QR Master publish this success from our X account?', name: 'Mention my X handle', decline: 'Not now', self: 'Share myself', approve: 'Post from QR Master', queued: 'Waiting for the X publisher …', posted: 'Published on X', failed: 'Publishing failed' };
  const postCopy = useMemo(() => {
    if (!milestone || !withName || !xHandle.trim()) return milestone?.preview || '';
    const mention = milestone.language === 'de' ? 'Glückwunsch' : 'Congratulations';
    return `${milestone.preview}\n\n${mention} @${xHandle.trim().replace(/^@/, '')}.`;
  }, [milestone, withName, xHandle]);
  const preview = milestone ? `${postCopy}\n\n${milestone.shareUrl}` : '';
  const update = async (action: 'approve_brand' | 'self_share' | 'decline' | 'opt_out') => {
    if (!milestone) return null;
    const response = await fetchWithCsrf(`/api/social-milestones/${milestone.id}`, { method: 'PATCH', body: JSON.stringify({ action, withName, xHandle, language: milestone.language }) });
    const result = await response.json();
    if (!response.ok) throw new Error(result.error || 'Could not save your choice');
    return result;
  };
  const prepareSelfShare = async () => {
    const result = await update('self_share');
    const shareUrl = `${result.shareUrl}?v=${result.shareVersion}`;
    setBrand(result.milestone);
    return { shareUrl, text: `${postCopy}\n\n${shareUrl}` };
  };
  const shareSelf = async (network: 'x' | 'linkedin') => {
    if (!milestone) return;
    // LinkedIn's public share dialog accepts only a URL. Start copying the
    // prepared commentary while this click still owns browser focus, then
    // open the LinkedIn share dialog after public-share consent is persisted.
    const linkedinCopy = network === 'linkedin'
      ? copyShareText(postCopy).then(() => true).catch(() => false)
      : Promise.resolve(true);
    // Open synchronously from the user gesture. Awaiting the API first can make
    // LinkedIn treat the new window as a blocked popup.
    const shareWindow = window.open('about:blank', '_blank');
    if (shareWindow) shareWindow.opener = null;
    setSaving('self');
    try {
      const { shareUrl, text } = await prepareSelfShare();
      const copied = await linkedinCopy;
      const targetUrl = network === 'x'
        ? `https://x.com/intent/post?text=${encodeURIComponent(text)}`
        : `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(shareUrl)}`;
      if (shareWindow) shareWindow.location.href = targetUrl;
      else window.location.assign(targetUrl);
      showToast(network === 'linkedin'
        ? copied
          ? (milestone.language === 'de' ? 'LinkedIn-Text kopiert. Jetzt nur noch einfügen.' : 'LinkedIn text copied. Paste it into the composer.')
          : (milestone.language === 'de' ? 'LinkedIn ist geöffnet. Bitte nutze „Text kopieren“ im QR-Master-Fenster.' : 'LinkedIn is open. Please use “Copy text” in the QR Master window.')
        : 'X share composer opened.', copied ? 'success' : 'error');
    } catch (error) { shareWindow?.close(); showToast(error instanceof Error ? error.message : 'Could not prepare this share', 'error'); }
    finally { setSaving(null); }
  };
  const copyLinkedInText = async () => {
    setSaving('copy');
    try {
      const { text } = await prepareSelfShare();
      await copyShareText(text);
      showToast(milestone?.language === 'de' ? 'LinkedIn-Text kopiert.' : 'LinkedIn post text copied.', 'success');
    } catch (error) {
      showToast(error instanceof Error ? error.message : 'Could not copy the LinkedIn text', 'error');
    } finally { setSaving(null); }
  };
  const approveBrand = async () => {
    setSaving('brand');
    try {
      const result = await update('approve_brand');
      setBrand(result.milestone);
      showToast(copy.queued, 'success');
    } catch (error) { showToast(error instanceof Error ? error.message : 'Could not save your choice', 'error'); }
    finally { setSaving(null); }
  };
  const dismiss = async (action: 'decline' | 'opt_out') => {
    try { await update(action); setMilestone(null); } catch (error) { showToast(error instanceof Error ? error.message : 'Could not save your choice', 'error'); }
  };
  const optOut = () => {
    const message = milestone?.language === 'de'
      ? 'Meilenstein-Hinweise dauerhaft ausblenden? Du kannst sie später in den Einstellungen wieder aktivieren.'
      : 'Turn off milestone prompts? You can enable them again later in Settings.';
    if (window.confirm(message)) void dismiss('opt_out');
  };

  if (!milestone) return null;
  const card = milestone.card;
  const count = card.totalUniqueScans || milestone.threshold;
  const status = brand?.brandStatus || milestone.brandStatus || 'pending';
  const canApprove = ['pending', 'failed', 'revoked'].includes(status);
  return <Dialog open onOpenChange={open => !open && setMilestone(null)}>
    <DialogContent className="flex max-h-[calc(100dvh-2rem)] max-w-2xl flex-col overflow-hidden border-slate-200 p-0 shadow-[0_30px_45px_-30px_rgba(50,50,93,0.45)]">
      <div className="shrink-0 px-6 pb-4 pt-5"><DialogHeader><div className="mb-3 flex h-9 w-9 items-center justify-center rounded-lg bg-[#eaf1ff] text-[#0256ff]"><Sparkles className="h-4 w-4" /></div><DialogTitle className="text-2xl font-semibold tracking-[-0.03em] text-[#061b31]">{copy.heading}</DialogTitle><DialogDescription className="pt-1 text-sm leading-6 text-[#4b5e76]"><strong className="font-medium text-[#061b31]">{milestone.qrTitle}</strong> {copy.subtitle}</DialogDescription></DialogHeader></div>
      <div className="min-h-0 space-y-4 overflow-y-auto border-y border-slate-100 px-6 py-5 overscroll-contain">
        <section className="rounded-xl border border-slate-200 bg-white p-5 shadow-[0_14px_28px_-22px_rgba(50,50,93,0.4)]">
          <div className="flex items-center justify-between border-b border-slate-100 pb-4 text-xs"><span className="flex items-center gap-2 font-semibold tracking-wide text-[#061b31]"><img src="/favicon.ico" alt="" className="h-5 w-5" />QR MASTER</span><span className="rounded bg-emerald-50 px-2 py-1 font-medium text-emerald-700"><Check className="mr-1 inline h-3 w-3" />Verified scan milestone</span></div>
          <div className="mt-5 flex items-end justify-between gap-6"><div><div className="text-[10px] font-semibold tracking-[0.1em] text-slate-400">UNIQUE SCANS</div><div className="mt-1 text-5xl font-normal tracking-[-0.04em] tabular-nums text-[#061b31]">{count.toLocaleString(milestone.language === 'de' ? 'de-DE' : 'en-US')}</div></div><div className="pb-1 text-right"><div className="text-[10px] font-semibold tracking-[0.1em] text-slate-400">{milestone.language === 'de' ? 'SCANS INSGESAMT' : 'TOTAL SCANS'}</div><div className="mt-1 text-2xl font-normal tabular-nums text-[#061b31]">{(card.totalScans || count).toLocaleString(milestone.language === 'de' ? 'de-DE' : 'en-US')}</div></div></div>
          <div className="mt-4 border-t border-slate-100 pt-4">{card.trend ? <Trend trend={card.trend} locale={milestone.language} /> : <div className="py-8 text-center text-xs text-[#45617f]">{milestone.language === 'de' ? 'Noch keine Verlaufskurve verfügbar.' : 'No scan timeline available yet.'}</div>}</div>
          {card.trend && <div className="mt-3 flex items-center justify-end gap-2 text-[11px] text-[#45617f]"><LineChart className="h-3.5 w-3.5 text-[#0256ff]" />{milestone.language === 'de' ? 'Kumulierte eindeutige Scans' : 'Cumulative unique scans'}</div>}
          <div className="mt-5 border-t border-slate-100 pt-3 text-sm font-medium text-[#061b31]">{card.qrTitle}</div>
        </section>
        <div><p className="text-sm leading-6 text-[#4b5e76]">{copy.consent}</p><blockquote className="mt-3 whitespace-pre-line border-l border-[#0256ff] pl-3 text-sm leading-6 text-[#273951]">{preview}</blockquote></div>
        <label className="flex cursor-pointer items-center gap-3 text-sm font-medium text-slate-700"><input type="checkbox" checked={withName} onChange={event => setWithName(event.target.checked)} disabled={saving !== null} className="h-4 w-4 rounded border-slate-300 text-[#0256ff] focus:ring-[#0256ff]" />{copy.name}</label>
        {withName && <input aria-label="X handle" value={xHandle} onChange={event => setXHandle(event.target.value)} disabled={saving !== null} maxLength={16} pattern="@?[A-Za-z0-9_]{1,15}" placeholder="@yourhandle" className="w-full rounded-md border border-slate-200 px-3 py-2 text-sm outline-none focus:border-[#0256ff] focus:ring-2 focus:ring-blue-100" />}
        <div className="space-y-2"><div className="flex flex-wrap items-center gap-2"><span className="mr-1 text-xs font-medium text-slate-500">{copy.self}</span><Button variant="outline" size="sm" onClick={() => shareSelf('x')} disabled={saving !== null}><X className="mr-1.5 h-3.5 w-3.5" />X</Button><Button variant="outline" size="sm" onClick={copyLinkedInText} disabled={saving !== null}><Copy className="mr-1.5 h-3.5 w-3.5" />{milestone.language === 'de' ? 'Text kopieren' : 'Copy text'}</Button><Button variant="outline" size="sm" onClick={() => shareSelf('linkedin')} disabled={saving !== null}><Linkedin className="mr-1.5 h-3.5 w-3.5" />{milestone.language === 'de' ? 'Kopieren & LinkedIn öffnen' : 'Copy & open LinkedIn'}</Button></div><p className="text-[11px] leading-4 text-slate-500">{milestone.language === 'de' ? 'LinkedIn erlaubt kein automatisches Text-Vorausfüllen. Der Button kopiert den fertigen Text und öffnet den Beitrag.' : 'LinkedIn does not allow text prefill. The button copies the finished text and opens the composer.'}</p></div>
        {status !== 'pending' && <div className={`flex items-start justify-between gap-3 rounded-md px-3 py-2 text-sm ${status === 'posted' ? 'bg-emerald-50 text-emerald-800' : status === 'failed' ? 'bg-rose-50 text-rose-800' : 'bg-blue-50 text-blue-800'}`}><span>{status === 'posted' ? copy.posted : status === 'failed' ? `${copy.failed}${brand?.brandPostError ? `: ${brand.brandPostError}` : ''}` : copy.queued}</span>{brand?.brandPostUrl && <a href={brand.brandPostUrl} target="_blank" rel="noreferrer" className="inline-flex shrink-0 items-center gap-1 font-medium underline"><ExternalLink className="h-3.5 w-3.5" />View</a>}</div>}
      </div>
      <DialogFooter className="shrink-0 bg-slate-50 px-6 py-4"><div className="flex w-full flex-wrap items-center justify-end gap-2"><Button variant="outline" onClick={() => status === 'pending' ? dismiss('decline') : setMilestone(null)} disabled={saving !== null}>{copy.decline}</Button><Button variant="primary" onClick={approveBrand} disabled={saving !== null || !canApprove}><Send className="mr-1.5 h-4 w-4" />{status === 'approved' || status === 'processing' ? copy.queued : status === 'failed' ? (milestone.language === 'de' ? 'Erneut versuchen' : 'Retry post') : copy.approve}</Button>{status === 'pending' && <button type="button" className="w-full pt-1 text-xs text-slate-500 underline underline-offset-2 hover:text-slate-700" onClick={optOut} disabled={saving !== null}>{milestone.language === 'de' ? 'Nicht mehr anzeigen' : 'Do not show again'}</button>}</div></DialogFooter>
    </DialogContent>
  </Dialog>;
}
