import { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { type BackupBundle, exportDeviceBackupWithRecovery } from '../lib/deviceBackup';
import { AlertIcon, CopyIcon, LockIcon, ShieldIcon, SpinnerIcon, XIcon } from './icons';

interface Props {
  open: boolean;
  userId: string;
  deviceId: string;
  privateKey: Uint8Array;
  onClose: () => void;
}

// Exports the device's private key + identity into a passphrase-protected
// portable string. The user can store this string anywhere (password manager,
// printed paper, encrypted file on a USB stick). Without it, losing local
// storage on this install means losing all past conversation keys.
export function BackupExportDialog({ open, userId, deviceId, privateKey, onClose }: Props) {
  const { t } = useTranslation(['app']);
  const [passphrase, setPassphrase] = useState('');
  const [confirm, setConfirm] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [bundle, setBundle] = useState<BackupBundle | null>(null);
  const [copied, setCopied] = useState(false);
  const [copiedRecovery, setCopiedRecovery] = useState(false);

  const canGenerate = useMemo(() => {
    return passphrase.length >= 8 && passphrase === confirm && !busy;
  }, [passphrase, confirm, busy]);

  const reset = useCallback(() => {
    setPassphrase('');
    setConfirm('');
    setBundle(null);
    setError(null);
    setCopied(false);
    setCopiedRecovery(false);
  }, []);

  const handleClose = useCallback(() => {
    reset();
    onClose();
  }, [reset, onClose]);

  const handleGenerate = useCallback(async () => {
    if (!canGenerate) return;
    setBusy(true);
    setError(null);
    try {
      const b = await exportDeviceBackupWithRecovery({
        userId,
        deviceId,
        privateKey,
        passphrase,
      });
      setBundle(b);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setBusy(false);
    }
  }, [canGenerate, userId, deviceId, privateKey, passphrase]);

  const copyText = async (text: string, marker: 'main' | 'recovery'): Promise<void> => {
    try {
      await navigator.clipboard.writeText(text);
      if (marker === 'main') {
        setCopied(true);
        window.setTimeout(() => setCopied(false), 1500);
      } else {
        setCopiedRecovery(true);
        window.setTimeout(() => setCopiedRecovery(false), 1500);
      }
    } catch {
      /* fall back — user can select manually */
    }
  };

  const handleDownload = useCallback(() => {
    if (!bundle) return;
    const text =
      '=== Passphrase backup ===\n' +
      bundle.passphraseBackup +
      '\n\n=== Recovery code ===\n' +
      bundle.recoveryCode +
      '\n\n=== Recovery backup (use with the recovery code) ===\n' +
      bundle.recoveryBackup +
      '\n';
    const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `chatapp-device-backup-${deviceId.slice(0, 8)}.txt`;
    a.click();
    URL.revokeObjectURL(url);
  }, [bundle, deviceId]);

  if (!open) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-label={t('app:backup.export_title', { defaultValue: 'Gerätesicherung erstellen' })}
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"
      onClick={handleClose}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        className="flex max-h-[90vh] w-full max-w-lg flex-col overflow-hidden rounded-2xl border border-line bg-surface-3 shadow-xl"
      >
        <header className="flex items-center justify-between border-b border-line px-5 py-3">
          <div className="flex items-center gap-2">
            <ShieldIcon className="h-4 w-4 text-accent" />
            <h3 className="font-display text-sm font-semibold text-fg">
              {t('app:backup.export_title', { defaultValue: 'Gerätesicherung erstellen' })}
            </h3>
          </div>
          <button
            type="button"
            onClick={handleClose}
            aria-label="Close"
            className="flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg text-fg-muted transition hover:bg-surface-2 hover:text-fg"
          >
            <XIcon className="h-4 w-4" />
          </button>
        </header>

        <div className="flex-1 overflow-y-auto p-5">
          {!bundle ? (
            <>
              <p className="text-sm text-fg-muted">
                {t('app:backup.export_explainer', {
                  defaultValue:
                    'Verschlüssele den Geräteschlüssel mit einer Passphrase. Ohne Passphrase UND Backup-String ist keine Wiederherstellung möglich.',
                })}
              </p>

              <div className="mt-4 space-y-3">
                <div className="space-y-1">
                  <label className="block text-xs font-medium uppercase tracking-wide text-fg-muted">
                    {t('app:backup.passphrase', { defaultValue: 'Passphrase' })}
                  </label>
                  <input
                    type="password"
                    autoFocus
                    minLength={8}
                    value={passphrase}
                    onChange={(e) => setPassphrase(e.target.value)}
                    placeholder="min. 8 Zeichen"
                    className="w-full rounded-lg border border-line bg-surface-2 px-3 py-2.5 text-sm text-fg placeholder-fg-muted transition focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent/30"
                  />
                </div>
                <div className="space-y-1">
                  <label className="block text-xs font-medium uppercase tracking-wide text-fg-muted">
                    {t('app:backup.passphrase_confirm', { defaultValue: 'Passphrase wiederholen' })}
                  </label>
                  <input
                    type="password"
                    value={confirm}
                    onChange={(e) => setConfirm(e.target.value)}
                    className="w-full rounded-lg border border-line bg-surface-2 px-3 py-2.5 text-sm text-fg placeholder-fg-muted transition focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent/30"
                  />
                </div>
                {confirm.length > 0 && confirm !== passphrase && (
                  <p className="text-xs text-rose-500 dark:text-rose-300">
                    {t('app:backup.passphrase_mismatch', { defaultValue: 'Passphrasen stimmen nicht überein.' })}
                  </p>
                )}
              </div>

              <div className="mt-4 rounded-lg border border-amber-500/30 bg-amber-500/10 p-3 text-xs text-amber-700 dark:text-amber-200">
                <div className="flex items-start gap-2">
                  <AlertIcon className="mt-0.5 h-4 w-4 shrink-0 text-amber-600 dark:text-amber-300" />
                  <span>
                    {t('app:backup.export_warning', {
                      defaultValue:
                        'Anthropic: Backup + Passphrase sicher aufbewahren. Passphrase kann nicht wiederhergestellt werden.',
                    })}
                  </span>
                </div>
              </div>

              {error && (
                <p role="alert" className="mt-3 text-sm text-rose-600 dark:text-rose-200">
                  {error}
                </p>
              )}
            </>
          ) : (
            <>
              <div className="rounded-lg border border-emerald-500/30 bg-emerald-500/10 p-3 text-xs text-emerald-700 dark:text-emerald-200">
                <div className="flex items-start gap-2">
                  <LockIcon className="mt-0.5 h-4 w-4 shrink-0" />
                  <span>
                    {t('app:backup.export_success', {
                      defaultValue:
                        'Backup erstellt. Speichere diesen String + Passphrase in einem Passwortmanager oder drucke ihn aus.',
                    })}
                  </span>
                </div>
              </div>
              <label className="mt-3 block text-xs font-medium uppercase tracking-wide text-fg-muted">
                Backup-String
              </label>
              <textarea
                readOnly
                value={bundle.passphraseBackup}
                rows={6}
                onFocus={(e) => e.currentTarget.select()}
                className="mt-1 w-full resize-none rounded-lg border border-line bg-surface-2 p-3 font-mono text-[11px] leading-relaxed text-fg"
              />
              <div className="mt-2 flex gap-2">
                <button
                  type="button"
                  onClick={() => void copyText(bundle.passphraseBackup, 'main')}
                  className="inline-flex flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-lg border border-line bg-surface-2 px-3 py-2 text-sm font-medium text-fg transition hover:bg-surface-3"
                >
                  <CopyIcon className="h-4 w-4" />
                  <span>{copied ? 'Kopiert!' : 'Kopieren'}</span>
                </button>
                <button
                  type="button"
                  onClick={handleDownload}
                  className="inline-flex flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-lg border border-line bg-surface-2 px-3 py-2 text-sm font-medium text-fg transition hover:bg-surface-3"
                >
                  Als Datei speichern (alles)
                </button>
              </div>

              <div className="mt-5 rounded-lg border border-amber-500/30 bg-amber-500/10 p-3">
                <div className="flex items-start gap-2">
                  <ShieldIcon className="mt-0.5 h-4 w-4 shrink-0 text-amber-600 dark:text-amber-300" />
                  <div className="min-w-0 flex-1">
                    <p className="text-xs font-semibold text-amber-700 dark:text-amber-200">
                      Recovery-Code (Passphrase vergessen?)
                    </p>
                    <p className="mt-0.5 text-[11px] text-amber-700/80 dark:text-amber-200/80">
                      Code separat aufbewahren. Mit dem Recovery-Backup unten lässt sich der Schlüssel
                      ohne Passphrase wiederherstellen.
                    </p>
                    <p className="mt-2 select-all rounded bg-surface-3 px-2 py-1.5 font-mono text-sm tracking-widest text-fg">
                      {bundle.recoveryCode}
                    </p>
                  </div>
                </div>
              </div>

              <label className="mt-3 block text-xs font-medium uppercase tracking-wide text-fg-muted">
                Recovery-Backup-String
              </label>
              <textarea
                readOnly
                value={bundle.recoveryBackup}
                rows={6}
                onFocus={(e) => e.currentTarget.select()}
                className="mt-1 w-full resize-none rounded-lg border border-line bg-surface-2 p-3 font-mono text-[11px] leading-relaxed text-fg"
              />
              <button
                type="button"
                onClick={() => void copyText(bundle.recoveryBackup, 'recovery')}
                className="mt-2 inline-flex w-full cursor-pointer items-center justify-center gap-1.5 rounded-lg border border-line bg-surface-2 px-3 py-2 text-sm font-medium text-fg transition hover:bg-surface-3"
              >
                <CopyIcon className="h-4 w-4" />
                <span>{copiedRecovery ? 'Kopiert!' : 'Recovery-Backup kopieren'}</span>
              </button>
            </>
          )}
        </div>

        <footer className="flex items-center justify-end gap-2 border-t border-line bg-surface-2 px-5 py-3">
          {!bundle ? (
            <>
              <button
                type="button"
                onClick={handleClose}
                className="cursor-pointer rounded-md border border-line bg-surface-3 px-3 py-2 text-sm text-fg transition hover:bg-surface-2"
              >
                {t('app:friends.action_cancel', { defaultValue: 'Abbrechen' })}
              </button>
              <button
                type="button"
                onClick={() => void handleGenerate()}
                disabled={!canGenerate}
                className="inline-flex cursor-pointer items-center gap-1.5 rounded-md bg-accent px-3 py-2 text-sm font-semibold text-accent-fg transition hover:brightness-110 disabled:cursor-not-allowed disabled:opacity-60"
              >
                {busy && <SpinnerIcon className="h-4 w-4" />}
                <span>{t('app:backup.generate', { defaultValue: 'Backup erstellen' })}</span>
              </button>
            </>
          ) : (
            <button
              type="button"
              onClick={handleClose}
              className="cursor-pointer rounded-md bg-accent px-3 py-2 text-sm font-semibold text-accent-fg transition hover:brightness-110"
            >
              {t('app:backup.done', { defaultValue: 'Fertig' })}
            </button>
          )}
        </footer>
      </div>
    </div>
  );
}
