"use client";

import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { useTranslations, useLocale } from "next-intl";
import {
  Mail, Inbox, ChevronRight, Search, RefreshCw, X, Paperclip,
  Send, XCircle, RotateCcw, ChevronLeft, ChevronRight as ChevronRightIcon,
  User, Globe, Clock, Download, FileText, Image, File, AlertCircle,
  ArrowRight, Check, Eye, UserCheck,
} from "lucide-react";
import {
  listMailInbox, getMailDetail, dispatchMail, selfDispatchMail, acceptMail, reassignMail,
  rejectMail, restoreMail, markMailProcessed, downloadMailAttachment,
  listCountryManagers,
  type IncomingMailSummary, type IncomingMailDetail, type CountryManager,
  type IncomingMailAttachment,
} from "@/src/lib/api/mail-config";
import { useMailBadge } from "@/src/contexts/MailBadgeContext";
import { listTenantUsers, type TenantUser } from "@/src/lib/api/tenant-users";
import { listTenantCountries, type TenantCountry } from "@/src/lib/api/countries";
import { useMe } from "@/src/lib/hooks/useMe";

const NAVY = "#1e1b4b";
const NAVY2 = "#312e81";

function cx(...cls: (string | boolean | undefined | null)[]) {
  return cls.filter(Boolean).join(" ");
}

// ─── Date helper (fully locale-aware via Intl) ────────────────────────────────
function formatDate(iso: string, locale: string): string {
  const d = new Date(iso);
  const now = new Date();
  const diffMs = now.getTime() - d.getTime();
  const diffMin = Math.floor(diffMs / 60000);
  const diffH = Math.floor(diffMin / 60);
  const diffD = Math.floor(diffH / 24);
  try {
    const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
    if (diffMin < 1) return rtf.format(0, "second");
    if (diffMin < 60) return rtf.format(-diffMin, "minute");
    if (diffH < 24) return rtf.format(-diffH, "hour");
    if (diffD < 7) return rtf.format(-diffD, "day");
  } catch {
    // fallback below
  }
  return d.toLocaleDateString(locale, { day: "2-digit", month: "short", year: "numeric" });
}

function formatBytes(bytes: number) {
  if (!bytes) return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB"];
  const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
}

// ─── Status ───────────────────────────────────────────────────────────────────
type MailStatus = "pending" | "dispatched" | "processed" | "rejected";

const STATUS_STYLE: Record<MailStatus, { color: string; bg: string; border: string }> = {
  pending:    { color: "text-amber-600",   bg: "bg-amber-50",   border: "border-amber-200" },
  dispatched: { color: "text-indigo-600",  bg: "bg-indigo-50",  border: "border-indigo-200" },
  processed:  { color: "text-emerald-600", bg: "bg-emerald-50", border: "border-emerald-200" },
  rejected:   { color: "text-red-500",     bg: "bg-red-50",     border: "border-red-200" },
};

function StatusBadge({ status }: { status: MailStatus }) {
  const t = useTranslations("mail_inbox");
  const c = STATUS_STYLE[status];
  return (
    <span className={cx(
      "inline-flex items-center text-xs font-medium px-2 py-0.5 rounded-full border",
      c.color, c.bg, c.border
    )}>
      {t(`status_${status}` as any)}
    </span>
  );
}

// ─── Attachment icon ──────────────────────────────────────────────────────────
function AttachmentIcon({ contentType }: { contentType: string }) {
  if (contentType.startsWith("image/")) return <Image size={14} className="text-purple-400" />;
  if (contentType === "application/pdf") return <FileText size={14} className="text-red-400" />;
  return <File size={14} className="text-slate-400" />;
}

function AttachmentRow({ att, downloadHint }: { att: IncomingMailAttachment; downloadHint: string }) {
  const [downloading, setDownloading] = useState(false);

  const handleDownload = async () => {
    setDownloading(true);
    try {
      const blob = await downloadMailAttachment(att.id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = att.filename || "piece-jointe";
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    } catch {
      alert("Impossible de télécharger le fichier.");
    } finally {
      setDownloading(false);
    }
  };

  return (
    <div className="flex items-center gap-2 bg-slate-50 border border-slate-200 rounded-lg px-3 py-2">
      <AttachmentIcon contentType={att.content_type} />
      <div className="flex-1 min-w-0">
        <p className="text-xs font-medium text-slate-700 truncate">{att.filename}</p>
        <p className="text-xs text-slate-400">{att.content_type} · {formatBytes(att.size)}</p>
      </div>
      <button
        onClick={handleDownload}
        disabled={downloading}
        className="p-1.5 rounded-lg text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 transition disabled:opacity-50"
        title={downloadHint}
      >
        {downloading
          ? <span className="w-3.5 h-3.5 border-2 border-indigo-400 border-t-transparent rounded-full animate-spin inline-block" />
          : <Download size={13} />
        }
      </button>
    </div>
  );
}

// ─── Stats bar ────────────────────────────────────────────────────────────────
function StatsBar({ stats }: {
  stats: { total: number; pending: number; dispatched: number; processed: number; rejected: number };
}) {
  const t = useTranslations("mail_inbox");
  const items = [
    { label: t("stats_total"),      value: stats.total,      color: "text-slate-700" },
    { label: t("stats_pending"),    value: stats.pending,    color: "text-amber-600" },
    { label: t("stats_dispatched"), value: stats.dispatched, color: "text-indigo-600" },
    { label: t("stats_processed"),  value: stats.processed,  color: "text-emerald-600" },
    { label: t("stats_rejected"),   value: stats.rejected,   color: "text-red-500" },
  ];
  return (
    <div className="grid grid-cols-5 gap-3">
      {items.map((item) => (
        <div key={item.label} className="bg-white rounded-xl border border-slate-200 px-4 py-3 text-center shadow-sm">
          <div className={cx("text-2xl font-bold", item.color)}>{item.value}</div>
          <div className="text-xs text-slate-500 mt-0.5">{item.label}</div>
        </div>
      ))}
    </div>
  );
}

// ─── Dispatch Modal ───────────────────────────────────────────────────────────
function DispatchModal({
  mail, onDispatch, onClose,
}: {
  mail: IncomingMailSummary;
  onDispatch: (assigned_to_id: number, country: string, note: string) => Promise<void>;
  onClose: () => void;
}) {
  const t = useTranslations("mail_inbox");

  const [allMembers, setAllMembers] = useState<TenantUser[]>([]);
  const [operationalCountries, setOperationalCountries] = useState<TenantCountry[]>([]);
  const [loadingData, setLoadingData] = useState(true);

  const [country, setCountry] = useState(mail.assigned_country || "");
  const [overrideManager, setOverrideManager] = useState(false);
  const [manualAssigneeId, setManualAssigneeId] = useState<number | "">("");
  const [note, setNote] = useState("");
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");

  useEffect(() => {
    Promise.all([listTenantUsers(), listTenantCountries()])
      .then(([users, countries]) => {
        setAllMembers(users.filter((u) => u.is_active !== false));
        setOperationalCountries(countries.filter((c) => c.is_active));
      })
      .finally(() => setLoadingData(false));
  }, []);

  // Country currently selected
  const selectedCountry = operationalCountries.find((c) => c.country_code === country);
  // Manager auto-assigned from country config
  const autoManager = selectedCountry?.manager ?? null;
  // Show manual picker when: no country selected, no manager for selected country, or user clicked override
  const showManualPicker = !autoManager || overrideManager;
  // Effective assignee
  const effectiveAssigneeId = autoManager && !overrideManager
    ? autoManager.id
    : manualAssigneeId;

  const handleCountryChange = (code: string) => {
    setCountry(code);
    setOverrideManager(false);
    setManualAssigneeId("");
    setError("");
  };

  const handleSubmit = async () => {
    if (!effectiveAssigneeId) { setError(t("error_select")); return; }
    setSaving(true);
    setError("");
    try {
      await onDispatch(Number(effectiveAssigneeId), country, note);
      onClose();
    } catch (e: any) {
      setError(e?.message || e?.detail || t("error_generic"));
    } finally {
      setSaving(false);
    }
  };

  const inputCls = "w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-800 focus:outline-none focus:ring-2 focus:ring-indigo-300 focus:border-indigo-400";

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm p-4">
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-md max-h-[90vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-slate-100 flex-shrink-0">
          <div>
            <h2 className="font-bold text-slate-800 text-base">{t("dispatch_title")}</h2>
            <p className="text-xs text-slate-500 mt-0.5 truncate max-w-sm">{mail.subject}</p>
          </div>
          <button onClick={onClose} className="text-slate-400 hover:text-slate-700 transition">
            <X size={18} />
          </button>
        </div>

        <div className="px-6 py-5 space-y-4 overflow-y-auto">
          {error && (
            <div className="flex items-center gap-2 text-sm text-red-600 bg-red-50 border border-red-200 rounded-lg px-3 py-2">
              <XCircle size={14} /> {error}
            </div>
          )}

          {/* Sender info */}
          <div className="bg-slate-50 rounded-xl border border-slate-200 px-4 py-3">
            <p className="text-xs text-slate-500">
              {t("from_label")} :{" "}
              <span className="font-medium text-slate-700">{mail.from_name || mail.from_email}</span>
            </p>
            <p className="text-xs text-slate-500 mt-0.5">
              {t("sender_label")} :{" "}
              <span className="font-mono text-slate-600">{mail.from_email}</span>
            </p>
          </div>

          {/* ① Country — primary choice */}
          <div className="space-y-1.5">
            <label className="text-xs font-semibold text-neutral-500 uppercase tracking-wide">
              {t("country_label")}
            </label>
            {loadingData ? (
              <div className="flex items-center gap-2 text-xs text-slate-400 py-2">
                <RefreshCw size={12} className="animate-spin" /> {t("loading")}
              </div>
            ) : (
              <select
                value={country}
                onChange={(e) => handleCountryChange(e.target.value)}
                className={inputCls}
              >
                <option value="">{t("country_none")}</option>
                {operationalCountries.map((c) => (
                  <option key={c.country_code} value={c.country_code}>
                    {c.country_name} ({c.country_code})
                  </option>
                ))}
              </select>
            )}
          </div>

          {/* ② Auto-assigned manager card — shown when country has a manager */}
          {!loadingData && autoManager && (
            <div className="rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 space-y-2">
              <div className="flex items-center justify-between">
                <span className="text-xs font-semibold text-emerald-700 uppercase tracking-wide flex items-center gap-1.5">
                  <Check size={12} /> {t("country_manager_auto")}
                </span>
                <button
                  type="button"
                  onClick={() => setOverrideManager((v) => !v)}
                  className="text-xs text-indigo-600 hover:underline"
                >
                  {overrideManager ? t("assignee_cancel_override") : t("assignee_override")}
                </button>
              </div>
              <div className="flex items-center gap-2">
                <div className="w-7 h-7 rounded-full bg-emerald-100 border border-emerald-200 flex items-center justify-center flex-shrink-0">
                  <User size={13} className="text-emerald-600" />
                </div>
                <div className="min-w-0">
                  <p className="text-sm font-semibold text-slate-800 truncate">{autoManager.full_name}</p>
                  <p className="text-xs text-slate-500 font-mono truncate">{autoManager.email}</p>
                </div>
              </div>
              {!overrideManager && (
                <p className="text-xs text-emerald-700 leading-snug">{t("assignee_auto_hint")}</p>
              )}
            </div>
          )}

          {/* ③ Warning when country selected but no manager */}
          {!loadingData && country && !autoManager && (
            <div className="flex items-center gap-2 text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded-lg px-3 py-2">
              <AlertCircle size={13} className="flex-shrink-0" /> {t("country_no_manager")}
            </div>
          )}

          {/* ④ Manual picker — shown when no manager or override active */}
          {!loadingData && showManualPicker && (
            <div className="space-y-1.5">
              <label className="text-xs font-semibold text-neutral-500 uppercase tracking-wide">
                {t("assignee_label")}
                {(!autoManager || country === "") && <span className="text-red-500 ml-1">*</span>}
              </label>
              {allMembers.length === 0 ? (
                <div className="flex items-center gap-2 text-xs text-amber-600 bg-amber-50 border border-amber-200 rounded-lg px-3 py-2">
                  <AlertCircle size={13} /> {t("no_managers")}
                </div>
              ) : (
                <select
                  value={manualAssigneeId}
                  onChange={(e) => setManualAssigneeId(e.target.value === "" ? "" : Number(e.target.value))}
                  className={inputCls}
                >
                  <option value="">{t("assignee_placeholder")}</option>
                  <optgroup label={t("group_managers")}>
                    {allMembers
                      .filter((u) => operationalCountries.some((c) => c.manager?.id === u.id))
                      .map((u) => {
                        const name = [u.first_name, u.last_name].filter(Boolean).join(" ") || u.username;
                        return <option key={u.id} value={u.id}>{name} — {u.email}</option>;
                      })}
                  </optgroup>
                  <optgroup label={t("group_members")}>
                    {allMembers
                      .filter((u) => !operationalCountries.some((c) => c.manager?.id === u.id))
                      .map((u) => {
                        const name = [u.first_name, u.last_name].filter(Boolean).join(" ") || u.username;
                        return <option key={u.id} value={u.id}>{name} — {u.email}</option>;
                      })}
                  </optgroup>
                </select>
              )}
            </div>
          )}

          {/* ⑤ Dispatch note */}
          <div className="space-y-1.5">
            <label className="text-xs font-semibold text-neutral-500 uppercase tracking-wide">
              {t("dispatch_note_label")}
            </label>
            <textarea
              className={cx(inputCls, "resize-none")}
              rows={2}
              value={note}
              onChange={(e) => setNote(e.target.value)}
              placeholder={t("dispatch_note_placeholder")}
            />
          </div>
        </div>

        {/* Footer */}
        <div className="flex justify-end gap-3 px-6 py-4 border-t border-slate-100 flex-shrink-0">
          <button
            onClick={onClose}
            className="px-4 py-2 rounded-lg border border-slate-200 text-sm text-slate-600 hover:bg-slate-50 transition"
          >
            {t("dispatch_cancel")}
          </button>
          <button
            onClick={handleSubmit}
            disabled={saving || !effectiveAssigneeId}
            className="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-semibold text-white transition disabled:opacity-50"
            style={{ background: `linear-gradient(135deg, ${NAVY} 0%, ${NAVY2} 100%)` }}
          >
            <Send size={14} />
            {saving ? t("dispatching") : t("dispatch_confirm")}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Reassign Modal ───────────────────────────────────────────────────────────
function ReassignModal({
  mail, onReassign, onClose,
}: {
  mail: IncomingMailDetail;
  onReassign: (assigned_to_id: number, note: string) => Promise<void>;
  onClose: () => void;
}) {
  const t = useTranslations("mail_inbox");
  const [members, setMembers] = useState<TenantUser[]>([]);
  const [loading, setLoading] = useState(true);
  const [assigneeId, setAssigneeId] = useState<number | "">("");
  const [note, setNote] = useState("");
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");

  useEffect(() => {
    listTenantUsers()
      .then((u) => setMembers(u.filter((m) => m.is_active !== false && m.id !== mail.assigned_to?.id)))
      .finally(() => setLoading(false));
  }, [mail.assigned_to?.id]);

  const handleSubmit = async () => {
    if (!assigneeId) { setError(t("error_select_member")); return; }
    setSaving(true);
    setError("");
    try {
      await onReassign(Number(assigneeId), note);
      onClose();
    } catch (e: any) {
      setError(e?.message || e?.detail || t("error_generic"));
    } finally {
      setSaving(false);
    }
  };

  const inputCls = "w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-800 focus:outline-none focus:ring-2 focus:ring-indigo-300 focus:border-indigo-400";

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm p-4">
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-md flex flex-col">
        <div className="flex items-center justify-between px-6 py-4 border-b border-slate-100">
          <div>
            <h2 className="font-bold text-slate-800 text-base">{t("reassign_title")}</h2>
            <p className="text-xs text-slate-500 mt-0.5 truncate max-w-sm">{mail.subject}</p>
          </div>
          <button onClick={onClose} className="text-slate-400 hover:text-slate-700 transition"><X size={18} /></button>
        </div>

        <div className="px-6 py-5 space-y-4">
          {error && (
            <div className="flex items-center gap-2 text-sm text-red-600 bg-red-50 border border-red-200 rounded-lg px-3 py-2">
              <XCircle size={14} /> {error}
            </div>
          )}

          {/* Actuellement assigné */}
          {mail.assigned_to && (
            <div className="flex items-center gap-2 text-xs text-slate-500 bg-slate-50 border border-slate-200 rounded-lg px-3 py-2">
              <ArrowRight size={12} className="text-indigo-400" />
              {t("currently_assigned")} :{" "}
              <span className="font-medium text-slate-700">{mail.assigned_to.name}</span>
            </div>
          )}

          <div className="space-y-1.5">
            <label className="text-xs font-semibold text-neutral-500 uppercase tracking-wide">
              {t("reassign_to_label")} <span className="text-red-500">*</span>
            </label>
            {loading ? (
              <div className="flex items-center gap-2 text-xs text-slate-400 py-2">
                <RefreshCw size={12} className="animate-spin" /> {t("loading")}
              </div>
            ) : (
              <select
                value={assigneeId}
                onChange={(e) => setAssigneeId(e.target.value === "" ? "" : Number(e.target.value))}
                className={inputCls}
              >
                <option value="">{t("assignee_placeholder")}</option>
                {members.map((u) => {
                  const name = [u.first_name, u.last_name].filter(Boolean).join(" ") || u.username;
                  return <option key={u.id} value={u.id}>{name} — {u.email}</option>;
                })}
              </select>
            )}
          </div>

          <div className="space-y-1.5">
            <label className="text-xs font-semibold text-neutral-500 uppercase tracking-wide">
              {t("dispatch_note_label")}
            </label>
            <textarea
              className={cx(inputCls, "resize-none")}
              rows={2}
              value={note}
              onChange={(e) => setNote(e.target.value)}
              placeholder={t("reassign_note_placeholder")}
            />
          </div>
        </div>

        <div className="flex justify-end gap-3 px-6 py-4 border-t border-slate-100">
          <button
            onClick={onClose}
            className="px-4 py-2 rounded-lg border border-slate-200 text-sm text-slate-600 hover:bg-slate-50 transition"
          >
            {t("dispatch_cancel")}
          </button>
          <button
            onClick={handleSubmit}
            disabled={saving || !assigneeId}
            className="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-semibold text-white transition disabled:opacity-50"
            style={{ background: `linear-gradient(135deg, ${NAVY} 0%, ${NAVY2} 100%)` }}
          >
            <ArrowRight size={14} />
            {saving ? t("reassigning") : t("reassign_confirm")}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Detail Panel ─────────────────────────────────────────────────────────────
function DetailPanel({
  mailId, onClose, onAction, isAdmin, currentUserId,
}: {
  mailId: number;
  onClose: () => void;
  onAction: (updated: IncomingMailSummary) => void;
  isAdmin: boolean;
  currentUserId?: number;
}) {
  const t = useTranslations("mail_inbox");
  const locale = useLocale();
  const [mail, setMail] = useState<IncomingMailDetail | null>(null);
  const [loading, setLoading] = useState(true);
  const [showDispatch, setShowDispatch] = useState(false);
  const [showReassign, setShowReassign] = useState(false);
  const [actionLoading, setActionLoading] = useState(false);
  const [htmlView, setHtmlView] = useState(true);

  useEffect(() => {
    setLoading(true);
    getMailDetail(mailId).then(setMail).finally(() => setLoading(false));
  }, [mailId]);

  const handleDispatch = async (assigneeId: number, country: string, note: string) => {
    const updated = await dispatchMail(mailId, {
      assigned_to_id: assigneeId,
      assigned_country: country,
      dispatch_note: note,
    });
    setMail(updated);
    onAction(updated);
    setShowDispatch(false);
    refreshBadge();
  };

  const handleReject = async () => {
    setActionLoading(true);
    try {
      const updated = await rejectMail(mailId);
      setMail((prev) => prev ? { ...prev, ...updated } : prev);
      onAction(updated);
    } finally {
      setActionLoading(false);
    }
  };

  const handleRestore = async () => {
    setActionLoading(true);
    try {
      const updated = await restoreMail(mailId);
      setMail((prev) => prev ? { ...prev, ...updated } : prev);
      onAction(updated);
    } finally {
      setActionLoading(false);
    }
  };

  const handleProcessed = async () => {
    setActionLoading(true);
    try {
      const updated = await markMailProcessed(mailId);
      setMail((prev) => prev ? { ...prev, ...updated } : prev);
      onAction(updated);
    } finally {
      setActionLoading(false);
    }
  };

  const { refresh: refreshBadge } = useMailBadge();

  const handleSelfDispatch = async () => {
    setActionLoading(true);
    try {
      const updated = await selfDispatchMail(mailId);
      setMail(updated);
      onAction(updated);
      refreshBadge();
    } catch { /* ignore */ } finally {
      setActionLoading(false);
    }
  };

  const handleAccept = async () => {
    setActionLoading(true);
    try {
      const updated = await acceptMail(mailId);
      setMail(updated);
      onAction(updated);
    } catch { /* ignore */ } finally {
      setActionLoading(false);
    }
  };

  const handleReassign = async (assigneeId: number, note: string) => {
    const updated = await reassignMail(mailId, { assigned_to_id: assigneeId, dispatch_note: note });
    setMail(updated);
    onAction(updated);
    setShowReassign(false);
    refreshBadge();
  };

  const isAssignee = mail?.assigned_to?.id === currentUserId;

  return (
    <>
      <div className="h-full flex flex-col bg-white border-l border-slate-200">
        {/* Header */}
        <div className="flex items-start justify-between px-5 py-4 border-b border-slate-100">
          <div className="flex-1 min-w-0 pr-3">
            {loading || !mail ? (
              <div className="h-4 w-48 bg-slate-200 rounded animate-pulse" />
            ) : (
              <>
                <div className="flex items-center gap-2 mb-1">
                  <StatusBadge status={mail.status as MailStatus} />
                  {mail.attachments_count > 0 && (
                    <span className="inline-flex items-center gap-1 text-xs text-slate-500">
                      <Paperclip size={11} /> {mail.attachments_count}
                    </span>
                  )}
                </div>
                <h3 className="font-bold text-slate-800 text-sm leading-tight line-clamp-2">
                  {mail.subject || t("no_subject")}
                </h3>
              </>
            )}
          </div>
          <button
            onClick={onClose}
            className="p-1 rounded-lg text-slate-400 hover:text-slate-700 hover:bg-slate-100 transition flex-shrink-0"
          >
            <X size={16} />
          </button>
        </div>

        {loading || !mail ? (
          <div className="flex-1 flex items-center justify-center text-slate-400">
            <RefreshCw size={20} className="animate-spin mr-2" /> {t("loading")}
          </div>
        ) : (
          <>
            {/* Meta */}
            <div className="px-5 py-3 border-b border-slate-100 space-y-1.5">
              <div className="flex items-start gap-2 text-xs text-slate-500">
                <User size={12} className="mt-0.5 flex-shrink-0" />
                <div>
                  {mail.from_name && <span className="font-medium text-slate-700">{mail.from_name} </span>}
                  <span className="font-mono">&lt;{mail.from_email}&gt;</span>
                </div>
              </div>
              <div className="flex items-center gap-2 text-xs text-slate-500">
                <Clock size={12} className="flex-shrink-0" />
                {new Date(mail.received_at).toLocaleString(locale, { dateStyle: "full", timeStyle: "short" })}
              </div>
              {mail.mail_source && (
                <div className="flex items-center gap-2 text-xs text-slate-500">
                  <Globe size={12} className="flex-shrink-0" />
                  <span>
                    {t("client_label")} :{" "}
                    <span className="font-medium text-slate-700">
                      {mail.mail_source.client_name || mail.mail_source.email_or_domain}
                    </span>
                  </span>
                </div>
              )}
              {mail.assigned_to && (
                <div className="flex items-center gap-2 text-xs text-indigo-600">
                  <ArrowRight size={12} className="flex-shrink-0" />
                  {t("assigned_to_label")}{" "}
                  <span className="font-medium ml-1">{mail.assigned_to.name}</span>
                  {mail.assigned_country && (
                    <span className="inline-flex items-center gap-1 bg-indigo-50 border border-indigo-200 rounded px-1.5 py-0.5">
                      {mail.assigned_country}
                    </span>
                  )}
                </div>
              )}
              {mail.dispatch_note && (
                <div className="text-xs text-slate-500 bg-amber-50 border border-amber-100 rounded-lg px-3 py-2">
                  📌 {mail.dispatch_note}
                </div>
              )}
            </div>

            {/* Attachments */}
            {mail.attachments.length > 0 && (
              <div className="px-5 py-3 border-b border-slate-100">
                <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">
                  {t("attachments_title", { count: mail.attachments.length })}
                </p>
                <div className="space-y-1.5">
                  {mail.attachments.map((att) => (
                    <AttachmentRow key={att.id} att={att} downloadHint={t("download_hint")} />
                  ))}
                </div>
              </div>
            )}

            {/* Body */}
            <div className="flex-1 overflow-y-auto">
              {(mail.body_html || mail.body_text) && (
                <>
                  <div className="flex items-center gap-2 px-5 py-2 border-b border-slate-100">
                    <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide flex-1">
                      {t("body_title")}
                    </p>
                    {mail.body_html && mail.body_text && (
                      <button
                        onClick={() => setHtmlView((v) => !v)}
                        className="text-xs text-indigo-600 hover:underline flex items-center gap-1"
                      >
                        <Eye size={11} /> {htmlView ? t("view_raw") : t("view_html")}
                      </button>
                    )}
                  </div>
                  <div className="px-5 py-4">
                    {htmlView && mail.body_html ? (
                      <div
                        className="prose prose-sm max-w-none text-slate-700 text-xs"
                        dangerouslySetInnerHTML={{ __html: mail.body_html }}
                      />
                    ) : (
                      <pre className="text-xs text-slate-600 whitespace-pre-wrap font-sans leading-relaxed">
                        {mail.body_text || t("no_body")}
                      </pre>
                    )}
                  </div>
                </>
              )}
            </div>

            {/* Historique dispatch + acceptance */}
            {mail.dispatched_at && (
              <div className="px-5 py-3 border-t border-slate-100 bg-indigo-50/40 space-y-2.5">
                <p className="text-[10px] font-bold text-indigo-400 uppercase tracking-wide">{t("dispatch_history_title")}</p>

                {/* Ligne dispatch */}
                <div className="flex items-start gap-2">
                  <div className="w-6 h-6 rounded-full bg-indigo-100 flex items-center justify-center flex-shrink-0 mt-0.5">
                    <Send size={11} className="text-indigo-600" />
                  </div>
                  <div className="text-xs text-slate-600 leading-relaxed">
                    <span className="font-semibold text-indigo-700">
                      {mail.dispatched_by?.name || "—"}
                    </span>
                    {" "}{t("dispatch_history_verb")}{" "}
                    <span className="font-semibold text-slate-700">
                      {mail.assigned_to?.name || "—"}
                    </span>
                    <span className="text-slate-400 ml-2">
                      {new Date(mail.dispatched_at).toLocaleString(locale, { dateStyle: "short", timeStyle: "short" })}
                    </span>
                    {mail.dispatch_note && (
                      <p className="mt-1 italic text-slate-500">« {mail.dispatch_note} »</p>
                    )}
                  </div>
                </div>

                {/* Ligne acceptance */}
                {mail.accepted_at ? (
                  <div className="flex items-start gap-2">
                    <div className="w-6 h-6 rounded-full bg-emerald-100 flex items-center justify-center flex-shrink-0 mt-0.5">
                      <Check size={11} className="text-emerald-600" />
                    </div>
                    <div className="text-xs text-slate-600 leading-relaxed">
                      <span className="font-semibold text-emerald-700">
                        {mail.accepted_by?.name || "—"}
                      </span>
                      {" "}{t("accept_history_verb")}
                      <span className="text-slate-400 ml-2">
                        {new Date(mail.accepted_at).toLocaleString(locale, { dateStyle: "short", timeStyle: "short" })}
                      </span>
                    </div>
                  </div>
                ) : mail.status === "dispatched" ? (
                  <div className="flex items-center gap-2 text-xs text-amber-600">
                    <div className="w-6 h-6 rounded-full bg-amber-50 border border-amber-200 flex items-center justify-center flex-shrink-0">
                      <Clock size={11} className="text-amber-500" />
                    </div>
                    {t("pending_acceptance")}
                  </div>
                ) : null}
              </div>
            )}

            {/* Actions */}
            {(isAdmin || isAssignee) && (
              <div className="px-5 py-4 border-t border-slate-100 flex flex-wrap gap-2">
                {/* ── Actions admin sur un mail en attente ── */}
                {isAdmin && mail.status === "pending" && (
                  <>
                    <button
                      onClick={() => setShowDispatch(true)}
                      className="flex items-center gap-1.5 px-3 py-2 rounded-lg text-xs font-semibold text-white transition"
                      style={{ background: `linear-gradient(135deg, ${NAVY} 0%, ${NAVY2} 100%)` }}
                    >
                      <Send size={12} /> {t("dispatch_btn")}
                    </button>
                    <button
                      onClick={handleSelfDispatch}
                      disabled={actionLoading}
                      className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-indigo-200 text-xs font-medium text-indigo-700 hover:bg-indigo-50 transition disabled:opacity-50"
                    >
                      <UserCheck size={12} /> {t("self_dispatch_btn")}
                    </button>
                    <button
                      onClick={handleReject}
                      disabled={actionLoading}
                      className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-red-200 text-xs font-medium text-red-600 hover:bg-red-50 transition disabled:opacity-50"
                    >
                      <XCircle size={12} /> {t("reject_btn")}
                    </button>
                  </>
                )}

                {/* ── Actions sur un mail dispatché ── */}
                {mail.status === "dispatched" && (
                  <>
                    {/* Accepter — assigné n'ayant pas encore accepté */}
                    {isAssignee && !mail.accepted_at && (
                      <button
                        onClick={handleAccept}
                        disabled={actionLoading}
                        className="flex items-center gap-1.5 px-3 py-2 rounded-lg text-xs font-semibold text-white transition disabled:opacity-50"
                        style={{ background: "linear-gradient(135deg, #059669 0%, #10b981 100%)" }}
                      >
                        <Check size={12} /> {t("accept_btn")}
                      </button>
                    )}
                    {/* Réaffecter — assigné ou admin */}
                    {(isAssignee || isAdmin) && (
                      <button
                        onClick={() => setShowReassign(true)}
                        disabled={actionLoading}
                        className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-indigo-200 text-xs font-medium text-indigo-600 hover:bg-indigo-50 transition disabled:opacity-50"
                      >
                        <ArrowRight size={12} /> {t("reassign_btn")}
                      </button>
                    )}
                    {/* Re-dispatcher (admin) */}
                    {isAdmin && (
                      <button
                        onClick={() => setShowDispatch(true)}
                        className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-slate-200 text-xs font-medium text-slate-500 hover:bg-slate-50 transition"
                      >
                        <Send size={12} /> {t("redispatch_btn")}
                      </button>
                    )}
                    {/* Marquer traité — assigné ou admin */}
                    {(isAssignee || isAdmin) && (
                      <button
                        onClick={handleProcessed}
                        disabled={actionLoading}
                        className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-emerald-200 text-xs font-medium text-emerald-600 hover:bg-emerald-50 transition disabled:opacity-50"
                      >
                        <UserCheck size={12} /> {t("processed_btn")}
                      </button>
                    )}
                    {/* Remettre en attente — admin uniquement */}
                    {isAdmin && (
                      <button
                        onClick={handleRestore}
                        disabled={actionLoading}
                        className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-slate-200 text-xs font-medium text-slate-400 hover:bg-slate-50 transition disabled:opacity-50"
                      >
                        <RotateCcw size={12} /> {t("restore_btn")}
                      </button>
                    )}
                  </>
                )}

                {/* ── Restaurer depuis rejeté/traité — admin uniquement ── */}
                {isAdmin && (mail.status === "rejected" || mail.status === "processed") && (
                  <button
                    onClick={handleRestore}
                    disabled={actionLoading}
                    className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-slate-200 text-xs font-medium text-slate-500 hover:bg-slate-50 transition disabled:opacity-50"
                  >
                    <RotateCcw size={12} /> {t("restore_btn")}
                  </button>
                )}
              </div>
            )}
          </>
        )}
      </div>

      {showDispatch && mail && (
        <DispatchModal
          mail={mail}
          onDispatch={handleDispatch}
          onClose={() => setShowDispatch(false)}
        />
      )}
      {showReassign && mail && (
        <ReassignModal
          mail={mail}
          onReassign={handleReassign}
          onClose={() => setShowReassign(false)}
        />
      )}
    </>
  );
}

// ─── Page ─────────────────────────────────────────────────────────────────────
export default function MailInboxPage() {
  const t = useTranslations("mail_inbox");
  const locale = useLocale();
  const me = useMe();

  const STATUS_FILTERS = useMemo(() => [
    { value: "",            label: t("filter_all") },
    { value: "pending",     label: t("filter_pending") },
    { value: "dispatched",  label: t("filter_dispatched") },
    { value: "processed",   label: t("filter_processed") },
    { value: "rejected",    label: t("filter_rejected") },
  ], [t]);

  const [data, setData] = useState<import("@/src/lib/api/mail-config").MailInboxResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [statusFilter, setStatusFilter] = useState("");
  const [search, setSearch] = useState("");
  const [searchInput, setSearchInput] = useState("");
  const [page, setPage] = useState(1);
  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [refreshing, setRefreshing] = useState(false);
  const [newMailFlash, setNewMailFlash] = useState(false);

  const load = useCallback(async (params?: { status?: string; search?: string; page?: number }) => {
    setLoading(true);
    try {
      const res = await listMailInbox({
        status: params?.status ?? statusFilter,
        search: params?.search ?? search,
        page: params?.page ?? page,
      });
      setData(res);
    } finally {
      setLoading(false);
    }
  }, [statusFilter, search, page]);

  // Polling silencieux — sans spinner pour ne pas perturber l'utilisateur
  const silentLoad = useCallback(async () => {
    try {
      const res = await listMailInbox({ status: statusFilter, search, page });
      setData((prev) => {
        if (prev && res.stats.pending > (prev.stats?.pending ?? 0)) {
          setNewMailFlash(true);
          setTimeout(() => setNewMailFlash(false), 4000);
        }
        return res;
      });
    } catch { /* erreur réseau silencieuse */ }
  }, [statusFilter, search, page]);

  // Polling toutes les 30s (sans vérifier document.hidden) + retour onglet + événement SSE
  useEffect(() => {
    const id = setInterval(silentLoad, 30_000);
    // Refresh immédiat quand l'onglet redevient visible (machine déverrouillée, retour d'onglet)
    const onVisible = () => { if (!document.hidden) silentLoad(); };
    document.addEventListener("visibilitychange", onVisible);
    // Écoute l'événement SSE émis par MailBadgeContext
    const onSSE = () => silentLoad();
    window.addEventListener("mail:update", onSSE);
    return () => {
      clearInterval(id);
      document.removeEventListener("visibilitychange", onVisible);
      window.removeEventListener("mail:update", onSSE);
    };
  }, [silentLoad]);

  useEffect(() => { load(); }, [statusFilter, page]);

  const handleSearch = (e: React.FormEvent) => {
    e.preventDefault();
    setSearch(searchInput);
    setPage(1);
    load({ search: searchInput, page: 1 });
  };

  const handleRefresh = async () => {
    setRefreshing(true);
    await load();
    setRefreshing(false);
  };

  const handleStatusFilter = (s: string) => {
    setStatusFilter(s);
    setPage(1);
  };

  const handleMailAction = (updated: IncomingMailSummary) => {
    setData((prev) => {
      if (!prev) return prev;
      return { ...prev, results: prev.results.map((m) => (m.id === updated.id ? updated : m)) };
    });
  };

  const isAdmin = data?.is_admin ?? true;
  const totalPages = data ? Math.ceil(data.count / (data.page_size || 20)) : 0;

  // Calcule les numéros de pages à afficher (max 7 boutons avec ellipses)
  const pageNumbers = useMemo((): (number | "...")[] => {
    if (totalPages <= 7) return Array.from({ length: totalPages }, (_, i) => i + 1);
    const pages: (number | "...")[] = [1];
    if (page > 3) pages.push("...");
    for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) pages.push(i);
    if (page < totalPages - 2) pages.push("...");
    pages.push(totalPages);
    return pages;
  }, [page, totalPages]);

  return (
    <div className="flex flex-col h-full max-h-full overflow-hidden">
      {/* Header */}
      <div className="px-6 pt-6 pb-4 flex-shrink-0">
        <div className="flex items-center gap-1.5 text-xs text-slate-400 mb-3">
          <span>{t("breadcrumb_workspace")}</span>
          <ChevronRight size={12} />
          <span className="text-slate-600 font-medium">
            {isAdmin ? t("title") : t("title_assignee")}
          </span>
        </div>
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-3">
            <div
              className="w-10 h-10 rounded-xl flex items-center justify-center shadow-sm flex-shrink-0"
              style={{ background: `linear-gradient(135deg, ${NAVY} 0%, ${NAVY2} 100%)` }}
            >
              <Inbox size={20} color="white" />
            </div>
            <div>
              <h1 className="text-xl font-bold text-slate-800">
                {isAdmin ? t("title") : t("title_assignee")}
              </h1>
              <p className="text-sm text-slate-500">
                {isAdmin ? t("subtitle") : t("subtitle_assignee")}
              </p>
            </div>
          </div>
          <div className="flex items-center gap-2">
            {newMailFlash && (
              <span className="flex items-center gap-1.5 text-xs font-medium text-emerald-600 bg-emerald-50 border border-emerald-200 px-2.5 py-1 rounded-full animate-pulse">
                <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 inline-block" />
                {t("new_mail")}
              </span>
            )}
            <div className="relative">
              <button
                onClick={handleRefresh}
                disabled={refreshing}
                className="flex items-center gap-1.5 px-3 py-2 rounded-lg border border-slate-200 text-sm text-slate-600 hover:bg-slate-50 transition disabled:opacity-50"
              >
                <RefreshCw size={14} className={refreshing ? "animate-spin" : ""} />
                {t("refresh")}
              </button>
              {/* Point vert "live" */}
              <span className="absolute -top-1 -right-1 w-2.5 h-2.5 rounded-full bg-emerald-400 border-2 border-white" title="Mise à jour automatique" />
            </div>
          </div>
        </div>
      </div>

      {/* Stats */}
      {data?.stats && (
        <div className="px-6 mb-4 flex-shrink-0">
          <StatsBar stats={data.stats} />
        </div>
      )}

      {/* Filters */}
      <div className="px-6 mb-4 flex-shrink-0 flex items-center gap-3 flex-wrap">
        <form
          onSubmit={handleSearch}
          className="flex-1 min-w-48 max-w-xs flex items-center gap-2 bg-white border border-slate-200 rounded-lg px-3 py-2"
        >
          <Search size={14} className="text-slate-400 flex-shrink-0" />
          <input
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            placeholder={t("search_placeholder")}
            className="flex-1 text-sm bg-transparent outline-none text-slate-700 placeholder:text-slate-400"
          />
          {searchInput && (
            <button
              type="button"
              onClick={() => { setSearchInput(""); setSearch(""); load({ search: "", page: 1 }); }}
            >
              <X size={13} className="text-slate-400 hover:text-slate-600" />
            </button>
          )}
        </form>

        <div className="flex items-center gap-1 bg-white border border-slate-200 rounded-lg p-1">
          {STATUS_FILTERS.map((f) => (
            <button
              key={f.value}
              onClick={() => handleStatusFilter(f.value)}
              className={cx(
                "px-3 py-1.5 rounded-md text-xs font-medium transition",
                statusFilter === f.value
                  ? "text-indigo-700 bg-indigo-50 shadow-sm"
                  : "text-slate-500 hover:text-slate-700 hover:bg-slate-50"
              )}
            >
              {f.label}
            </button>
          ))}
        </div>
      </div>

      {/* Main content */}
      <div className="flex-1 overflow-hidden flex min-h-0 px-6 pb-6 gap-4">
        {/* Table */}
        <div className={cx("flex flex-col min-w-0", selectedId ? "flex-[1.3]" : "flex-1")}>
          <div className="flex-1 overflow-y-auto bg-white rounded-xl border border-slate-200 shadow-sm">
            {loading ? (
              <div className="flex items-center justify-center py-16 text-slate-400">
                <RefreshCw size={20} className="animate-spin mr-2" /> {t("loading")}
              </div>
            ) : !data || data.results.length === 0 ? (
              <div className="text-center py-16">
                <Mail size={36} className="mx-auto text-slate-200 mb-3" />
                <p className="text-sm text-slate-500 font-medium">{t("empty")}</p>
                <p className="text-xs text-slate-400 mt-1">
                  {statusFilter || search ? t("empty_hint_filtered") : t("empty_hint")}
                </p>
              </div>
            ) : (
              <table className="w-full text-sm">
                <thead className="bg-slate-50 border-b border-slate-200 sticky top-0 z-10">
                  <tr>
                    <th className="text-left px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wide">
                      {t("col_sender")}
                    </th>
                    <th className="text-left px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wide">
                      {t("col_subject")}
                    </th>
                    <th className="text-left px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wide w-28">
                      {t("col_status")}
                    </th>
                    <th className="text-left px-4 py-3 text-xs font-semibold text-slate-500 uppercase tracking-wide w-24">
                      {t("col_date")}
                    </th>
                    <th className="w-8" />
                  </tr>
                </thead>
                <tbody className="divide-y divide-slate-100">
                  {data.results.map((mail) => (
                    <tr
                      key={mail.id}
                      onClick={() => setSelectedId(mail.id === selectedId ? null : mail.id)}
                      className={cx(
                        "cursor-pointer transition",
                        mail.id === selectedId
                          ? "bg-indigo-50 border-l-2 border-indigo-500"
                          : "hover:bg-slate-50"
                      )}
                    >
                      <td className="px-4 py-3">
                        <p className="font-medium text-slate-800 text-xs truncate max-w-[180px]">
                          {mail.from_name || mail.from_email}
                        </p>
                        <p className="text-xs text-slate-400 font-mono truncate max-w-[180px]">
                          {mail.from_name ? mail.from_email : ""}
                        </p>
                        {mail.mail_source && (
                          <p className="text-xs text-indigo-500 mt-0.5">
                            {mail.mail_source.client_name || mail.mail_source.email_or_domain}
                          </p>
                        )}
                      </td>
                      <td className="px-4 py-3">
                        <p className="text-slate-700 text-xs font-medium truncate max-w-[240px]">
                          {mail.subject || t("no_subject")}
                        </p>
                        {mail.attachments_count > 0 && (
                          <span className="inline-flex items-center gap-0.5 text-xs text-slate-400 mt-0.5">
                            <Paperclip size={10} /> {t("pj_count", { count: mail.attachments_count })}
                          </span>
                        )}
                        {mail.assigned_to && (
                          <p className="text-xs text-slate-400 mt-0.5 truncate">
                            → {mail.assigned_to.name} {mail.assigned_country && `(${mail.assigned_country})`}
                          </p>
                        )}
                      </td>
                      <td className="px-4 py-3">
                        <StatusBadge status={mail.status as MailStatus} />
                      </td>
                      <td className="px-4 py-3 text-xs text-slate-400 whitespace-nowrap">
                        {formatDate(mail.received_at, locale)}
                      </td>
                      <td className="px-4 py-3">
                        <ChevronRightIcon
                          size={14}
                          className={cx("text-slate-300 transition", mail.id === selectedId && "text-indigo-400")}
                        />
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>

          {/* Pagination — toujours visible quand il y a des résultats */}
          {data && data.count > 0 && (
            <div className="flex items-center justify-between mt-3 flex-wrap gap-2">
              <p className="text-xs text-slate-500">
                {t("pagination", { count: data.count, page, total: Math.max(1, totalPages) })}
              </p>
              {totalPages > 1 && (
                <div className="flex items-center gap-1">
                  <button
                    onClick={() => setPage((p) => Math.max(1, p - 1))}
                    disabled={page <= 1}
                    className="p-1.5 rounded-lg border border-slate-200 text-slate-500 hover:bg-slate-50 disabled:opacity-40 transition"
                    title="Page précédente"
                  >
                    <ChevronLeft size={14} />
                  </button>
                  {pageNumbers.map((n, i) =>
                    n === "..." ? (
                      <span key={`ellipsis-${i}`} className="px-1 text-xs text-slate-400">…</span>
                    ) : (
                      <button
                        key={n}
                        onClick={() => setPage(n)}
                        className={cx(
                          "min-w-[28px] h-7 rounded-lg text-xs font-medium transition border",
                          n === page
                            ? "border-indigo-500 bg-indigo-50 text-indigo-700"
                            : "border-slate-200 text-slate-500 hover:bg-slate-50"
                        )}
                      >
                        {n}
                      </button>
                    )
                  )}
                  <button
                    onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                    disabled={page >= totalPages}
                    className="p-1.5 rounded-lg border border-slate-200 text-slate-500 hover:bg-slate-50 disabled:opacity-40 transition"
                    title="Page suivante"
                  >
                    <ChevronRightIcon size={14} />
                  </button>
                </div>
              )}
            </div>
          )}
        </div>

        {/* Detail panel */}
        {selectedId && (
          <div className="flex-1 min-w-0 rounded-xl overflow-hidden border border-slate-200 shadow-sm">
            <DetailPanel
              mailId={selectedId}
              onClose={() => setSelectedId(null)}
              onAction={handleMailAction}
              isAdmin={isAdmin}
              currentUserId={me?.id}
            />
          </div>
        )}
      </div>
    </div>
  );
}
