import React, { useEffect, useState } from 'react';
import { Alert, Linking, View, Text, Pressable, ScrollView, StyleSheet, TextInput } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Constants from 'expo-constants';
import { LOCALES, type Locale } from '@ai-radar/shared';
import { useTheme } from '../theme/ThemeProvider';
import { textStyle, space, radius } from '../theme';
import { getDict } from '../lib/dictionary';
import { SectionHeading } from '../components/SectionHeading';
import { enablePush, disablePush, isPushEnabled, syncPushPrefs } from '../lib/push';

/**
 * The notifications toggle is hidden until push actually works.
 *
 * Expo push tokens require an EAS project id, issued by Expo when you
 * run `eas init`. Without one, `getExpoPushTokenAsync` throws in a
 * standalone build, `enablePush()` catches it, and the toggle just
 * refuses with "could not turn notifications on" — a control that
 * silently fails is worse than no control, and a Play reviewer trying it
 * sees a broken feature.
 *
 * Everything below it still works and is tested; this only hides the UI.
 * To restore: run `eas init`, put the project id in app.json under
 * `expo.extra.eas.projectId`, and flip this to true.
 */
const PUSH_ENABLED = false;
import { useAuth } from '../lib/auth';

/**
 * Settings.
 *
 * Account, notifications, language, appearance, and what the app is.
 *
 * Signing in is optional and the screen says so: the app is fully usable
 * signed out, and an account only exists to keep filters and Saved in
 * step with the website.
 */
export function SettingsScreen() {
  const { palette, locale, setLocale, choice, setChoice, rtl } = useTheme();
  const dict = getDict(locale);
  const insets = useSafeAreaInsets();
  const align = rtl ? ('right' as const) : ('left' as const);

  // 'unknown' until the stored flag is read, so neither option shows as
  // selected before we know which one is true.
  const [push, setPush] = useState<'unknown' | 'on' | 'off'>('unknown');
  const [pushNote, setPushNote] = useState<string | null>(null);

  useEffect(() => {
    void isPushEnabled().then((on) => setPush(on ? 'on' : 'off'));
  }, []);

  // Language is stored on the device row so the server can pick the
  // right copy. Re-register when it changes, rather than sending Arabic
  // notifications to someone who switched to English.
  useEffect(() => {
    void syncPushPrefs({ locale });
  }, [locale]);

  async function togglePush(on: boolean) {
    setPushNote(null);

    if (!on) {
      setPush('off');
      await disablePush();
      return;
    }

    const result = await enablePush({ locale });
    if (result.ok) {
      setPush('on');
      return;
    }

    // Stay off and say why. Each reason has a different next step, and
    // "something went wrong" would leave the reader with none.
    setPush('off');
    setPushNote(
      result.reason === 'denied'
        ? dict.notificationsDenied
        : result.reason === 'unsupported'
          ? dict.notificationsUnsupported
          : dict.notificationsFailed,
    );
  }

  const themes: { key: 'system' | 'light' | 'dark'; label: string }[] = [
    { key: 'system', label: dict.themeSystem },
    { key: 'light', label: dict.themeLight },
    { key: 'dark', label: dict.themeDark },
  ];

  const localeName: Record<Locale, string> = { en: 'English', ar: 'العربية' };

  return (
    <ScrollView
      style={{ backgroundColor: palette.bg }}
      contentContainerStyle={[styles.content, { paddingBottom: insets.bottom + space.s10 }]}
    >
      <Text
        style={[
          textStyle('display', locale),
          { color: palette.text, textAlign: align, marginBottom: space.s6 },
        ]}
      >
        {dict.settings}
      </Text>

      {/* Account first, because it is the only thing here that reaches
          beyond this device. Optional throughout: the app never asks
          anyone to sign in to read. */}
      <View style={styles.block}>
        <SectionHeading title={dict.account} />
        <AccountSection dict={dict} align={align} rtl={rtl} />
      </View>

      {PUSH_ENABLED && (
        <View style={styles.block}>
          <SectionHeading title={dict.notifications} />
          <Text
            style={[
              textStyle('bodySm', locale),
              {
                color: palette.text2,
                textAlign: align,
                writingDirection: rtl ? 'rtl' : 'ltr',
                marginBottom: space.s3,
              },
            ]}
          >
            {dict.notificationsHelp}
          </Text>

          <View style={[styles.options, { flexDirection: rtl ? 'row-reverse' : 'row' }]}>
            <Option
              label={dict.notificationsOn}
              selected={push === 'on'}
              onPress={() => void togglePush(true)}
            />
            <Option
              label={dict.notificationsOff}
              selected={push === 'off'}
              onPress={() => void togglePush(false)}
            />
          </View>

          {pushNote ? (
            <Text
              style={[
                textStyle('bodySm', locale),
                {
                  color: palette.warn,
                  textAlign: align,
                  writingDirection: rtl ? 'rtl' : 'ltr',
                  marginTop: space.s3,
                },
              ]}
            >
              {pushNote}
            </Text>
          ) : null}
        </View>
      )}

      <View style={styles.block}>
        <SectionHeading title={dict.language} />
        <View style={[styles.options, { flexDirection: rtl ? 'row-reverse' : 'row' }]}>
          {LOCALES.map((l) => (
            <Option
              key={l}
              label={localeName[l]}
              selected={l === locale}
              onPress={() => setLocale(l)}
            />
          ))}
        </View>
      </View>

      <View style={styles.block}>
        <SectionHeading title={dict.theme} />
        <View style={[styles.options, { flexDirection: rtl ? 'row-reverse' : 'row' }]}>
          {themes.map((t) => (
            <Option
              key={t.key}
              label={t.label}
              selected={t.key === choice}
              onPress={() => setChoice(t.key)}
            />
          ))}
        </View>
      </View>

      <View style={styles.block}>
        <SectionHeading title={dict.about} />
        <Text
          style={[
            textStyle('bodySm', locale),
            {
              color: palette.text2,
              textAlign: align,
              writingDirection: rtl ? 'rtl' : 'ltr',
            },
          ]}
        >
          {dict.aboutBody}
        </Text>
        <Pressable
          onPress={() => void Linking.openURL(`https://onairadar.com/${locale}/privacy`)}
          accessibilityRole="link"
          style={({ pressed }) => ({
            alignSelf: rtl ? 'flex-end' : 'flex-start',
            marginTop: space.s3,
            opacity: pressed ? 0.7 : 1,
          })}
        >
          <Text style={[textStyle('row', locale), { color: palette.accent }]}>
            {dict.privacyPolicy}
          </Text>
        </Pressable>
        <Text
          style={[
            textStyle('meta', locale),
            { color: palette.text3, textAlign: align, marginTop: space.s3 },
          ]}
        >
          {`v${Constants.expoConfig?.version ?? '0.1.0'}`}
        </Text>
      </View>
    </ScrollView>
  );
}

function Option({
  label,
  selected,
  onPress,
}: {
  label: string;
  selected: boolean;
  onPress: () => void;
}) {
  const { palette, locale } = useTheme();

  return (
    <Pressable
      onPress={onPress}
      accessibilityRole="radio"
      accessibilityState={{ selected }}
      style={({ pressed }) => [
        styles.option,
        {
          borderColor: selected ? palette.accent : palette.border,
          // No fill. accentQuiet is a tint meant to sit behind text2 —
          // accent-on-accentQuiet is too close in both themes to read
          // comfortably, and the border alone says "selected" clearly.
          backgroundColor: 'transparent',
          opacity: pressed ? 0.7 : 1,
        },
      ]}
    >
      <Text
        style={[
          textStyle('row', locale),
          { color: selected ? palette.accent : palette.text2 },
        ]}
      >
        {label}
      </Text>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  content: {
    paddingHorizontal: space.s4,
    paddingTop: space.s4,
  },
  block: {
    marginBottom: space.section,
  },
  options: {
    gap: space.s2,
    flexWrap: 'wrap',
  },
  input: {
    paddingVertical: space.s3,
    paddingHorizontal: space.s4,
    borderRadius: radius.chip,
    borderWidth: StyleSheet.hairlineWidth,
    fontSize: 15,
  },
  signInBtn: {
    marginTop: space.s4,
    paddingVertical: space.s3,
    paddingHorizontal: space.s6,
    borderRadius: radius.chip,
    alignItems: "center",
  },
  option: {
    paddingVertical: space.s3,
    paddingHorizontal: space.s5,
    borderRadius: radius.chip,
    borderWidth: StyleSheet.hairlineWidth,
  },
});

/**
 * Sign in, or show who is signed in.
 *
 * Two fields and a button. No social login on the app yet: OAuth in a
 * React Native app needs a browser redirect back into a custom scheme,
 * which is real work and belongs after the flow is proven on the web.
 */
function AccountSection({
  dict,
  align,
  rtl,
}: {
  dict: ReturnType<typeof getDict>;
  align: 'left' | 'right';
  rtl: boolean;
}) {
  const { palette, locale } = useTheme();
  const { account, ready, signIn, signOut, deleteAccount } = useAuth();

  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  function confirmAccountDeletion() {
    Alert.alert(dict.deleteAccountTitle, dict.deleteAccountConfirm, [
      { text: dict.cancel, style: 'cancel' },
      {
        text: dict.deleteAccount,
        style: 'destructive',
        onPress: () => {
          setBusy(true);
          setError(null);
          void deleteAccount().then((result) => {
            setBusy(false);
            if (!result.ok) setError(result.error ?? dict.deleteAccountFailed);
          });
        },
      },
    ]);
  }

  if (!ready) return null;

  if (account) {
    return (
      <View>
        <Text
          style={[
            textStyle('bodySm', locale),
            { color: palette.text2, textAlign: align, writingDirection: rtl ? 'rtl' : 'ltr' },
          ]}
        >
          {dict.signedInAs}
        </Text>
        <Text
          style={[
            textStyle('row', locale),
            // An address is LTR even inside Arabic text.
            { color: palette.text, textAlign: align, writingDirection: 'ltr', marginTop: 2 },
          ]}
        >
          {account.email}
        </Text>

        <Pressable
          onPress={() => void signOut()}
          accessibilityRole="button"
          style={({ pressed }) => [
            styles.option,
            {
              alignSelf: rtl ? 'flex-end' : 'flex-start',
              marginTop: space.s4,
              borderColor: palette.border,
              opacity: pressed ? 0.7 : 1,
            },
          ]}
        >
          <Text style={[textStyle('row', locale), { color: palette.text2 }]}>{dict.signOut}</Text>
        </Pressable>

        <Text
          style={[
            textStyle('bodySm', locale),
            {
              color: palette.text3,
              textAlign: align,
              writingDirection: rtl ? 'rtl' : 'ltr',
              marginTop: space.s6,
            },
          ]}
        >
          {dict.deleteAccountHelp}
        </Text>
        {error ? (
          <Text
            style={[
              textStyle('bodySm', locale),
              { color: palette.danger, textAlign: align, marginTop: space.s2 },
            ]}
          >
            {error}
          </Text>
        ) : null}
        <Pressable
          onPress={confirmAccountDeletion}
          disabled={busy}
          accessibilityRole="button"
          style={({ pressed }) => [
            styles.option,
            {
              alignSelf: rtl ? 'flex-end' : 'flex-start',
              marginTop: space.s3,
              borderColor: palette.danger,
              opacity: pressed || busy ? 0.5 : 1,
            },
          ]}
        >
          <Text style={[textStyle('row', locale), { color: palette.danger }]}>
            {dict.deleteAccount}
          </Text>
        </Pressable>
      </View>
    );
  }

  async function submit() {
    setBusy(true);
    setError(null);

    const result = await signIn(email.trim(), password);
    setBusy(false);

    if (!result.ok) {
      setError(result.error ?? dict.signInFailed);
      return;
    }
    setPassword('');
  }

  return (
    <View>
      <Text
        style={[
          textStyle('bodySm', locale),
          {
            color: palette.text2,
            textAlign: align,
            writingDirection: rtl ? 'rtl' : 'ltr',
            marginBottom: space.s3,
          },
        ]}
      >
        {dict.signInHelp}
      </Text>

      <TextInput
        value={email}
        onChangeText={setEmail}
        placeholder={dict.email}
        placeholderTextColor={palette.text3}
        autoCapitalize="none"
        autoCorrect={false}
        keyboardType="email-address"
        textContentType="emailAddress"
        style={[
          styles.input,
          { borderColor: palette.border, color: palette.text, backgroundColor: palette.bg },
        ]}
      />

      <TextInput
        value={password}
        onChangeText={setPassword}
        placeholder={dict.password}
        placeholderTextColor={palette.text3}
        secureTextEntry
        autoCapitalize="none"
        textContentType="password"
        style={[
          styles.input,
          {
            marginTop: space.s2,
            borderColor: palette.border,
            color: palette.text,
            backgroundColor: palette.bg,
          },
        ]}
      />

      {error ? (
        <Text
          style={[
            textStyle('bodySm', locale),
            { color: palette.danger, textAlign: align, marginTop: space.s2 },
          ]}
        >
          {error}
        </Text>
      ) : null}

      <Pressable
        onPress={() => void submit()}
        disabled={busy || email.length === 0 || password.length === 0}
        accessibilityRole="button"
        style={({ pressed }) => [
          styles.signInBtn,
          {
            backgroundColor: palette.accent,
            opacity: pressed || busy || email.length === 0 || password.length === 0 ? 0.5 : 1,
          },
        ]}
      >
        <Text style={[textStyle('card', locale), { color: '#ffffff' }]}>{dict.signIn}</Text>
      </Pressable>
    </View>
  );
}
