'use client';

import { useEffect, useState, useTransition } from 'react';
import { validateSubdomain } from '@/lib/validation';

type CheckState =
  | { kind: 'idle' }
  | { kind: 'checking' }
  | { kind: 'ok' }
  | { kind: 'taken' }
  | { kind: 'invalid'; message: string };

const ERROR_TEXT: Record<string, string> = {
  invalid_user_code: 'That code is invalid. Double-check and try again.',
  expired: 'That code has expired. Generate a new one in your add-on.',
  'subdomain taken': 'That subdomain is already taken.',
  subdomain_required: 'Please choose a subdomain for your tunnel.',
  aal2_required: 'Please finish 2FA, then try again.',
  unauthorized: 'Your session expired. Please sign in again.',
};

function friendly(error: string | undefined, status: number): string {
  if (error && ERROR_TEXT[error]) return ERROR_TEXT[error];
  return error ?? `Request failed (${status})`;
}

/** Normalize a user-typed code to XXXX-XXXX for display (client-side mirror). */
function normalizeCode(raw: string): string {
  const cleaned = raw.toUpperCase().replace(/[^A-Z0-9]/g, '');
  if (cleaned.length !== 8) return raw.toUpperCase();
  return `${cleaned.slice(0, 4)}-${cleaned.slice(4, 8)}`;
}

export function ActivateClient({
  prefillCode,
  currentSubdomain,
}: {
  prefillCode: string;
  currentSubdomain: string | null;
}) {
  const [userCode, setUserCode] = useState(
    prefillCode ? normalizeCode(prefillCode) : '',
  );
  // When the user has an existing subdomain, default to reusing it.
  const [useExisting, setUseExisting] = useState<boolean>(!!currentSubdomain);
  const [subdomain, setSubdomain] = useState('');
  const [check, setCheck] = useState<CheckState>({ kind: 'idle' });
  const [error, setError] = useState<string | null>(null);
  const [done, setDone] = useState(false);
  const [isPending, startTransition] = useTransition();

  const needsSubdomain = !useExisting;

  useEffect(() => {
    if (!needsSubdomain) {
      setCheck({ kind: 'idle' });
      return;
    }
    const v = validateSubdomain(subdomain);
    if (!subdomain) {
      setCheck({ kind: 'idle' });
      return;
    }
    if (!v.ok) {
      setCheck({ kind: 'invalid', message: v.error });
      return;
    }
    setCheck({ kind: 'checking' });
    const ctrl = new AbortController();
    const t = setTimeout(async () => {
      try {
        const res = await fetch(
          `/api/tunnel/check?subdomain=${encodeURIComponent(v.value)}`,
          { signal: ctrl.signal },
        );
        const body = (await res.json()) as { available?: boolean };
        setCheck(body.available ? { kind: 'ok' } : { kind: 'taken' });
      } catch (e) {
        if ((e as { name?: string }).name !== 'AbortError') {
          setCheck({ kind: 'idle' });
        }
      }
    }, 300);
    return () => {
      ctrl.abort();
      clearTimeout(t);
    };
  }, [subdomain, needsSubdomain]);

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);

    const code = normalizeCode(userCode);
    if (code.replace(/[^A-Z0-9]/g, '').length !== 8) {
      setError(ERROR_TEXT.invalid_user_code);
      return;
    }

    const payload: { user_code: string; subdomain?: string } = {
      user_code: code,
    };
    if (needsSubdomain) {
      const v = validateSubdomain(subdomain);
      if (!v.ok) {
        setError(v.error);
        return;
      }
      payload.subdomain = v.value;
    }

    startTransition(async () => {
      const res = await fetch('/api/device/approve', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!res.ok) {
        const body = (await res.json().catch(() => ({}))) as { error?: string };
        setError(friendly(body.error, res.status));
        return;
      }
      setDone(true);
    });
  }

  if (done) {
    return (
      <p className="success">
        ✓ Device approved — return to your Home Assistant add-on.
      </p>
    );
  }

  const submitDisabled =
    isPending ||
    !userCode ||
    (needsSubdomain &&
      (check.kind === 'invalid' ||
        check.kind === 'taken' ||
        check.kind === 'checking' ||
        !subdomain));

  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="user_code">Pairing code</label>
      <div className="row">
        <input
          id="user_code"
          type="text"
          value={userCode}
          onChange={(e) => setUserCode(e.target.value.toUpperCase())}
          onBlur={() => setUserCode((c) => normalizeCode(c))}
          required
          autoCapitalize="characters"
          autoCorrect="off"
          spellCheck={false}
          placeholder="WXYZ-2345"
        />
      </div>

      {currentSubdomain && (
        <div style={{ marginTop: '1rem' }}>
          <label>
            <input
              type="radio"
              name="subchoice"
              checked={useExisting}
              onChange={() => setUseExisting(true)}
            />{' '}
            Use my current subdomain ({currentSubdomain}.linumiq.net)
          </label>
          <label style={{ display: 'block', marginTop: '0.5rem' }}>
            <input
              type="radio"
              name="subchoice"
              checked={!useExisting}
              onChange={() => setUseExisting(false)}
            />{' '}
            Use a different subdomain
          </label>
        </div>
      )}

      {needsSubdomain && (
        <div style={{ marginTop: '1rem' }}>
          <label htmlFor="subdomain">Subdomain</label>
          <div className="row">
            <input
              id="subdomain"
              type="text"
              value={subdomain}
              onChange={(e) => setSubdomain(e.target.value.toLowerCase())}
              required
              autoCapitalize="none"
              autoCorrect="off"
              spellCheck={false}
              placeholder="smith"
            />
            <span className="muted">.linumiq.net</span>
          </div>
          <div style={{ minHeight: '1.5em', marginTop: '0.25rem' }}>
            {check.kind === 'checking' && (
              <span className="muted">Checking availability…</span>
            )}
            {check.kind === 'ok' && <span className="success">Available</span>}
            {check.kind === 'taken' && <span className="error">Taken</span>}
            {check.kind === 'invalid' && (
              <span className="error">{check.message}</span>
            )}
          </div>
        </div>
      )}

      {error && <p className="error">{error}</p>}

      <div className="row" style={{ marginTop: '1rem' }}>
        <button type="submit" disabled={submitDisabled}>
          {isPending ? 'Approving…' : 'Approve device'}
        </button>
      </div>
    </form>
  );
}
