import { useEffect, useState } from 'react';
import { router, useLocalSearchParams } from 'expo-router';
import { Text, TextInput, StyleSheet, View } from 'react-native';
import { useTranslation } from 'react-i18next';
import type { User, AuthTokens } from '@navi/types';
import { Screen } from '../../../src/components/Screen';
import { PrimaryButton } from '../../../src/components/PrimaryButton';
import { StateView } from '../../../src/components/StateView';
import { BackButton } from '../../../src/components/BackButton';
import { api, ApiError } from '../../../src/api/client';
import { useAuth } from '../../../src/state/auth';
import { color, radius, spacing, typography } from '../../../src/theme';

export default function Otp() {
  const { t } = useTranslation();
  const { purpose, email, devCode } = useLocalSearchParams<{
    purpose: 'signup' | 'login' | 'reset';
    email?: string;
    devCode?: string;
  }>();
  const setSession = useAuth((s) => s.setSession);
  const continueAsGuest = useAuth((s) => s.continueAsGuest);
  const [code, setCode] = useState(isSixDigitCode(devCode) ? devCode : '');
  const [submitting, setSubmitting] = useState(false);
  const [resending, setResending] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!code && isSixDigitCode(devCode)) setCode(devCode);
  }, [code, devCode]);

  async function onVerify() {
    setError(null);
    if (!email) {
      setError(t('auth.invalidCode'));
      return;
    }
    setSubmitting(true);
    try {
      let result: { ok: true } | (AuthTokens & { userId: string });
      try {
        result = await api.auth.verifyOtp({ email, purpose: purpose ?? 'signup', code });
      } catch (e) {
        if (e instanceof ApiError && e.status === 401) setError(t('auth.invalidCode'));
        else setError(e instanceof ApiError ? e.message : t('auth.networkError'));
        return;
      }

      if ('accessToken' in result) {
        let me: User | null = null;
        try {
          me = await api.raw.get<User | null>('/users/me', {
            headers: { Authorization: `Bearer ${result.accessToken}` },
          });
        } catch {
          setError(t('auth.profileFetchFailed'));
          return;
        }
        if (!me) {
          setError(t('auth.profileFetchFailed'));
          return;
        }
        await setSession(me, result as AuthTokens);
        router.replace('/(tabs)/home');
        return;
      }
      if (purpose === 'reset') {
        router.replace({
          pathname: '/(auth)/reset-password',
          params: { email, code },
        });
        return;
      }
      router.replace('/(auth)/login');
    } finally {
      setSubmitting(false);
    }
  }

  async function onResend() {
    setError(null);
    if (!email) {
      setError(t('auth.invalidCode'));
      return;
    }
    setResending(true);
    try {
      const result = await api.auth.requestOtp({ email, purpose: purpose ?? 'signup' });
      if (isSixDigitCode(result.devCode)) setCode(result.devCode);
    } catch (e) {
      setError(e instanceof ApiError ? e.message : t('auth.networkError'));
    } finally {
      setResending(false);
    }
  }

  async function onContinueAsGuest() {
    await continueAsGuest();
    router.replace('/(tabs)/home');
  }

  return (
    <Screen>
      <BackButton fallbackHref="/(auth)/login" />
      <Text style={styles.title}>{t('auth.otpTitle')}</Text>
      <Text style={styles.body}>{t('auth.otpBody', { purpose })}</Text>
      {!email ? <StateView tone="error" title={t('auth.verificationFailed')} body={t('auth.invalidCode')} /> : null}
      {devCode ? <StateView tone="empty" title={t('auth.developmentCode')} body={devCode} /> : null}
      <View style={styles.row}>
        <TextInput
          value={code}
          onChangeText={(v) => setCode(v.replace(/\D/g, '').slice(0, 6))}
          keyboardType="number-pad"
          placeholder="123456"
          style={styles.input}
          maxLength={6}
        />
      </View>
      {error ? <StateView tone="error" title={t('auth.verificationFailed')} body={error} /> : null}
      <PrimaryButton label={submitting ? t('states.loading') : t('auth.verify')} onPress={onVerify} disabled={code.length !== 6 || submitting} />
      <PrimaryButton
        label={resending ? t('states.loading') : t('auth.sendReset')}
        variant="secondary"
        onPress={onResend}
        disabled={resending || submitting}
      />
      <PrimaryButton label={t('actions.continueAsGuest')} variant="ghost" onPress={onContinueAsGuest} disabled={submitting} />
      <PrimaryButton label={t('auth.signInTitle')} variant="ghost" onPress={() => router.replace('/(auth)/login')} disabled={submitting} />
    </Screen>
  );
}

function isSixDigitCode(value: unknown): value is string {
  return typeof value === 'string' && /^\d{6}$/.test(value);
}

const styles = StyleSheet.create({
  title: { fontSize: typography.scale.h1.size, fontWeight: '700', color: color.ink[900] },
  body: { fontSize: typography.scale.body.size, color: color.ink[500] },
  row: { flexDirection: 'row', gap: spacing[2] },
  input: {
    height: 56, borderRadius: radius.md, borderWidth: 1, borderColor: color.border,
    paddingHorizontal: spacing[4], backgroundColor: color.bg[0], fontSize: 22, letterSpacing: 6, textAlign: 'center', flex: 1,
  },
});
