'use client';

import { useEffect, useState, useCallback, useRef } from 'react';
import { useParams } from 'next/navigation';
import Link from 'next/link';
import {
  ArrowLeft, Loader2, Mail, MessageCircle,
  Clock, AlertTriangle, Layers, RefreshCw, BarChart2,
  Download, ChevronLeft, ChevronRight,
} from 'lucide-react';
import FeatureGuard from '@client/components/FeatureGuard';
import { usePageHeader } from '@client/contexts/PageHeaderContext';
import { useLanguage } from '@client/contexts/LanguageContext';
import { toast } from 'sonner';
import {
  getCampaign, getCampaignReport, listCampaignDeliveries, exportCampaignDeliveriesCsv,
  type Campaign, type CampaignReport, type ListDeliveriesResult,
} from '@client/api/marketing';
import {
  listWhatsAppTemplates,
  type WhatsAppTemplate,
} from '@client/api/whatsapp-templates';
import { WhatsAppTemplateBubble } from '@client/components/marketing/WhatsAppTemplateBubble';

const DELIVERY_PAGE_SIZE = 50;

const POLL_INTERVAL_MS = 6000;

const STATUS_BADGE: Record<Campaign['status'], string> = {
  draft: 'bg-gray-100 text-gray-700',
  scheduled: 'bg-blue-100 text-blue-700',
  sending: 'bg-amber-100 text-amber-700',
  completed: 'bg-emerald-100 text-emerald-700',
  cancelled: 'bg-gray-100 text-gray-500',
  failed: 'bg-red-100 text-red-700',
};

function StatusBadge({ status }: { status: Campaign['status'] }) {
  return (
    <span className={`text-xs px-2 py-0.5 rounded-full font-medium ${STATUS_BADGE[status]}`}>
      {status}
    </span>
  );
}

function ChannelIcon({ channel }: { channel: 'email' | 'whatsapp' }) {
  return channel === 'email' ? <Mail size={16} /> : <MessageCircle size={16} />;
}

function fmtDate(iso: string | null) {
  if (!iso) return '—';
  try { return new Date(iso).toLocaleString(); } catch { return '—'; }
}

interface ProgressBarProps {
  sent: number;
  failed: number;
  total: number;
  status: Campaign['status'];
}

function ProgressBar({ sent, failed, total, status }: ProgressBarProps) {
  const safeTotal = total > 0 ? total : 1;
  const sentPct = Math.min(100, (sent / safeTotal) * 100);
  const failedPct = Math.min(100 - sentPct, (failed / safeTotal) * 100);
  const isActive = status === 'sending';

  return (
    <div className="space-y-1.5">
      <div className="flex justify-between text-xs text-gray-500">
        <span>{sent.toLocaleString()} / {total.toLocaleString()} sent</span>
        <span>{sentPct.toFixed(1)}%</span>
      </div>
      <div className="h-3 bg-gray-100 rounded-full overflow-hidden flex">
        <div
          className={`h-full rounded-full transition-all duration-700 ${isActive ? 'bg-amber-400' : 'bg-emerald-500'}`}
          style={{ width: `${sentPct}%` }}
        />
        {failedPct > 0 && (
          <div
            className="h-full bg-red-400 transition-all duration-700"
            style={{ width: `${failedPct}%` }}
          />
        )}
      </div>
      {isActive && (
        <p className="text-xs text-amber-700 flex items-center gap-1">
          <Loader2 size={11} className="animate-spin" /> Sending in progress — updating automatically…
        </p>
      )}
    </div>
  );
}

function StatCard({ label, value, color }: { label: string; value: number; color?: string }) {
  return (
    <div className="bg-gray-50 rounded-lg p-4 text-center">
      <div className={`text-2xl font-bold ${color ?? 'text-gray-800'}`}>{value.toLocaleString()}</div>
      <div className="text-xs text-gray-500 mt-0.5">{label}</div>
    </div>
  );
}

function FailedSkippedTab({
  campaignId,
  t,
}: {
  campaignId: string;
  t: (key: string, fallback?: string) => string;
}) {
  const [data, setData] = useState<ListDeliveriesResult | null>(null);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);

  useEffect(() => {
    let alive = true;
    setLoading(true);
    listCampaignDeliveries(campaignId, { page, pageSize: DELIVERY_PAGE_SIZE })
      .then((r) => { if (alive) setData(r); })
      .catch((e) => {
        if (alive) toast.error(e instanceof Error ? e.message : t('marketing.report.failedLoad', 'Failed to load deliveries'));
      })
      .finally(() => { if (alive) setLoading(false); });
    return () => { alive = false; };
  }, [campaignId, page, t]);

  const totalPages = data ? Math.max(1, Math.ceil(data.total / DELIVERY_PAGE_SIZE)) : 1;

  return (
    <div className="p-4 space-y-3">
      <div className="flex items-center justify-between gap-2">
        <p className="text-xs text-gray-500">
          {t('marketing.report.failedHint',
            'Permanent failures (bad address, auth error, opted out) are shown in amber. Transient failures that exhausted retries are shown in red.')}
        </p>
        <button
          className="btn-ghost text-xs flex items-center gap-1.5 shrink-0"
          onClick={() => exportCampaignDeliveriesCsv(campaignId)}
        >
          <Download size={13} />
          {t('marketing.report.exportCsv', 'Export CSV')}
        </button>
      </div>

      {loading ? (
        <div className="text-center py-8"><Loader2 size={18} className="inline animate-spin text-gray-400" /></div>
      ) : !data || data.items.length === 0 ? (
        <div className="text-center py-10 text-sm text-gray-500">
          {t('marketing.report.noFailures', 'No failed or skipped deliveries.')}
        </div>
      ) : (
        <>
          <div className="border rounded divide-y overflow-hidden">
            <div className="grid grid-cols-[1fr_auto_auto] gap-x-3 px-4 py-2 bg-gray-50 text-xs font-medium text-gray-600">
              <span>{t('marketing.report.colRecipient', 'Recipient')}</span>
              <span>{t('marketing.report.colStatus', 'Status')}</span>
              <span className="text-right">{t('marketing.report.colAttempts', 'Tries')}</span>
            </div>
            {data.items.map((item) => (
              <div key={item.id} className="px-4 py-2.5 space-y-0.5">
                <div className="grid grid-cols-[1fr_auto_auto] gap-x-3 items-center">
                  <span className="truncate font-mono text-xs text-gray-800">{item.recipient}</span>
                  <span className={`text-xs px-2 py-0.5 rounded-full font-medium whitespace-nowrap ${
                    item.status === 'skipped'
                      ? 'bg-amber-100 text-amber-800'
                      : 'bg-red-100 text-red-700'
                  }`}>
                    {item.status === 'skipped'
                      ? t('marketing.report.statusPermanent', 'permanent')
                      : t('marketing.report.statusFailed', 'failed')}
                  </span>
                  <span className="text-xs text-gray-500 text-right">{item.attempts}</span>
                </div>
                {item.last_error && (
                  <p className="text-xs text-gray-500 truncate" title={item.last_error}>
                    {item.last_error}
                  </p>
                )}
              </div>
            ))}
          </div>

          <div className="flex items-center justify-between text-xs text-gray-500 pt-1">
            <span>
              {t('marketing.report.showing', 'Showing')}{' '}
              {(page - 1) * DELIVERY_PAGE_SIZE + 1}–{Math.min(page * DELIVERY_PAGE_SIZE, data.total)}{' '}
              {t('marketing.report.of', 'of')} {data.total}
            </span>
            <div className="flex items-center gap-1">
              <button
                className="p-1 hover:bg-gray-100 rounded disabled:opacity-40"
                disabled={page <= 1}
                onClick={() => setPage((p) => p - 1)}
                aria-label={t('common.previous', 'Previous')}
              >
                <ChevronLeft size={14} />
              </button>
              <span>{page} / {totalPages}</span>
              <button
                className="p-1 hover:bg-gray-100 rounded disabled:opacity-40"
                disabled={page >= totalPages}
                onClick={() => setPage((p) => p + 1)}
                aria-label={t('common.next', 'Next')}
              >
                <ChevronRight size={14} />
              </button>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

function CampaignDetailInner() {
  const { t } = useLanguage();
  usePageHeader(
    t('marketing.campaign.detailTitle', 'Campaign Detail'),
    t('marketing.campaign.detailSubtitle', 'Live send progress and delivery report'),
  );

  const params = useParams();
  const id = params?.id as string;

  const [campaign, setCampaign] = useState<Campaign | null>(null);
  const [report, setReport] = useState<CampaignReport | null>(null);
  const [loading, setLoading] = useState(true);
  const [reportLoading, setReportLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [activeTab, setActiveTab] = useState<'recent' | 'failures'>('recent');
  const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);

  // waTemplate === null  → not yet fetched
  // waTemplate === false → fetched but not found in cache
  // waTemplate === WhatsAppTemplate → found
  const [waTemplate, setWaTemplate] = useState<WhatsAppTemplate | null | false>(null);

  const stopPolling = useCallback(() => {
    if (pollingRef.current !== null) {
      clearInterval(pollingRef.current);
      pollingRef.current = null;
    }
  }, []);

  const fetchCampaign = useCallback(async (silent = false) => {
    if (!silent) setLoading(true);
    try {
      const c = await getCampaign(id);
      setCampaign(c);
      setError(null);
      if (c.status !== 'sending') {
        stopPolling();
      }
      return c;
    } catch (e) {
      const msg = e instanceof Error ? e.message : t('marketing.campaign.loadFailed', 'Failed to load campaign');
      if (!silent) setError(msg);
      return null;
    } finally {
      if (!silent) setLoading(false);
    }
  }, [id, t, stopPolling]);

  const fetchReport = useCallback(async () => {
    setReportLoading(true);
    try {
      const r = await getCampaignReport(id);
      setReport(r);
    } catch {
      // non-fatal, report section stays empty
    } finally {
      setReportLoading(false);
    }
  }, [id]);

  useEffect(() => {
    let alive = true;

    async function init() {
      const c = await fetchCampaign(false);
      if (!alive) return;
      if (c) {
        void fetchReport();
        if (c.status === 'sending') {
          pollingRef.current = setInterval(async () => {
            const updated = await fetchCampaign(true);
            if (updated && updated.status === 'sending') {
              void fetchReport();
            }
          }, POLL_INTERVAL_MS);
        }
      }
    }

    void init();

    return () => {
      alive = false;
      stopPolling();
    };
  }, [fetchCampaign, fetchReport, stopPolling]);

  /**
   * Secondary effect keyed on campaign status. Handles the edge case where a
   * campaign transitions into 'sending' *after* the initial load (e.g. the
   * page was already open when the dispatcher picked up a scheduled campaign).
   * Guards against starting a duplicate interval if polling is already running.
   */
  useEffect(() => {
    if (campaign?.status !== 'sending') return;
    if (pollingRef.current !== null) return;

    pollingRef.current = setInterval(async () => {
      const updated = await fetchCampaign(true);
      if (updated && updated.status === 'sending') {
        void fetchReport();
      }
    }, POLL_INTERVAL_MS);
  }, [campaign?.status, fetchCampaign, fetchReport]);

  // Fetch the cached WhatsApp template once the campaign is known.
  useEffect(() => {
    if (campaign?.channel !== 'whatsapp' || !campaign.template_name || !campaign.branch_id) return;
    let alive = true;
    listWhatsAppTemplates(campaign.branch_id)
      .then((result) => {
        if (!alive) return;
        const found = result.templates.find(
          (tpl) => tpl.name === campaign.template_name && tpl.language === (campaign.template_lang ?? 'en'),
        ) ?? false;
        setWaTemplate(found);
      })
      .catch(() => { if (alive) setWaTemplate(false); });
    return () => { alive = false; };
  }, [campaign?.channel, campaign?.template_name, campaign?.template_lang, campaign?.branch_id]);

  function handleManualRefresh() {
    void fetchCampaign(false);
    void fetchReport();
  }

  if (loading) {
    return (
      <div className="p-10 text-center">
        <Loader2 size={24} className="inline animate-spin text-gray-400" />
      </div>
    );
  }

  if (error || !campaign) {
    return (
      <div className="p-8">
        <Link href="/marketing/campaigns" className="text-sm text-gray-500 hover:text-gray-800 flex items-center gap-1 mb-6">
          <ArrowLeft size={14} /> {t('common.back', 'Back')}
        </Link>
        <div className="text-center py-16 text-red-600">
          <AlertTriangle size={28} className="mx-auto mb-3 opacity-60" />
          <p>{error ?? t('marketing.campaign.notFound', 'Campaign not found')}</p>
        </div>
      </div>
    );
  }

  const isLive = campaign.status === 'sending';
  const skipped = report ? report.totals.skipped : campaign.opt_out_count;

  return (
    <div className="p-6 space-y-6 max-w-3xl">
      <div className="flex items-center justify-between gap-3">
        <Link
          href="/marketing/campaigns"
          className="text-sm text-gray-500 hover:text-gray-800 flex items-center gap-1"
        >
          <ArrowLeft size={14} /> {t('marketing.campaign.backToList', 'All campaigns')}
        </Link>
        <button
          className="btn-ghost flex items-center gap-2 text-sm"
          onClick={handleManualRefresh}
        >
          <RefreshCw size={14} /> {t('common.refresh', 'Refresh')}
        </button>
      </div>

      {/* Header card */}
      <div className="bg-white rounded-xl border p-5 space-y-4">
        <div className="flex items-start justify-between gap-3">
          <div className="flex items-center gap-2 min-w-0">
            <ChannelIcon channel={campaign.channel} />
            <h1 className="font-bold text-lg truncate">{campaign.name}</h1>
          </div>
          <div className="flex items-center gap-2 shrink-0">
            <StatusBadge status={campaign.status} />
            {campaign.launch_group_id && (
              <span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 text-purple-700 inline-flex items-center gap-1">
                <Layers size={10} /> {t('marketing.campaign.linked', 'linked')}
              </span>
            )}
          </div>
        </div>

        <div className="grid grid-cols-2 gap-x-6 gap-y-1 text-sm text-gray-600">
          <div>
            <span className="font-medium">{t('marketing.campaign.channel', 'Channel')}:</span>{' '}
            <span className="capitalize">{campaign.channel}</span>
          </div>
          <div>
            <span className="font-medium">{t('marketing.campaign.audience', 'Audience')}:</span>{' '}
            {campaign.audience_count.toLocaleString()}
          </div>
          <div>
            <span className="font-medium">{t('marketing.campaign.started', 'Started')}:</span>{' '}
            {fmtDate(campaign.started_at)}
          </div>
          <div>
            <span className="font-medium">{t('marketing.campaign.completed', 'Completed')}:</span>{' '}
            {fmtDate(campaign.completed_at)}
          </div>
          {campaign.scheduled_at && (
            <div className="col-span-2 flex items-center gap-1">
              <Clock size={13} className="text-gray-400" />
              <span className="font-medium">{t('marketing.campaign.scheduledAt', 'Scheduled')}:</span>{' '}
              {fmtDate(campaign.scheduled_at)}
            </div>
          )}
        </div>

        {/* WhatsApp template preview */}
        {campaign.channel === 'whatsapp' && campaign.template_name && (
          <div className="border-t pt-3">
            <div className="text-sm font-medium mb-2 flex items-center gap-1.5">
              <MessageCircle size={14} />
              {t('marketing.report.templatePreview', 'Message template')}
            </div>
            <WhatsAppTemplateBubble
              template={waTemplate}
              vars={campaign.template_vars}
              templateName={campaign.template_name}
              templateLang={campaign.template_lang}
              t={t}
            />
          </div>
        )}

        {/* Progress bar — always shown; animated when live */}
        {(campaign.status === 'sending' || campaign.status === 'completed' || campaign.status === 'failed') && (
          <ProgressBar
            sent={campaign.sent_count}
            failed={campaign.failed_count}
            total={campaign.audience_count}
            status={campaign.status}
          />
        )}

        {campaign.last_error && (
          <div className="text-xs bg-red-50 border border-red-200 rounded p-2 text-red-700 flex items-start gap-1.5">
            <AlertTriangle size={13} className="mt-0.5 shrink-0" />
            {campaign.last_error}
          </div>
        )}
      </div>

      {/* Stats row */}
      <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
        <StatCard
          label={t('marketing.report.sent', 'Sent')}
          value={campaign.sent_count}
          color="text-emerald-600"
        />
        <StatCard
          label={t('marketing.report.failed', 'Failed')}
          value={campaign.failed_count}
          color={campaign.failed_count > 0 ? 'text-red-600' : undefined}
        />
        <StatCard
          label={t('marketing.report.skipped', 'Skipped / opt-out')}
          value={skipped}
        />
        <StatCard
          label={t('marketing.report.remaining', 'Remaining')}
          value={Math.max(0, campaign.audience_count - campaign.sent_count - campaign.failed_count - skipped)}
          color={isLive ? 'text-amber-600' : undefined}
        />
      </div>

      {/* Delivery report — tabbed: recent feed + failed/skipped drill-down */}
      <div className="bg-white rounded-xl border">
        <div className="p-4 border-b flex items-center justify-between">
          <div className="font-semibold flex items-center gap-2">
            <BarChart2 size={16} />
            {t('marketing.report.deliveries', 'Deliveries')}
          </div>
          {reportLoading && <Loader2 size={14} className="animate-spin text-gray-400" />}
        </div>

        {report && report.totals && (
          <div className="grid grid-cols-5 divide-x border-b">
            {(
              [
                [t('marketing.report.queued', 'Queued'), report.totals.queued, ''],
                [t('marketing.report.sending', 'Sending'), report.totals.sending, 'text-amber-600'],
                [t('marketing.report.sent', 'Sent'), report.totals.sent, 'text-emerald-600'],
                [t('marketing.report.failed', 'Failed'), report.totals.failed, report.totals.failed > 0 ? 'text-red-600' : ''],
                [t('marketing.report.skipped', 'Skipped'), report.totals.skipped, ''],
              ] as [string, number, string][]
            ).map(([label, val, color]) => (
              <div key={label} className="p-3 text-center">
                <div className={`text-lg font-bold ${color}`}>{val.toLocaleString()}</div>
                <div className="text-xs text-gray-500">{label}</div>
              </div>
            ))}
          </div>
        )}

        {/* Tab bar */}
        <div className="border-b px-4 flex gap-1">
          <button
            onClick={() => setActiveTab('recent')}
            className={`py-2 px-3 text-sm font-medium border-b-2 -mb-px transition-colors ${
              activeTab === 'recent'
                ? 'border-blue-600 text-blue-700'
                : 'border-transparent text-gray-500 hover:text-gray-700'
            }`}
          >
            {t('marketing.report.tabRecent', 'Recent deliveries')}
          </button>
          <button
            onClick={() => setActiveTab('failures')}
            className={`py-2 px-3 text-sm font-medium border-b-2 -mb-px transition-colors flex items-center gap-1.5 ${
              activeTab === 'failures'
                ? 'border-red-500 text-red-700'
                : 'border-transparent text-gray-500 hover:text-gray-700'
            }`}
          >
            {t('marketing.report.tabFailures', 'Failed / Skipped')}
            {report && (report.totals.failed + report.totals.skipped) > 0 && (
              <span className="text-xs bg-red-100 text-red-700 px-1.5 py-0.5 rounded-full font-medium">
                {(report.totals.failed + report.totals.skipped).toLocaleString()}
              </span>
            )}
          </button>
        </div>

        {/* Tab content */}
        {activeTab === 'recent' && (
          <div className="divide-y">
            {!report && !reportLoading && (
              <p className="p-4 text-sm text-gray-500">{t('marketing.report.noDeliveries', 'No deliveries yet.')}</p>
            )}
            {report && report.recent.length === 0 && (
              <p className="p-4 text-sm text-gray-500">{t('marketing.report.noDeliveries', 'No deliveries yet.')}</p>
            )}
            {report && report.totals && (report.totals.failed + report.totals.skipped) > 0 && report.recent.length > 0 && (
              <div className="px-4 py-2.5 bg-amber-50 border-b border-amber-100 text-xs text-amber-800 flex items-center justify-between gap-2">
                <span>
                  <AlertTriangle size={11} className="inline mr-1" />
                  {t('marketing.report.failureHint',
                    'Some recipients could not be reached. Open "Failed / Skipped" to see details and export bad addresses.')}
                </span>
                <button
                  className="font-medium underline whitespace-nowrap"
                  onClick={() => setActiveTab('failures')}
                >
                  {t('marketing.report.viewFailures', 'View details')}
                </button>
              </div>
            )}
            {report?.recent.map((row) => (
              <div key={row.id} className="px-4 py-2.5 flex items-center gap-3 text-sm">
                <span className="flex-1 truncate text-gray-700">{row.recipient}</span>
                <span className={`text-xs px-2 py-0.5 rounded font-medium ${
                  row.status === 'sent'
                    ? 'bg-emerald-100 text-emerald-700'
                    : row.status === 'failed'
                    ? 'bg-red-100 text-red-700'
                    : row.status === 'skipped'
                    ? 'bg-amber-100 text-amber-800'
                    : 'bg-gray-100 text-gray-600'
                }`}>
                  {row.status}
                </span>
                {row.last_error && (
                  <span className="text-xs text-red-500 truncate max-w-[180px]" title={row.last_error}>
                    {row.last_error}
                  </span>
                )}
                {row.sent_at && (
                  <span className="text-xs text-gray-400 shrink-0">
                    {new Date(row.sent_at).toLocaleTimeString()}
                  </span>
                )}
              </div>
            ))}
          </div>
        )}

        {activeTab === 'failures' && (
          <FailedSkippedTab campaignId={id} t={t} />
        )}
      </div>

      {isLive && (
        <p className="text-xs text-center text-gray-400">
          {t('marketing.campaign.pollNote', 'This page refreshes automatically every 6 seconds while the campaign is sending.')}
        </p>
      )}
    </div>
  );
}

export default function CampaignDetailPage() {
  return (
    <FeatureGuard feature="marketing" featureName="Marketing">
      <CampaignDetailInner />
    </FeatureGuard>
  );
}
