import { useEffect, useMemo, useState } from 'react';
import { Copy, KeyRound, Loader2, Plus, Trash2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { addTotpProfile, deleteTotpProfile, loadTotpProfiles } from './secure-totp-store';
import { generateTotpCode, getRemainingSeconds, parseOtpAuthUrl, type TotpProfile } from './totp';

interface TotpCodeState {
  code: string;
  remaining: number;
}

export function TotpScreen() {
  const [profiles, setProfiles] = useState<TotpProfile[]>([]);
  const [codes, setCodes] = useState<Record<string, TotpCodeState>>({});
  const [issuer, setIssuer] = useState('');
  const [label, setLabel] = useState('');
  const [secret, setSecret] = useState('');
  const [otpauth, setOtpauth] = useState('');
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const canSave = useMemo(() => issuer.trim() && label.trim() && secret.trim(), [issuer, label, secret]);

  useEffect(() => {
    loadTotpProfiles()
      .then(setProfiles)
      .catch((err) => setError(err instanceof Error ? err.message : 'Не удалось открыть защищённое хранилище'))
      .finally(() => setLoading(false));
  }, []);

  useEffect(() => {
    let cancelled = false;
    async function tick() {
      const entries = await Promise.all(
        profiles.map(async (profile) => [
          profile.id,
          {
            code: await generateTotpCode(profile),
            remaining: getRemainingSeconds(profile.period)
          }
        ] as const)
      );
      if (!cancelled) {
        setCodes(Object.fromEntries(entries));
      }
    }
    void tick();
    const timer = window.setInterval(() => void tick(), 1000);
    return () => {
      cancelled = true;
      window.clearInterval(timer);
    };
  }, [profiles]);

  function applyOtpAuthUrl(value: string) {
    setOtpauth(value);
    const parsed = parseOtpAuthUrl(value);
    if (!parsed) return;
    setIssuer(parsed.issuer ?? '');
    setLabel(parsed.label ?? '');
    setSecret(parsed.secret ?? '');
  }

  async function saveProfile() {
    setSaving(true);
    setError(null);
    try {
      const profile = await addTotpProfile({
        issuer: issuer.trim(),
        label: label.trim(),
        secret: secret.trim(),
        digits: 6,
        period: 30
      });
      setProfiles((current) => [...current, profile]);
      setIssuer('');
      setLabel('');
      setSecret('');
      setOtpauth('');
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Не удалось сохранить TOTP');
    } finally {
      setSaving(false);
    }
  }

  async function removeProfile(profileId: string) {
    await deleteTotpProfile(profileId);
    setProfiles((current) => current.filter((profile) => profile.id !== profileId));
  }

  return (
    <div className="safe-top mx-auto max-w-3xl space-y-4 p-4">
      <header className="rounded-[28px] bg-white p-5 shadow-sm">
        <p className="text-sm text-[#667085]">Offline 2FA</p>
        <h1 className="mt-1 text-2xl font-semibold">Authenticator</h1>
        <p className="mt-2 text-sm text-[#667085]">TOTP-секреты хранятся в Tauri Stronghold, а не в LocalStorage.</p>
      </header>

      <section className="rounded-[28px] bg-white p-5 shadow-sm">
        <h2 className="mb-4 flex items-center gap-2 font-semibold">
          <Plus className="h-5 w-5" />
          Добавить код
        </h2>
        <div className="space-y-3">
          <Input value={otpauth} onChange={(event) => applyOtpAuthUrl(event.target.value)} placeholder="otpauth://totp/..." />
          <div className="grid gap-3 sm:grid-cols-2">
            <Input value={issuer} onChange={(event) => setIssuer(event.target.value)} placeholder="Сервис, например GitHub" />
            <Input value={label} onChange={(event) => setLabel(event.target.value)} placeholder="Аккаунт" />
          </div>
          <Input value={secret} onChange={(event) => setSecret(event.target.value)} placeholder="Base32 secret" />
          {error ? <p className="rounded-2xl bg-red-50 px-3 py-2 text-sm text-red-700">{error}</p> : null}
          <Button disabled={!canSave || saving} onClick={() => void saveProfile()}>
            {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <KeyRound className="h-4 w-4" />}
            Сохранить в защищённом хранилище
          </Button>
        </div>
      </section>

      <section className="space-y-3">
        {loading ? (
          <div className="rounded-[28px] bg-white p-5 text-sm text-[#667085]">Загрузка...</div>
        ) : profiles.length ? (
          profiles.map((profile) => {
            const state = codes[profile.id];
            const progress = state ? (state.remaining / profile.period) * 100 : 0;
            return (
              <article key={profile.id} className="rounded-[28px] bg-white p-5 shadow-sm">
                <div className="flex items-start justify-between gap-3">
                  <div>
                    <h3 className="font-semibold">{profile.issuer}</h3>
                    <p className="text-sm text-[#667085]">{profile.label}</p>
                  </div>
                  <Button variant="ghost" size="icon" onClick={() => void removeProfile(profile.id)} aria-label="Удалить TOTP">
                    <Trash2 className="h-4 w-4 text-red-600" />
                  </Button>
                </div>
                <button
                  type="button"
                  className="mt-4 flex w-full items-center justify-between rounded-3xl bg-[#20212b] px-5 py-4 text-left text-white"
                  onClick={() => state?.code && navigator.clipboard.writeText(state.code)}
                >
                  <span className="font-mono text-4xl font-semibold tracking-[0.2em]">{state?.code ?? '------'}</span>
                  <Copy className="h-5 w-5 text-white/70" />
                </button>
                <div className="mt-3 h-2 overflow-hidden rounded-full bg-[#eef1f6]">
                  <div className="h-full rounded-full bg-[#3390ec] transition-all" style={{ width: `${progress}%` }} />
                </div>
                <p className="mt-2 text-right text-xs text-[#667085]">{state?.remaining ?? profile.period} сек.</p>
              </article>
            );
          })
        ) : (
          <div className="rounded-[28px] bg-white p-8 text-center text-sm text-[#667085] shadow-sm">Добавьте первый TOTP-код</div>
        )}
      </section>
    </div>
  );
}
