'use client';

import { useEffect, useRef, useState, useMemo } from 'react';
import {
  ShieldCheck, Clock, ArrowRight, RotateCcw, Loader2,
  FileSpreadsheet, FileText, Presentation, Upload, X,
  Zap, CheckCircle2,
  Search, Languages, Wrench, Activity, Timer,
  Download, AlertTriangle, FileType,
  Image as ImageIcon,
} from 'lucide-react';
import { useFileUpload } from './useFileUpload';
import { useTranslationConfig } from './useTranslationConfig';
import { useTranslationSubmit } from './useTranslationSubmit';
import LanguageSelector from './LanguageSelector';
import { ProviderSelector } from './ProviderSelector';
import { GlossarySelector } from './GlossarySelector';
import { Switch } from '@/components/ui/switch';
import { useNotification } from '@/components/ui/notification';
import { useI18n } from '@/lib/i18n';
import { API_BASE } from '@/lib/config';
import { cn } from '@/lib/utils';

/* ── helpers ─────────────────────────────────────────────────────── */
const FILE_ICONS: Record<string, React.ElementType> = {
  xlsx: FileSpreadsheet, docx: FileText, pptx: Presentation, pdf: FileType,
};
const FILE_COLORS: Record<string, string> = {
  xlsx: 'text-green-500', docx: 'text-blue-500', pptx: 'text-orange-500', pdf: 'text-red-500',
};
function fmt(bytes: number) {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / 1048576).toFixed(1)} MB`;
}

/* ── Quality label based on provider ────────────────────────────── */
function getQualityLabel(t: (key: string) => string, provider: string | null | undefined): string {
  if (!provider) return t('dashboard.translate.highQuality');
  if (['openai', 'openrouter', 'openrouter_premium'].includes(provider)) return t('dashboard.translate.highQuality');
  if (provider === 'deepl') return t('dashboard.translate.highQuality');
  return t('dashboard.translate.quality');
}

/* ── Pipeline step keys ─────────────────────────────────────────── */
const PIPELINE_STEP_KEYS = [
  'dashboard.translate.pipeline.upload',
  'dashboard.translate.pipeline.analyze',
  'dashboard.translate.pipeline.translate',
  'dashboard.translate.pipeline.rebuild',
  'dashboard.translate.pipeline.finalize',
] as const;

const PIPELINE_ICONS = [Upload, Search, Languages, Wrench, CheckCircle2] as const;
const PIPELINE_STARTS = [0, 10, 25, 75, 92];

function getActiveStepIdx(progress: number) {
  for (let i = PIPELINE_STARTS.length - 1; i >= 0; i--) {
    if (progress >= PIPELINE_STARTS[i]) return i;
  }
  return 0;
}

function formatElapsed(totalSeconds: number) {
  const m = Math.floor(totalSeconds / 60);
  const s = totalSeconds % 60;
  return `${m}:${s.toString().padStart(2, '0')}`;
}

/* ── Page ────────────────────────────────────────────────────────── */
export default function TranslatePage() {
  const upload = useFileUpload();
  const config = useTranslationConfig(!!upload.file);
  const submit = useTranslationSubmit();
  const { error: showError } = useNotification();
  const { t } = useI18n();
  const lastErrorRef = useRef<string | null>(null);
  const replaceInputRef = useRef<HTMLInputElement>(null);
  const dropzoneInputRef = useRef<HTMLInputElement>(null);
  const [pdfMode, setPdfMode] = useState<'layout' | 'text_only'>('layout');
  const [elapsed, setElapsed] = useState(0);
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const isPdf = upload.file?.name.toLowerCase().endsWith('.pdf') ?? false;

  /* ── Human-friendly error messages ──────────────────────────── */
  const humanFriendlyError = (raw: string | null): string => {
    if (!raw) return t('dashboard.translate.error.unexpected');
    const r = raw.toLowerCase();
    if (r.includes('0 out of') || r.includes('0 textes') || r.includes('0 texts'))
      return t('dashboard.translate.error.noResult');
    if (r.includes('api key') || r.includes('api_key') || r.includes('unauthorized') || r.includes('401'))
      return t('dashboard.translate.error.apiKey');
    if (r.includes('quota') || r.includes('rate limit') || r.includes('429'))
      return t('dashboard.translate.error.quota');
    if (r.includes('timeout') || r.includes('timed out') || r.includes('connexion'))
      return t('dashboard.translate.error.timeout');
    if (r.includes('not found') || r.includes('404'))
      return t('dashboard.translate.error.sessionExpired');
    if (r.includes('empty') || r.includes('vide') || r.includes('no translatable'))
      return t('dashboard.translate.error.empty');
    if (r.includes('unsupported') || r.includes('format'))
      return t('dashboard.translate.error.unsupported');
    if (r.includes('lost connection') || r.includes('internet'))
      return t('dashboard.translate.error.connection');
    // Generic fallback — show raw but readable
    return t('dashboard.translate.error.generic', { detail: raw.charAt(0).toUpperCase() + raw.slice(1) });
  };

  useEffect(() => {
    if (submit.error && submit.error !== lastErrorRef.current) {
      lastErrorRef.current = submit.error;
      showError({ title: t('dashboard.translate.error.title'), description: humanFriendlyError(submit.error) });
    }
  }, [submit.error, showError]);

  // Elapsed timer
  useEffect(() => {
    if ((submit.status === 'processing' || submit.isSubmitting) && submit.status !== 'completed') {
      setElapsed(0);
      timerRef.current = setInterval(() => setElapsed((s) => s + 1), 1000);
    } else {
      if (timerRef.current) clearInterval(timerRef.current);
    }
    return () => { if (timerRef.current) clearInterval(timerRef.current); };
  }, [submit.status, submit.isSubmitting]);

  const handleTranslate = async () => {
    if (!upload.file || !config.isConfigValid) return;
    const cfg = config.getConfig();
    if (isPdf) cfg.pdfMode = pdfMode;
    await submit.submitTranslation(upload.file, cfg);
  };

  const handleRetry = async () => {
    submit.reset();
    // Small delay to ensure reset completes
    await new Promise(r => setTimeout(r, 50));
    await handleTranslate();
  };

  const handleNewTranslation = () => { submit.reset(); upload.removeFile(); setElapsed(0); };
  const handleDownload = async () => {
    if (!submit.jobId) return;
    const token = localStorage.getItem('token');
    const headers: Record<string, string> = {};
    if (token) headers['Authorization'] = `Bearer ${token}`;
    const response = await fetch(`${API_BASE}/api/v1/download/${submit.jobId}`, { headers });
    if (!response.ok) return;
    const contentDisposition = response.headers.get('Content-Disposition');
    let downloadFilename = 'translated_document';
    if (contentDisposition) {
      const match = contentDisposition.match(/filename\*?=['"]?(?:UTF-\d['"]*)?([^;\r\n"']+)/i);
      if (match?.[1]) downloadFilename = match[1];
    } else if (submit.fileName) {
      const ext = submit.fileName.split('.').pop() || '';
      const base = submit.fileName.replace(/\.[^.]+$/, '');
      downloadFilename = `${base}_translated.${ext}`;
    }
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = downloadFilename;
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };

  /* ── Derived states ──────────────────────────────────────────── */
  const isConfiguring = !!upload.file && submit.status === 'idle' && !submit.isSubmitting;
  const isProcessing = (submit.status === 'processing' || submit.isSubmitting) && submit.status !== 'completed';
  const isCompleted = submit.status === 'completed';
  const isFailed = submit.status === 'failed';

  const showUpload = !upload.file && !isProcessing && !isCompleted && !isFailed;
  const showConfiguring = isConfiguring;
  const showProcessing = isProcessing;
  const showComplete = isCompleted && !!submit.jobId;
  const showFailed = isFailed;

  const currentProvider = config.availableProviders.find(p => p.id === config.provider);
  const srcLangName = config.languages.find(l => l.code === config.sourceLang)?.name || config.sourceLang;
  const tgtLangName = config.languages.find(l => l.code === config.targetLang)?.name || config.targetLang;
  const activeStepIdx = getActiveStepIdx(submit.progress);
  const qualityLabel = useMemo(() => getQualityLabel(t, config.provider), [t, config.provider]);
  const fileTypeButtons = [
    { label: t('translate.fileType.word'), type: 'word' as const, icon: <FileText size={11} className="text-blue-500" /> },
    { label: t('translate.fileType.excel'), type: 'excel' as const, icon: <FileSpreadsheet size={11} className="text-green-500" /> },
    { label: t('translate.fileType.slides'), type: 'slides' as const, icon: <Presentation size={11} className="text-orange-500" /> },
    { label: t('translate.fileType.pdf'), type: 'pdf' as const, icon: <FileType size={11} className="text-red-500" /> },
  ];

  return (
    <div className="min-h-full p-6 pb-24 lg:pb-8 lg:p-8 dark:bg-[#0a0a0a] selection:bg-brand-accent/10">
      <div className="max-w-6xl mx-auto">

        {/* ── HEADER (Landing Page Style) ───────────────────────── */}
        <div className="mb-12">
          {showProcessing ? (
            <>
              <span className="accent-pill mb-4 block w-fit italic">{t('translate.header.processing')}</span>
              <h1 className="text-4xl md:text-5xl mb-3 leading-tight text-brand-dark dark:text-white font-serif font-medium tracking-tight">
                {(() => {
                  const full = t('translate.header.aiActive');
                  const i = full.lastIndexOf(' ');
                  return <>{i === -1 ? full : <>{full.slice(0, i)} <span className="italic">{full.slice(i + 1)}</span></>}</>;
                })()}
              </h1>
              <p className="text-brand-dark/50 dark:text-white/50 text-sm font-light leading-relaxed">
                {t('translate.header.aiActiveDesc')}
              </p>
            </>
          ) : showComplete ? (
            <>
              <span className="accent-pill mb-4 block w-fit italic">{t('translate.header.completed')}</span>
              <h1 className="text-4xl md:text-5xl mb-3 leading-tight text-brand-dark dark:text-white font-serif font-medium tracking-tight">
                {(() => {
                  const full = t('translate.header.completedTitle');
                  const i = full.lastIndexOf(' ');
                  return <>{i === -1 ? full : <>{full.slice(0, i)} <span className="italic">{full.slice(i + 1)}</span></>}</>;
                })()}
              </h1>
              <p className="text-brand-dark/50 dark:text-white/50 text-sm font-light leading-relaxed truncate max-w-xl">
                {submit.fileName}
              </p>
            </>
          ) : (
            <>
              <span className="accent-pill mb-4 block w-fit">{t('translate.header.proSpace')}</span>
              <h1 className="text-4xl md:text-5xl mb-3 leading-tight text-brand-dark dark:text-white font-serif font-medium tracking-tight">
                {(() => {
                  const full = t('translate.header.translateDoc');
                  const i = full.lastIndexOf(' ');
                  return <>{i === -1 ? full : <>{full.slice(0, i)} <span className="italic">{full.slice(i + 1)}</span></>}</>;
                })()}
              </h1>
              <p className="text-brand-dark/50 dark:text-white/50 text-sm font-light leading-relaxed">
                {t('translate.header.translateDocDesc')}
              </p>
            </>
          )}
        </div>

        {/* ── GRID: 7/5 SPLIT ───────────────────────────────────── */}
        <div className="grid lg:grid-cols-12 gap-8 items-start">

          {/* ═══════════════════════════════════════════════════════ */}
          {/* LEFT (7 cols) — content swaps based on state            */}
          {/* ═══════════════════════════════════════════════════════ */}
          <div className="lg:col-span-7 space-y-6">

            {/* ── UPLOAD STATE: Editorial Dropzone ──────────────── */}
            {showUpload && (
              <div
                className="relative bg-white border-2 border-dashed border-brand-accent/15 dark:border-white/10 rounded-[32px] p-12 flex flex-col items-center justify-center text-center group cursor-pointer hover:border-brand-accent/40 dark:hover:border-brand-accent/40 hover:bg-brand-muted/10 dark:hover:bg-brand-muted/5 transition-all shadow-editorial dark:bg-[#141414]"
                onDragOver={upload.handleDragOver}
                onDragLeave={upload.handleDragLeave}
                onDrop={upload.handleDrop}
                onClick={() => dropzoneInputRef.current?.click()}
              >
                <div className="absolute top-4 right-4 text-[8px] font-bold uppercase tracking-widest text-brand-dark/30 dark:text-white/30 bg-brand-muted dark:bg-white/5 px-3 py-1 rounded-full border border-black/[0.03] dark:border-white/[0.03]">
                  {t('translate.upload.nativeFormat')}
                </div>

                <div className="w-16 h-16 bg-brand-muted dark:bg-white/5 rounded-2xl flex items-center justify-center text-brand-accent group-hover:scale-105 group-hover:bg-brand-dark dark:group-hover:bg-brand-accent group-hover:text-white dark:group-hover:text-brand-dark transition-all duration-300 mb-6 shadow-sm">
                  <Upload size={24} />
                </div>

                <h3 className="text-xl font-bold tracking-tight mb-2 text-brand-dark dark:text-white uppercase">
                  {t('landing.translate.dropHere')}
                </h3>
                <p className="text-xs text-brand-dark/40 dark:text-white/40 mb-8 font-medium">
                  {t('landing.translate.supportedFormats')}
                </p>

                {/* Simulated file triggers */}
                <div className="flex flex-wrap justify-center gap-2.5" onClick={(e) => e.stopPropagation()}>
                  {fileTypeButtons.map(f => (
                    <button
                      key={f.type}
                      type="button"
                      onClick={() => upload.setMockFile(f.type)}
                      className="flex items-center gap-2 px-3.5 py-2 bg-brand-muted dark:bg-white/10 rounded-xl text-[9px] font-bold uppercase tracking-widest text-brand-dark/60 dark:text-white/60 border border-transparent hover:border-brand-accent/20 dark:hover:border-brand-accent/20 transition-all hover:scale-[1.02] active:scale-[0.98]"
                    >
                      {f.icon} {f.label}
                    </button>
                  ))}
                </div>

                {/* Hidden file input for click-to-upload */}
                <input
                  ref={dropzoneInputRef}
                  type="file"
                  accept=".xlsx,.docx,.pptx,.pdf"
                  className="hidden"
                  onChange={upload.handleFileSelect}
                />
              </div>
            )}

            {/* ── CONFIGURING STATE: File indicator ──────────────── */}
            {showConfiguring && (
              <div className="editorial-card p-8 bg-white border-none shadow-editorial dark:bg-[#141414] space-y-6">
                <h4 className="text-[10px] font-bold uppercase tracking-[0.2em] text-brand-dark/30 dark:text-white/30 border-b border-black/5 dark:border-white/5 pb-4">
                  {t('landing.translate.sourceDocument') || 'Document Source'}
                </h4>
                <FileStrip file={upload.file!} onRemove={upload.removeFile} onReplace={() => replaceInputRef.current?.click()} t={t} />
                <input ref={replaceInputRef} type="file" accept=".xlsx,.docx,.pptx,.pdf" className="hidden" onChange={upload.handleFileSelect} />
                {upload.error && <p className="mt-2 text-xs text-destructive">{upload.error}</p>}
              </div>
            )}

            {/* ── Desktop Submit Button & Actions (shown when not processing/complete) ── */}
            {(showUpload || showConfiguring) && (
              <div className="hidden lg:block editorial-card p-6 bg-white dark:bg-[#141414] border-none shadow-editorial space-y-4">
                <button
                  disabled={!config.isConfigValid || submit.isSubmitting || !upload.file}
                  onClick={handleTranslate}
                  className={cn(
                    'w-full py-4 text-[10px] font-bold uppercase tracking-[0.25em] flex items-center justify-center gap-2 rounded-2xl transition-all shadow-sm active:scale-98',
                    config.isConfigValid && upload.file && !submit.isSubmitting
                      ? 'bg-brand-dark text-white hover:bg-brand-accent dark:bg-brand-accent dark:text-brand-dark hover:shadow-xl cursor-pointer'
                      : 'bg-brand-muted/70 text-brand-dark/25 dark:bg-white/5 dark:text-white/20 cursor-not-allowed border border-black/[0.03] dark:border-white/[0.03]'
                  )}
                >
                  {submit.isSubmitting ? (
                    <><Loader2 className="size-4 animate-spin" /> {t('translate.submit')}</>
                  ) : (
                    <>{t('translate.startTranslation')} <ArrowRight size={13} className={upload.file ? 'text-brand-accent' : 'opacity-20'} /></>
                  )}
                </button>

                {!upload.file && (
                  <p className="text-center text-[8px] text-brand-dark/30 dark:text-white/30 font-bold uppercase tracking-widest">{t('translate.pleaseLoadFile')}</p>
                )}
                {upload.file && !config.targetLang && (
                  <p className="text-center text-[8px] text-brand-dark/30 dark:text-white/30 font-bold uppercase tracking-widest">{t('translate.chooseTargetLang')}</p>
                )}

                <div className="flex justify-between text-[7.5px] font-bold uppercase tracking-[0.15em] text-brand-dark/30 dark:text-white/30 border-t border-black/5 dark:border-white/5 pt-4">
                  <span className="flex items-center gap-1.5">
                    <ShieldCheck size={12} /> {t('landing.translate.zeroRetention') || 'Rétention Zéro'}
                  </span>
                  <span className="flex items-center gap-1.5">
                    <Clock size={12} /> {t('landing.translate.filesDeleted') || 'Fichiers supprimés post-traitement'}
                  </span>
                </div>
              </div>
            )}

            {/* ── PROCESSING STATE: Rich progress ───────────────── */}
            {showProcessing && (
              <div className="editorial-card p-12 h-full border-none shadow-editorial bg-white dark:bg-[#141414] space-y-12">
                <div className="flex items-center gap-6">
                  <div className="w-16 h-16 bg-brand-muted dark:bg-white/5 rounded-2xl flex items-center justify-center text-brand-accent border border-brand-accent/10 animate-pulse">
                    <Activity size={32} />
                  </div>
                  <div className="text-left">
                    <h3 className="text-2xl font-serif font-medium text-brand-dark dark:text-white tracking-tight">
                      {t('translate.contextEngineActive')}
                    </h3>
                    <p className="text-[10px] text-brand-dark/30 dark:text-white/30 font-bold uppercase tracking-widest mt-1">
                      {submit.fileName || upload.file?.name}
                    </p>
                  </div>
                </div>

                {/* Progress Line with step icons */}
                <div className="relative h-2 bg-brand-muted dark:bg-white/5 rounded-full my-12">
                  <div className="absolute top-1/2 left-0 w-full -translate-y-1/2 flex justify-between px-2">
                    {PIPELINE_ICONS.map((Icon, i) => (
                      <div
                        key={i}
                        className={cn(
                          'w-12 h-12 rounded-2xl border-4 border-white dark:border-[#141414] shadow-xl flex items-center justify-center z-10 transition-all duration-500',
                          submit.progress > (i * 25)
                            ? 'bg-brand-dark text-white scale-110 dark:bg-brand-accent dark:text-brand-dark font-bold'
                            : 'bg-brand-muted text-brand-dark/25 dark:bg-[#1f1f1f] dark:text-white/20'
                        )}
                      >
                        <Icon size={18} />
                      </div>
                    ))}
                  </div>
                  <div
                    className="absolute top-0 left-0 h-full bg-brand-accent shadow-[0_0_20px_rgba(197,161,122,0.4)] transition-all duration-700 rounded-full"
                    style={{ width: `${Math.max(0, submit.progress)}%` }}
                  />
                </div>

                <div className="flex justify-between items-end mt-12 pt-6">
                  <span className="text-[10px] font-bold text-brand-dark/30 dark:text-white/30 uppercase tracking-[0.3em]">
                    {activeStepIdx < 2 ? t('translate.phase1') : t('translate.phase2')}
                  </span>
                  <span className="text-7xl font-serif font-medium text-brand-dark dark:text-white leading-none">
                    {Math.round(submit.progress)}%
                  </span>
                </div>

                <div className="grid grid-cols-4 gap-4 pt-12 border-t border-black/5 dark:border-white/5">
                  <StatBox icon={<FileText size={18} />} value={`${Math.round(submit.progress)}%`} label={t('translate.stat.segments')} />
                  <StatBox icon={<Zap size={18} />} value="99.9%" label={t('translate.stat.precision')} />
                  <StatBox icon={<Clock size={18} />} value="Turbo" label={t('translate.stat.speedLabel')} />
                  <StatBox icon={<Activity size={18} />} value={formatElapsed(elapsed)} label={t('translate.stat.time')} />
                </div>
              </div>
            )}

            {/* ── COMPLETE STATE: Success with download ─────────── */}
            {showComplete && (
              <div className="editorial-card p-12 h-full border-none shadow-editorial bg-white dark:bg-[#141414] flex flex-col space-y-12">
                <div className="p-8 bg-brand-accent/5 border border-brand-accent/10 rounded-[32px] flex items-center justify-between shadow-inner dark:bg-brand-accent/10 dark:border-brand-accent/20">
                  <div className="flex items-center gap-6">
                    <div className="w-14 h-14 bg-brand-accent rounded-full flex items-center justify-center text-white shadow-xl">
                      <CheckCircle2 size={28} />
                    </div>
                    <div className="text-left">
                      <p className="text-[13px] font-bold uppercase tracking-[0.1em] text-brand-dark dark:text-white">
                        {t('translate.header.completedTitle')}
                      </p>
                      <p className="text-[10px] text-brand-dark/40 dark:text-white/40 font-bold uppercase mt-1 tracking-widest max-w-[300px] truncate">
                        {submit.fileName}
                      </p>
                    </div>
                  </div>
                  <span className="px-5 py-2 bg-white dark:bg-[#1a1a1a] rounded-full text-[9px] font-bold uppercase tracking-widest text-brand-accent border border-brand-accent/20 shadow-sm shrink-0">
                    {t('translate.complete.masterQuality')}
                  </span>
                </div>

                <div className="flex-1 flex flex-col items-center justify-center py-16 bg-brand-muted/20 dark:bg-white/5 rounded-[40px] border border-black/5 dark:border-white/5">
                  <button
                    onClick={handleDownload}
                    className="premium-button px-24 py-6 text-xl !rounded-full flex items-center gap-6 mb-8 group cursor-pointer hover:scale-[1.02] active:scale-95"
                  >
                    <Download size={28} className="group-hover:translate-y-1 transition-transform" />
                    {t('translate.download')}
                  </button>
                  <button
                    onClick={handleNewTranslation}
                    className="text-[10px] font-bold uppercase tracking-[0.3em] text-brand-dark/30 hover:text-brand-dark dark:text-white/30 dark:hover:text-white transition-colors"
                  >
                    {t('translate.newTranslation')}
                  </button>
                </div>
              </div>
            )}

            {/* ── FAILED STATE ───────────────────────────────────── */}
            {showFailed && (
              <div className="editorial-card p-10 bg-white dark:bg-[#141414] border-none shadow-editorial space-y-6">
                <div className="rounded-[24px] bg-red-50 border-2 border-red-200 dark:bg-red-950/20 dark:border-red-900/30 p-6" role="alert">
                  <div className="flex items-start gap-4">
                    <div className="w-10 h-10 rounded-2xl bg-red-100 dark:bg-red-900/30 flex items-center justify-center shrink-0">
                      <AlertTriangle className="size-5 text-red-500" />
                    </div>
                    <div className="flex-1 min-w-0 text-left">
                      <p className="text-sm font-bold uppercase tracking-tight text-red-600 dark:text-red-400 mb-2">{t('translate.failedTitle')}</p>
                      <p className="text-xs text-red-600/80 dark:text-red-300/80 leading-relaxed font-medium">{humanFriendlyError(submit.error)}</p>
                    </div>
                  </div>
                </div>

                {(submit.fileName || upload.file?.name) && upload.file && (
                  <FileStrip file={upload.file} onRemove={upload.removeFile} onReplace={() => replaceInputRef.current?.click()} t={t} />
                )}
                <input ref={replaceInputRef} type="file" accept=".xlsx,.docx,.pptx,.pdf" className="hidden" onChange={upload.handleFileSelect} />

                <div className="flex flex-col gap-3">
                  {upload.file && config.isConfigValid && (
                    <button
                      onClick={handleRetry}
                      className="premium-button w-full py-5 text-[12px] uppercase tracking-[0.25em] flex items-center justify-center gap-3 !rounded-2xl cursor-pointer hover:scale-[1.01] active:scale-98"
                    >
                      <RotateCcw size={18} />
                      {t('translate.retry')}
                    </button>
                  )}
                  <button
                    onClick={handleNewTranslation}
                    className="w-full py-4 border border-black/10 dark:border-white/10 rounded-2xl text-[10px] font-bold uppercase tracking-[0.25em] text-brand-dark/50 dark:text-white/50 hover:text-brand-dark dark:hover:text-white transition-all flex items-center justify-center gap-3 cursor-pointer hover:bg-brand-muted/30 dark:hover:bg-white/5"
                  >
                    <Upload size={16} />
                    {t('translate.uploadAnother')}
                  </button>
                </div>
              </div>
            )}
          </div>

          {/* ═══════════════════════════════════════════════════════ */}
          {/* RIGHT (5 cols) — Config / Monitor / Summary              */}
          {/* ═══════════════════════════════════════════════════════ */}
          <div className="lg:col-span-5 space-y-6">

            {/* ── CONFIG (upload / configuring / failed) ──────────── */}
            {(showUpload || showConfiguring || showFailed) && (
              <div className="editorial-card bg-white dark:bg-[#141414] border-none shadow-editorial overflow-hidden flex flex-col lg:sticky lg:top-8 lg:max-h-[calc(100vh-6rem)]">
                {/* Scrollable config content */}
                <div className="flex-1 overflow-y-auto p-6 space-y-5">
                  <h4 className="text-[10px] font-bold uppercase tracking-[0.2em] text-brand-dark/30 dark:text-white/30 pb-3 border-b border-black/[0.03] dark:border-white/[0.03]">
                    {t('landing.translate.configuration') || 'Configuration'}
                  </h4>

                  <div className="space-y-6">
                    <LanguageSelector
                      sourceLang={config.sourceLang} targetLang={config.targetLang}
                      languages={config.languages} isLoading={config.isLoadingLanguages}
                      error={config.languagesError} onSourceChange={config.setSourceLang}
                      onTargetChange={config.setTargetLang}
                    />

                    <ProviderSelector
                      provider={config.provider} onProviderChange={config.setProvider}
                      availableProviders={config.availableProviders} isLoadingProviders={config.isLoadingProviders}
                      isPro={config.isPro}
                    />

                    {/* Active mode badge */}
                    {config.provider && (
                      <div className="flex items-center gap-2">
                        <span className={cn(
                          "inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[9px] font-bold uppercase tracking-[0.1em]",
                          config.mode === 'llm'
                            ? "bg-brand-accent/10 text-brand-accent border border-brand-accent/20"
                            : "bg-brand-muted/50 text-brand-dark/40 dark:bg-white/5 dark:text-white/40 border border-transparent"
                        )}>
                          {config.mode === 'llm' ? (
                            <><Zap size={10} /> {t('dashboard.translate.modeAI')}</>
                          ) : (
                            <><Languages size={10} /> {t('dashboard.translate.modeClassic')}</>
                          )}
                        </span>
                        {config.mode === 'classic' && config.isPro && (
                          <span className="text-[9px] text-brand-dark/40 dark:text-white/40 italic font-medium leading-none">
                            {t('dashboard.translate.glossaryLLMHint')}
                          </span>
                        )}
                      </div>
                    )}

                    {/* Glossary selector */}
                    <GlossarySelector
                      sourceLang={config.sourceLang}
                      targetLang={config.targetLang}
                      isPro={config.isPro}
                      mode={config.mode}
                      glossaryId={config.glossaryId}
                      onChange={config.setGlossaryId}
                      disabled={submit.isSubmitting}
                    />

                    {/* Translate Images */}
                    <div className="bg-brand-muted/30 dark:bg-white/[0.02] border border-black/[0.03] dark:border-white/[0.03] p-4 rounded-xl space-y-3">
                      <div className="flex justify-between items-center">
                        <div className="flex items-center gap-2">
                          <ImageIcon className="size-3.5 text-brand-accent shrink-0" />
                          <span className="text-[9px] font-black uppercase tracking-[0.1em] text-brand-dark dark:text-white">
                            {t('dashboard.translate.translateImages') || "Traduire les images"}
                          </span>
                        </div>
                        <Switch
                          checked={config.translateImages && config.mode === 'llm'}
                          onCheckedChange={config.setTranslateImages}
                          disabled={submit.isSubmitting || config.mode === 'classic'}
                          aria-label={t('dashboard.translate.translateImages') || "Traduire les images"}
                        />
                      </div>
                      
                      {config.mode === 'classic' ? (
                        <div className="p-2.5 bg-brand-dark/5 dark:bg-white/5 rounded-lg text-center">
                          <span className="text-[7.5px] font-black uppercase opacity-45 block">
                            {t('translate.unavailableStandard')}
                          </span>
                        </div>
                      ) : (
                        <div className="px-1">
                          <span className="text-[7.5px] font-medium text-brand-dark/50 dark:text-white/50 block leading-normal">
                            {t('dashboard.translate.translateImagesDesc') || "Détecter et traduire automatiquement les textes incrustés dans vos images."}
                          </span>
                        </div>
                      )}
                    </div>

                    {/* PDF mode selector */}
                    {isPdf && (
                      <div className="space-y-2 text-left">
                        <label className="text-[9px] font-bold text-brand-dark/40 dark:text-white/40 uppercase tracking-[0.15em] block mb-2">
                          {t('dashboard.translate.pdfMode.title') || 'Mode PDF'}
                        </label>
                        <div className="grid grid-cols-2 gap-2">
                          <button
                            type="button"
                            onClick={() => setPdfMode('layout')}
                            className={cn(
                              'flex flex-col items-start rounded-2xl border p-3.5 text-start transition-all',
                              pdfMode === 'layout'
                                ? 'border-brand-accent bg-brand-accent/5'
                                : 'border-black/5 bg-brand-muted/30 hover:border-brand-accent/20 dark:border-white/10 dark:bg-white/5'
                            )}
                          >
                            <div className="flex items-center gap-2 text-[10px] font-bold uppercase tracking-tight text-brand-dark dark:text-white">
                              <FileText className="size-3.5 text-brand-accent" />
                              {t('dashboard.translate.pdfMode.preserveLayout') || 'Mise en page'}
                            </div>
                            <p className="mt-1.5 text-[8px] text-brand-dark/40 dark:text-white/40 font-bold uppercase tracking-widest leading-relaxed">
                              {t('translate.preserveLayoutDesc')}
                            </p>
                          </button>
                          <button
                            type="button"
                            onClick={() => setPdfMode('text_only')}
                            className={cn(
                              'flex flex-col items-start rounded-2xl border p-3.5 text-start transition-all',
                              pdfMode === 'text_only'
                                ? 'border-brand-accent bg-brand-accent/5'
                                : 'border-black/5 bg-brand-muted/30 hover:border-brand-accent/20 dark:border-white/10 dark:bg-white/5'
                            )}
                          >
                            <div className="flex items-center gap-2 text-[10px] font-bold uppercase tracking-tight text-brand-dark dark:text-white">
                              <Languages className="size-3.5 text-brand-accent" />
                              {t('translate.textOnly')}
                            </div>
                            <p className="mt-1.5 text-[8px] text-brand-dark/40 dark:text-white/40 font-bold uppercase tracking-widest leading-relaxed">
                              {t('translate.textOnlyDesc')}
                            </p>
                          </button>
                        </div>
                      </div>
                    )}
                  </div>
                </div>
              </div>
            )}

            {/* ── MONITOR (processing) ────────────────────────────── */}
            {showProcessing && (
              <div className="editorial-card p-6 bg-white dark:bg-[#141414] border-none shadow-editorial h-full">
                <h4 className="text-[10px] font-bold uppercase tracking-[0.2em] mb-8 flex items-center gap-3 text-brand-dark/45 dark:text-white/45 pb-3 border-b border-black/[0.03] dark:border-white/[0.03]">
                  <div className="w-2 h-2 bg-brand-accent rounded-full animate-ping" />
                  {t('translate.monitor')}
                </h4>

                {/* File summary */}
                {(submit.fileName || upload.file?.name) && (
                  <div className="p-4 bg-brand-muted dark:bg-white/5 rounded-2xl mb-8 flex items-center gap-4 border border-black/5 dark:border-white/5">
                    <div className="w-10 h-10 bg-white dark:bg-[#1a1a1a] rounded-xl flex items-center justify-center text-brand-accent shadow-sm">
                      {(() => {
                        const name = submit.fileName || upload.file?.name || '';
                        const ext = name.split('.').pop()?.toLowerCase() ?? '';
                        const FileIcon = FILE_ICONS[ext] ?? FileText;
                        return <FileIcon size={20} className={FILE_COLORS[ext]} />;
                      })()}
                    </div>
                    <div className="overflow-hidden text-left">
                      <p className="text-[11px] font-bold truncate text-brand-dark dark:text-white">
                        {submit.fileName || upload.file?.name}
                      </p>
                      <p className="text-[9px] text-brand-dark/45 dark:text-white/45 font-bold uppercase tracking-widest mt-1">
                        {upload.file ? `${fmt(upload.file.size)} ` : ''}{(submit.fileName || upload.file?.name || '').split('.').pop()?.toUpperCase()}
                      </p>
                    </div>
                  </div>
                )}

                {/* Config summary */}
                <div className="space-y-6 mb-8 px-2 text-left">
                  <div className="flex justify-between items-center text-[9px] font-bold uppercase tracking-[0.2em] text-brand-dark/40 dark:text-white/40">
                    <span>Source</span>
                    <span className="text-brand-dark dark:text-white">{srcLangName.toUpperCase()}</span>
                  </div>
                  <div className="flex justify-between items-center text-[9px] font-bold uppercase tracking-[0.2em] text-brand-dark/40 dark:text-white/40">
                    <span>Cible</span>
                    <span className="text-brand-accent">{tgtLangName.toUpperCase()}</span>
                  </div>
                  {currentProvider && (
                    <div className="flex justify-between items-center text-[9px] font-bold uppercase tracking-[0.2em] text-brand-dark/40 dark:text-white/40">
                      <span>Moteur</span>
                      <span className="text-brand-dark dark:text-white">{currentProvider.label.toUpperCase()}</span>
                    </div>
                  )}
                </div>

                {/* Quality progress */}
                <div className="pt-6 border-t border-black/5 dark:border-white/5 text-left">
                  <div className="flex justify-between text-[9px] font-bold uppercase tracking-[0.2em] mb-3">
                    <span className="text-brand-dark/40 dark:text-white/40">{t('translate.layoutIntegrity')}</span>
                    <span className="text-brand-accent">{t('translate.secureHundred')}</span>
                  </div>
                  <div className="h-2 bg-brand-muted dark:bg-white/5 rounded-full overflow-hidden p-0.5">
                    <div
                      className="h-full bg-brand-accent rounded-full transition-all duration-700"
                      style={{ width: `${Math.min(95, 40 + submit.progress * 0.55)}%` }}
                    />
                  </div>
                </div>

                <button
                  onClick={handleNewTranslation}
                  className="w-full mt-12 py-4 border border-red-100 text-red-500 rounded-2xl text-[9px] font-bold uppercase tracking-[0.2em] flex items-center justify-center gap-2 hover:bg-red-50 dark:border-red-950/20 dark:hover:bg-red-950/30 transition-all cursor-pointer"
                >
                  {t('translate.cancelProcess')}
                </button>
              </div>
            )}

            {/* ── SUMMARY (complete) ──────────────────────────────── */}
            {showComplete && (
              <div className="editorial-card p-6 bg-white dark:bg-[#141414] border-none shadow-editorial h-full">
                <h4 className="text-[10px] font-bold uppercase tracking-[0.2em] mb-8 flex items-center gap-3 text-brand-dark/45 dark:text-white/45 pb-3 border-b border-black/[0.03] dark:border-white/[0.03]">
                  <CheckCircle2 size={14} className="text-emerald-500" />
                  {t('translate.summary')}
                </h4>

                <div className="space-y-6 mb-8 px-2 text-left">
                  <div className="flex justify-between items-center text-[9px] font-bold uppercase tracking-[0.2em] text-brand-dark/40 dark:text-white/40">
                    <span>Source</span>
                    <span className="text-brand-dark dark:text-white">{srcLangName.toUpperCase()}</span>
                  </div>
                  <div className="flex justify-between items-center text-[9px] font-bold uppercase tracking-[0.2em] text-brand-dark/40 dark:text-white/40">
                    <span>Cible</span>
                    <span className="text-brand-accent">{tgtLangName.toUpperCase()}</span>
                  </div>
                  {currentProvider && (
                    <div className="flex justify-between items-center text-[9px] font-bold uppercase tracking-[0.2em] text-brand-dark/40 dark:text-white/40">
                      <span>Moteur</span>
                      <span className="text-brand-dark dark:text-white">{currentProvider.label.toUpperCase()}</span>
                    </div>
                  )}
                </div>

                <div className="pt-6 border-t border-black/5 dark:border-white/5 text-left">
                  <div className="flex justify-between text-[9px] font-bold uppercase tracking-[0.2em] mb-3">
                    <span className="text-brand-dark/40 dark:text-white/40">{t('translate.layoutIntegrity')}</span>
                    <span className="text-brand-accent">{t('translate.okHundred')}</span>
                  </div>
                  <div className="h-2 bg-brand-muted dark:bg-white/5 rounded-full overflow-hidden p-0.5">
                    <div className="h-full bg-brand-accent rounded-full" style={{ width: '100%' }} />
                  </div>
                </div>
              </div>
            )}
          </div>
        </div>

        {/* ── MOMENTO PROMO BANNER ──────────────────────────────── */}
        {(showUpload || showConfiguring || showFailed) && (
          <div className="mt-12 editorial-card p-10 bg-white dark:bg-[#141414] border-none shadow-editorial flex flex-col md:flex-row items-center gap-8 group overflow-hidden relative">
            <div className="absolute -right-20 -top-20 w-64 h-64 bg-brand-accent/5 rounded-full blur-3xl group-hover:bg-brand-accent/10 transition-colors pointer-events-none" />

            <div className="w-16 h-16 bg-brand-dark dark:bg-brand-accent rounded-[24px] flex items-center justify-center text-white dark:text-brand-dark text-3xl font-black shadow-2xl shrink-0 group-hover:rotate-6 transition-transform duration-500">
              M
            </div>

            <div className="flex-1 text-left">
              <div className="flex items-center gap-3 mb-2">
                <span className="accent-pill !px-2.5 !py-0.5 text-[8px] italic">Ecosystème Wordly</span>
                <h3 className="text-xl font-bold tracking-tight text-brand-dark dark:text-white uppercase">{t('memento.title')}</h3>
              </div>
              <p className="text-xs text-brand-dark/40 dark:text-white/40 font-light leading-relaxed max-w-2xl">
                {t('memento.slogan')}
              </p>
            </div>

            <div className="flex flex-col sm:flex-row gap-3 shrink-0 w-full md:w-auto">
              <button className="premium-button px-8 py-3.5 text-[9px] uppercase tracking-widest !rounded-xl text-center">
                {t('memento.ctaFree')}
              </button>
              <button className="px-8 py-3.5 border border-black/5 bg-brand-muted text-brand-dark/40 rounded-xl text-[9px] font-bold uppercase tracking-widest hover:text-brand-dark dark:border-white/5 dark:bg-white/5 dark:text-white/40 dark:hover:text-white hover:bg-brand-muted/70 transition-all text-center">
                {t('memento.ctaMore')}
              </button>
            </div>
          </div>
        )}

        {/* Mobile Sticky Action Bar (visible on mobile, hidden on lg) */}
        {(showUpload || showConfiguring) && (
          <div className="block lg:hidden fixed bottom-0 left-0 right-0 z-40 p-4 bg-white/90 dark:bg-[#141414]/90 backdrop-blur-md border-t border-black/5 dark:border-white/5 shadow-lg">
            <button
              disabled={!config.isConfigValid || submit.isSubmitting || !upload.file}
              onClick={handleTranslate}
              className={cn(
                'w-full py-4 text-[10px] font-bold uppercase tracking-[0.2em] flex items-center justify-center gap-2 rounded-xl transition-all active:scale-98',
                config.isConfigValid && upload.file && !submit.isSubmitting
                  ? 'bg-brand-dark text-white hover:bg-brand-accent dark:bg-brand-accent dark:text-brand-dark cursor-pointer'
                  : 'bg-brand-muted/70 text-brand-dark/25 dark:bg-white/5 dark:text-white/20 cursor-not-allowed'
              )}
            >
              {submit.isSubmitting ? (
                <><Loader2 className="size-4 animate-spin" /> {t('translate.submit')}</>
              ) : (
                <>{t('translate.startTranslation')} <ArrowRight size={13} className={upload.file ? 'text-brand-accent' : 'opacity-20'} /></>
              )}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

/* ═══ Sub-components ═══════════════════════════════════════════════ */

/** Compact file strip */
function FileStrip({ file, onRemove, onReplace, t }: { file: File; onRemove: () => void; onReplace: () => void; t: (key: string) => string }) {
  const ext = file.name.split('.').pop()?.toLowerCase() ?? '';
  const FileIcon = FILE_ICONS[ext] ?? FileText;
  const color = FILE_COLORS[ext] ?? 'text-muted-foreground';
  return (
    <div className="flex items-center gap-3 rounded-[24px] border border-black/5 bg-brand-muted/30 px-4 py-3 dark:border-white/5 dark:bg-white/5">
      <FileIcon className={`size-5 shrink-0 ${color}`} />
      <div className="flex min-w-0 flex-1 flex-col">
        <span className="truncate text-[11px] font-black uppercase tracking-tight text-brand-dark dark:text-white">{file.name}</span>
        <span className="text-[10px] text-brand-dark/45 font-bold uppercase tracking-widest dark:text-white/45">{fmt(file.size)} .{ext.toUpperCase()}</span>
      </div>
      <button type="button" onClick={onReplace} className="flex shrink-0 items-center gap-1 rounded-xl px-2 py-1 text-[10px] font-black uppercase tracking-widest text-brand-dark/50 transition hover:bg-brand-muted hover:text-brand-dark dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white">
        <Upload className="size-3.5" />{t('dashboard.translate.replace')}
      </button>
      <button type="button" aria-label="Remove" onClick={onRemove} className="flex size-7 shrink-0 items-center justify-center rounded-xl text-brand-dark/40 transition hover:bg-brand-muted hover:text-brand-dark dark:text-white/40 dark:hover:bg-white/10 dark:hover:text-white">
        <X className="size-4" />
      </button>
    </div>
  );
}

/** Pipeline stepper */
function PipelineStepper({ activeIdx, t }: { activeIdx: number; t: (key: string) => string }) {
  return (
    <div className="flex items-start justify-between">
      {PIPELINE_STEP_KEYS.map((stepKey, i) => {
        const isActive = i === activeIdx;
        const isDone = i < activeIdx;
        const Icon = PIPELINE_ICONS[i];
        return (
          <div key={stepKey} className="flex flex-col items-center gap-1.5 relative" style={{ flex: i < PIPELINE_STEP_KEYS.length - 1 ? 1 : 'none' }}>
            <div className="flex items-center w-full">
              <div className={cn(
                'flex size-9 shrink-0 items-center justify-center rounded-full transition-all duration-500',
                isDone
                  ? 'bg-primary text-primary-foreground shadow-md shadow-primary/20'
                  : isActive
                  ? 'bg-primary text-primary-foreground shadow-lg shadow-primary/25 ring-[3px] ring-primary/20'
                  : 'bg-muted text-muted-foreground',
              )}>
                {isDone ? <CheckCircle2 className="size-4" /> : <Icon className={cn('size-4', isActive && 'animate-pulse')} />}
              </div>
              {i < PIPELINE_STEP_KEYS.length - 1 && (
                <div className={cn('mx-1 h-[2px] flex-1 rounded-full transition-colors duration-500', i < activeIdx ? 'bg-primary' : 'bg-border')} />
              )}
            </div>
            <span className={cn('text-[11px] font-medium transition-colors', isDone || isActive ? 'text-primary' : 'text-muted-foreground')}>
              {t(stepKey)}
            </span>
          </div>
        );
      })}
    </div>
  );
}

/** Small stat box */
function StatBox({ icon, value, label }: { icon: React.ReactNode; value: string; label: string }) {
  return (
    <div className="p-6 bg-brand-muted/30 rounded-3xl text-center border border-transparent hover:border-brand-accent/10 transition-all dark:bg-white/5 dark:border-white/5">
      <div className="text-brand-accent flex justify-center mb-4">{icon}</div>
      <p className="text-[12px] font-black text-brand-dark mb-1 uppercase tracking-tight dark:text-white">{value}</p>
      <p className="text-[11px] font-black text-brand-dark/50 uppercase tracking-[0.15em] dark:text-white/50">{label}</p>
    </div>
  );
}
