import { useState } from 'react';
import { router } from 'expo-router';
import { TextInput, View, Text, StyleSheet, Pressable } from 'react-native';
import { useTranslation } from 'react-i18next';
import type { User } from '@navi/types';
import { loginSchema } from '@navi/validators';
import { demoAccountsFor, isDemoModeEnabled } from '@navi/config';
import { Screen } from '../../src/components/Screen';
import { PrimaryButton } from '../../src/components/PrimaryButton';
import { StateView } from '../../src/components/StateView';
import { NaviHeader } from '../../src/components/layout/NaviHeader';
import { api, ApiError } from '../../src/api/client';
import { useAuth } from '../../src/state/auth';
import { clearFieldError, fieldErrorsFromIssues, summarizeFieldErrors, type FieldErrors } from '../../src/auth/formValidation';
import { color, radius, spacing, typography } from '../../src/theme';

type LoginField = 'email' | 'password';

const DEMO_ACCOUNTS = demoAccountsFor('mobile');
const IS_DEMO_MODE = isDemoModeEnabled({
  demoMode: process.env.EXPO_PUBLIC_DEMO_MODE,
  nodeEnv: process.env.NODE_ENV,
  naviEnv: process.env.EXPO_PUBLIC_NAVI_ENV,
});

export default function Login() {
  const { t } = useTranslation();
  const setSession = useAuth((s) => s.setSession);
  const continueAsGuest = useAuth((s) => s.continueAsGuest);
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [fieldErrors, setFieldErrors] = useState<FieldErrors<LoginField>>({});
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function onSignIn() {
    await loginWith(email, password);
  }

  async function loginWith(loginEmail: string, loginPassword: string) {
    setError(null);
    setFieldErrors({});
    const parsed = loginSchema.safeParse({
      email: loginEmail.trim().toLowerCase(),
      password: loginPassword,
    });
    if (!parsed.success) {
      const errors = fieldErrorsFromIssues<LoginField>(parsed.error.issues, {
        email: t('auth.email'),
        password: t('auth.password'),
      });
      setFieldErrors(errors);
      setError(summarizeFieldErrors(errors));
      return;
    }
    setSubmitting(true);
    try {
      const res = await api.auth.login(parsed.data);
      const me = await api.raw.get<User | null>('/users/me', {
        headers: { Authorization: `Bearer ${res.accessToken}` },
      });
      if (!me) throw new Error(t('auth.profileFetchFailed'));
      await setSession(me, {
        accessToken: res.accessToken,
        refreshToken: res.refreshToken,
        expiresAt: res.expiresAt,
      });
      router.replace('/(tabs)/home');
    } catch (e) {
      if (e instanceof ApiError && e.status === 401) setError(t('auth.invalidCredentials'));
      else if (e instanceof ApiError) setError(e.message);
      else setError(t('auth.networkError'));
    } finally {
      setSubmitting(false);
    }
  }

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

  return (
    <Screen>
      <NaviHeader variant="center" title={t('auth.signInTitle')} showBack onBack={() => router.replace('/(auth)/splash')} />
      <Text style={styles.title}>{t('auth.welcomeBack')}</Text>
      <Text style={styles.subtitle}>{t('auth.signInToExplore')}</Text>

      <Text style={styles.label}>{t('auth.email')}</Text>
      <TextInput
        autoCapitalize="none"
        autoCorrect={false}
        keyboardType="email-address"
        placeholder={t('auth.placeholderEmail')}
        value={email}
        onChangeText={(value) => {
          setEmail(value);
          setFieldErrors((current) => clearFieldError(current, 'email'));
        }}
        style={[styles.input, fieldErrors.email ? styles.inputError : null]}
      />
      {fieldErrors.email ? <Text style={styles.fieldError}>{fieldErrors.email}</Text> : null}

      <Text style={styles.label}>{t('auth.password')}</Text>
      <TextInput
        secureTextEntry
        placeholder={t('auth.placeholderPasswordDots')}
        value={password}
        onChangeText={(value) => {
          setPassword(value);
          setFieldErrors((current) => clearFieldError(current, 'password'));
        }}
        style={[styles.input, fieldErrors.password ? styles.inputError : null]}
      />
      {fieldErrors.password ? <Text style={styles.fieldError}>{fieldErrors.password}</Text> : null}

      {error ? <StateView tone="error" title={t('auth.signInFailed')} body={error} /> : null}

      <PrimaryButton
        label={submitting ? t('states.loading') : t('actions.signIn')}
        onPress={onSignIn}
        disabled={submitting}
        rightIcon
      />
      <PrimaryButton
        label={t('actions.continueAsGuest')}
        variant="secondary"
        onPress={onContinueAsGuest}
        disabled={submitting}
      />

      {IS_DEMO_MODE ? (
        <View style={styles.demoCard}>
          <Text style={styles.demoTitle}>Demo only: sign in as</Text>
          {!process.env.EXPO_PUBLIC_DEMO_PASSWORD ? (
            <Text style={styles.fieldError}>Set EXPO_PUBLIC_DEMO_PASSWORD to enable demo role login.</Text>
          ) : null}
          <View style={styles.demoGrid}>
            {DEMO_ACCOUNTS.map((account) => (
              <Pressable
                key={account.email}
                accessibilityRole="button"
                accessibilityLabel={`Demo login as ${account.label}`}
                disabled={submitting || !process.env.EXPO_PUBLIC_DEMO_PASSWORD}
                onPress={() => {
                  const demoPassword = process.env.EXPO_PUBLIC_DEMO_PASSWORD ?? '';
                  setEmail(account.email);
                  setPassword(demoPassword);
                  void loginWith(account.email, demoPassword);
                }}
                style={[styles.demoButton, submitting || !process.env.EXPO_PUBLIC_DEMO_PASSWORD ? styles.demoButtonDisabled : null]}
              >
                <Text style={styles.demoButtonText}>{account.label}</Text>
              </Pressable>
            ))}
          </View>
        </View>
      ) : null}

      <View style={styles.row}>
        <Text style={styles.muted}>{t('auth.noAccount')} </Text>
        <Pressable onPress={() => router.push('/(auth)/signup')} accessibilityRole="link">
          <Text style={styles.link}>{t('auth.createAccount')}</Text>
        </Pressable>
      </View>

      <Pressable onPress={() => router.push('/(auth)/forgot-password')} accessibilityRole="link">
        <Text style={[styles.link, { textAlign: 'center', marginTop: spacing[3] }]}>
          {t('auth.forgotPassword')}
        </Text>
      </Pressable>
    </Screen>
  );
}

const styles = StyleSheet.create({
  title: { fontSize: typography.scale.h1.size, fontWeight: '700', color: color.ink[900] },
  subtitle: { fontSize: typography.scale.body.size, color: color.ink[500] },
  label: { fontSize: typography.scale.caption.size, color: color.ink[700], marginTop: spacing[3] },
  input: {
    height: 52,
    borderRadius: radius.md,
    borderWidth: 1,
    borderColor: color.border,
    paddingHorizontal: spacing[4],
    backgroundColor: color.bg[0],
    fontSize: typography.scale.body.size,
  },
  inputError: { borderColor: color.danger },
  fieldError: { color: color.danger, fontSize: typography.scale.caption.size, marginTop: spacing[1] },
  demoCard: {
    backgroundColor: color.bg[0],
    borderColor: color.border,
    borderRadius: radius.lg,
    borderWidth: 1,
    gap: spacing[3],
    padding: spacing[4],
  },
  demoTitle: {
    color: color.ink[700],
    fontSize: typography.scale.caption.size,
    fontWeight: '800',
  },
  demoGrid: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: spacing[2],
  },
  demoButton: {
    backgroundColor: color.blue[100],
    borderColor: color.border,
    borderRadius: radius.pill,
    borderWidth: 1,
    paddingHorizontal: spacing[3],
    paddingVertical: spacing[2],
  },
  demoButtonDisabled: {
    opacity: 0.45,
  },
  demoButtonText: {
    color: color.blue[700],
    fontSize: typography.scale.caption.size,
    fontWeight: '800',
  },
  row: { flexDirection: 'row', justifyContent: 'center', marginTop: spacing[6] },
  muted: { color: color.ink[500] },
  link: { color: color.blue[600], fontWeight: '600' },
});
