import { useEffect, useState } from 'react';
import { Preferences } from '@capacitor/preferences';
import { BiometricAuth } from '@aparajita/capacitor-biometric-auth';
import { LOCAL_URL, PREF_SERVER_URL, PREF_BIOMETRIC, LOCAL_MODE_SENTINEL } from './config';
import SetupScreen from './SetupScreen';
import LoadingScreen from './LoadingScreen';
import LoginScreen from './LoginScreen';
import BiometricSetup from './BiometricSetup';
import BiometricLock from './BiometricLock';
import MainApp from './MainApp';

type Stage = 'checking' | 'setup' | 'boot' | 'login' | 'biometric-setup' | 'biometric-lock' | 'app';
type Mode = 'local' | 'server';

export default function App() {
  const [stage, setStage] = useState<Stage>('checking');
  const [mode, setMode] = useState<Mode>('server');
  const [serverUrl, setServerUrl] = useState('');
  const [booted, setBooted] = useState(false);

  // API base — the on-device server in local mode, or the remote server.
  const baseUrl = mode === 'local' ? LOCAL_URL : serverUrl;

  useEffect(() => {
    Preferences.get({ key: PREF_SERVER_URL })
      .then(async ({ value }) => {
        if (value === LOCAL_MODE_SENTINEL) {
          setMode('local');
          setStage('boot');
          return;
        }
        if (value) {
          setMode('server');
          setServerUrl(value);
          const { value: bio } = await Preferences.get({ key: PREF_BIOMETRIC });
          setStage(bio === 'true' ? 'biometric-lock' : 'app');
          return;
        }
        setStage('setup');
      })
      .catch(() => setStage('setup'));
  }, []);

  function handleConnect(url: string) {
    setMode('server');
    setServerUrl(url);
    setStage('login');
  }

  async function handleLocalMode() {
    await Preferences.set({ key: PREF_SERVER_URL, value: LOCAL_MODE_SENTINEL });
    setMode('local');
    setStage(booted ? 'app' : 'boot');
  }

  async function handleLoginSuccess() {
    if (mode === 'server') {
      await Preferences.set({ key: PREF_SERVER_URL, value: serverUrl });
    }
    // Offer biometric unlock once, if the device supports it and it's undecided.
    try {
      const { isAvailable } = await BiometricAuth.checkBiometry();
      const { value: bioPref } = await Preferences.get({ key: PREF_BIOMETRIC });
      setStage(isAvailable && bioPref == null ? 'biometric-setup' : 'app');
    } catch {
      setStage('app');
    }
  }

  async function handleBiometricSetupDone(enabled: boolean) {
    await Preferences.set({ key: PREF_BIOMETRIC, value: enabled ? 'true' : 'false' });
    setStage('app');
  }

  async function handleBiometricFallback() {
    await Preferences.set({ key: PREF_BIOMETRIC, value: 'false' });
    setStage('login');
  }

  function handleUnauthenticated() {
    setStage('login');
  }

  async function handleSignOut() {
    await Preferences.remove({ key: PREF_BIOMETRIC });
    setStage('login');
  }

  switch (stage) {
    case 'boot':
      return <LoadingScreen onReady={() => { setBooted(true); setStage('app'); }} />;

    case 'setup':
      return <SetupScreen onConnect={handleConnect} onLocalMode={handleLocalMode} />;

    case 'login':
      return (
        <LoginScreen
          serverUrl={baseUrl}
          onSuccess={handleLoginSuccess}
          onBack={() => setStage(mode === 'local' ? 'app' : 'setup')}
        />
      );

    case 'biometric-setup':
      return <BiometricSetup onDone={handleBiometricSetupDone} />;

    case 'biometric-lock':
      return <BiometricLock onUnlocked={() => setStage('app')} onFallback={handleBiometricFallback} />;

    case 'app':
      return <MainApp baseUrl={baseUrl} onUnauthenticated={handleUnauthenticated} onSignOut={handleSignOut} />;

    default:
      // 'checking' — brief blank while we read stored preferences.
      return (
        <div className="app-splash">
          <div className="spinner" />
        </div>
      );
  }
}
