import { FormEvent, useCallback, useEffect, useRef, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { createAccount } from '../api/client';
import {
  parseOtpauthFromText,
  parseOtpauthUri,
  type ParsedOtpAuth,
} from '../lib/otpauth-parse';

type Segment = 'manual' | 'scan' | 'image';

export function AddAccountPage() {
  const nav = useNavigate();
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const [segment, setSegment] = useState<Segment>('manual');
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const [label, setLabel] = useState('');
  const [issuer, setIssuer] = useState('');
  const [secret, setSecret] = useState('');
  const [algorithm, setAlgorithm] = useState('SHA1');
  const [digits, setDigits] = useState(6);
  const [period, setPeriod] = useState(30);
  const [paste, setPaste] = useState('');

  const applyParsed = useCallback((p: ParsedOtpAuth) => {
    setLabel(p.label);
    setIssuer(p.issuer ?? '');
    setSecret(p.secret);
    setAlgorithm(p.algorithm);
    setDigits(p.digits);
    setPeriod(p.period);
    setError(null);
  }, []);

  async function submitParsed(p?: ParsedOtpAuth) {
    const data =
      p ??
      ({
        label: label.trim(),
        issuer: issuer.trim() || null,
        secret: secret.trim(),
        algorithm,
        digits,
        period,
      } as ParsedOtpAuth);
    if (!data.label || !data.secret.trim()) {
      setError('请填写名称与密钥');
      return;
    }
    setBusy(true);
    setError(null);
    try {
      await createAccount({
        label: data.label,
        issuer: data.issuer,
        secret: data.secret.trim(),
        algorithm: data.algorithm,
        digits: data.digits,
        period: data.period,
      });
      nav('/', { replace: true });
    } catch (e) {
      setError(e instanceof Error ? e.message : '保存失败');
    } finally {
      setBusy(false);
    }
  }

  function onManualSubmit(e: FormEvent) {
    e.preventDefault();
    void submitParsed();
  }

  function onApplyPaste() {
    const p = parseOtpauthFromText(paste);
    if (!p) {
      setError('未识别 otpauth 链接，请检查粘贴内容');
      return;
    }
    applyParsed(p);
  }

  useEffect(() => {
    if (segment !== 'scan') return;
    const video = videoRef.current;
    if (!video) return;

    let reader: InstanceType<
      Awaited<typeof import('@zxing/browser')>['BrowserMultiFormatReader']
    > | null = null;
    let cancelled = false;

    (async () => {
      try {
        const { BrowserMultiFormatReader } = await import('@zxing/browser');
        reader = new BrowserMultiFormatReader();
        await reader.decodeFromVideoDevice(undefined, video, (result) => {
            if (cancelled || !result) return;
            const text = result.getText();
            const p = parseOtpauthUri(text);
            if (p) {
              applyParsed(p);
              if (reader) void reader.reset();
              setSegment('manual');
              setError(null);
            } else {
              setError('二维码内容不是 otpauth 格式');
            }
          });
      } catch {
        if (!cancelled) setError('无法打开摄像头，请检查权限');
      }
    })();

    return () => {
      cancelled = true;
      void reader?.reset();
    };
  }, [segment, applyParsed]);

  function onImageFile(file: File) {
    const reader = new FileReader();
    reader.onload = async () => {
      const url = String(reader.result || '');
      try {
        const { BrowserMultiFormatReader } = await import('@zxing/browser');
        const bf = new BrowserMultiFormatReader();
        const img = new Image();
        img.decoding = 'async';
        img.src = url;
        await img.decode();
        const result = await bf.decodeFromImageElement(img);
        const text = result.getText();
        const p = parseOtpauthUri(text);
        if (!p) {
          setError('图片中二维码不是 otpauth 格式');
          return;
        }
        applyParsed(p);
        setSegment('manual');
      } catch {
        setError('无法从图片解析二维码');
      }
    };
    reader.readAsDataURL(file);
  }

  return (
    <main>
      <div className="top-nav">
        <Link className="btn secondary" to="/">
          返回
        </Link>
        <span style={{ fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <img className="top-nav-logo" src="/logo.png" alt="" width={28} height={28} />
          添加账户
        </span>
        <span style={{ width: 72 }} />
      </div>

      <div className="segment">
        <button
          type="button"
          className={segment === 'manual' ? 'active' : ''}
          onClick={() => setSegment('manual')}
        >
          手动
        </button>
        <button
          type="button"
          className={segment === 'scan' ? 'active' : ''}
          onClick={() => setSegment('scan')}
        >
          扫码
        </button>
        <button
          type="button"
          className={segment === 'image' ? 'active' : ''}
          onClick={() => setSegment('image')}
        >
          图片
        </button>
      </div>

      {segment === 'scan' ? (
        <div className="card scan-wrap">
          <p className="sub">将二维码对准画面，识别成功后会自动控制转手动页并填入。</p>
          <video ref={videoRef} className="scan" muted playsInline />
        </div>
      ) : null}

      {segment === 'image' ? (
        <div className="card">
          <p className="sub">选择包含 otpauth 二维码的图片。</p>
          <input
            type="file"
            accept="image/*"
            onChange={(e) => {
              const f = e.target.files?.[0];
              if (f) onImageFile(f);
            }}
          />
        </div>
      ) : null}

      <div className="card">
        <p className="sub">粘贴 otpauth 链接可快速填充：</p>
        <textarea
          value={paste}
          placeholder="otpauth://totp/..."
          onChange={(e) => setPaste(e.target.value)}
        />
        <button type="button" className="btn secondary" style={{ marginTop: 8 }} onClick={onApplyPaste}>
          解析粘贴
        </button>
      </div>

      <form className="card" onSubmit={onManualSubmit}>
        <h2 style={{ marginTop: 0, fontSize: '1.1rem' }}>账户信息</h2>
        <div className="field">
          <label>显示名称</label>
          <input value={label} onChange={(e) => setLabel(e.target.value)} required />
        </div>
        <div className="field">
          <label>发行方（可选）</label>
          <input value={issuer} onChange={(e) => setIssuer(e.target.value)} />
        </div>
        <div className="field">
          <label>Secret（Base32）</label>
          <input
            value={secret}
            onChange={(e) => setSecret(e.target.value)}
            required
            autoComplete="off"
          />
        </div>
        <div className="field">
          <label>算法</label>
          <select value={algorithm} onChange={(e) => setAlgorithm(e.target.value)}>
            <option value="SHA1">SHA1</option>
            <option value="SHA256">SHA256</option>
            <option value="SHA512">SHA512</option>
          </select>
        </div>
        <div className="field">
          <label>位数</label>
          <input
            type="number"
            min={6}
            max={10}
            value={digits}
            onChange={(e) => setDigits(Number(e.target.value))}
          />
        </div>
        <div className="field">
          <label>周期（秒）</label>
          <input
            type="number"
            min={10}
            max={120}
            value={period}
            onChange={(e) => setPeriod(Number(e.target.value))}
          />
        </div>
        {error ? <p className="error">{error}</p> : null}
        <button className="btn" type="submit" disabled={busy} style={{ width: '100%', marginTop: 8 }}>
          {busy ? '保存中…' : '保存'}
        </button>
      </form>
    </main>
  );
}
