import { useState } from "react";
import Constants from "expo-constants";
import { router } from "expo-router";
import { Alert, Platform, Pressable, StyleSheet, Switch, Text, View } from "react-native";
import { TabPage } from "@/components/TabPage";
import { TabScrollView } from "@/components/TabScrollView";

import { AppBackground } from "@/components/AppBackground";
import { InstanceUrlField } from "@/components/InstanceUrlField";
import { LoadingScreen } from "@/components/LoadingScreen";
import { PageHeader } from "@/components/PageHeader";
import { PinPrompt } from "@/components/PinPrompt";
import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { fonts, spacing } from "@/constants/theme";
import { useAccounts } from "@/contexts/AccountsContext";
import { useAppLock } from "@/contexts/AppLockContext";
import { useAuthClient, useSession } from "@/contexts/AuthContext";
import { type ColorMode, useAppTheme } from "@/contexts/ThemeContext";
import { api } from "@/lib/trpc";

const THEME_OPTIONS: { value: ColorMode; label: string }[] = [
  { value: "system", label: "System" },
  { value: "light", label: "Light" },
  { value: "dark", label: "Dark" },
];

export default function SettingsScreen() {
  const authClient = useAuthClient();
  const { data: session } = useSession();
  const {
    accounts,
    activeAccount,
    activeAccountId,
    apiUrl,
    switchAccount,
    removeAccount,
    clearActiveAccount,
  } = useAccounts();
  const { colors, colorMode, setColorMode } = useAppTheme();
  const {
    enabled: lockEnabled,
    biometricEnabled,
    biometricAvailable,
    biometricLabel,
    enableLock,
    disableLock,
    changePin,
    setUseBiometric,
    lock,
  } = useAppLock();
  const profileQuery = api.settings.getProfile.useQuery();

  const [pinPrompt, setPinPrompt] = useState<
    | { mode: "create" }
    | { mode: "confirm-disable" }
    | { mode: "change-current" }
    | { mode: "change-next" }
    | null
  >(null);
  const [pendingPin, setPendingPin] = useState("");

  async function handleSignOut() {
    await authClient.signOut();
    await clearActiveAccount();
    router.replace("/(auth)/sign-in");
  }

  function confirmSignOut() {
    Alert.alert("Sign out", "Sign out of this account on this device?", [
      { text: "Cancel", style: "cancel" },
      { text: "Sign out", style: "destructive", onPress: handleSignOut },
    ]);
  }

  function confirmRemoveAccount(accountId: string, label: string) {
    Alert.alert("Remove account", `Remove ${label} from this device?`, [
      { text: "Cancel", style: "cancel" },
      {
        text: "Remove",
        style: "destructive",
        onPress: () => void removeAccount(accountId),
      },
    ]);
  }

  function confirmInstanceChange() {
    Alert.alert(
      "Server updated",
      "You may need to sign in again if you switched to a different instance.",
      [{ text: "OK" }],
    );
  }

  function handleLockToggle(next: boolean) {
    if (next) {
      setPinPrompt({ mode: "create" });
      return;
    }
    setPinPrompt({ mode: "confirm-disable" });
  }

  function handleChangePin() {
    setPendingPin("");
    setPinPrompt({ mode: "change-current" });
  }

  function handleBiometricToggle(next: boolean) {
    void setUseBiometric(next);
  }

  async function handlePinPromptSubmit(pin: string) {
    if (pinPrompt?.mode === "create") {
      try {
        await enableLock(pin);
        setPinPrompt(null);
      } catch (err) {
        Alert.alert("Could not enable lock", err instanceof Error ? err.message : "Try again");
      }
      return;
    }

    if (pinPrompt?.mode === "confirm-disable") {
      const success = await disableLock(pin);
      if (!success) {
        Alert.alert("Incorrect PIN", "Could not disable app lock.");
        return;
      }
      setPinPrompt(null);
      return;
    }

    if (pinPrompt?.mode === "change-current") {
      setPendingPin(pin);
      setPinPrompt({ mode: "change-next" });
      return;
    }

    if (pinPrompt?.mode === "change-next") {
      const success = await changePin(pendingPin, pin);
      if (!success) {
        Alert.alert("Could not change PIN", "Check your current PIN and try again.");
        return;
      }
      setPendingPin("");
      setPinPrompt(null);
      Alert.alert("PIN updated", "Your app lock PIN has been changed.");
    }
  }

  if (profileQuery.isLoading) {
    return <LoadingScreen message="Loading profile…" />;
  }

  const profile = profileQuery.data;
  const appVersion = Constants.expoConfig?.version ?? "1.0.0";

  return (
    <AppBackground>
      <TabPage>
        <PinPrompt
          visible={pinPrompt !== null}
          title={
            pinPrompt?.mode === "create"
              ? "Create PIN"
              : pinPrompt?.mode === "confirm-disable"
                ? "Disable app lock"
                : pinPrompt?.mode === "change-current"
                  ? "Current PIN"
                  : "New PIN"
          }
          message={
            pinPrompt?.mode === "create" || pinPrompt?.mode === "change-next"
              ? "Choose a 4–6 digit PIN."
              : pinPrompt?.mode === "confirm-disable"
                ? "Enter your PIN to turn off app lock."
                : "Enter your current PIN."
          }
          confirmLabel={
            pinPrompt?.mode === "create" || pinPrompt?.mode === "change-next" ? "Save" : "Continue"
          }
          requireConfirmation={pinPrompt?.mode === "create" || pinPrompt?.mode === "change-next"}
          onCancel={() => {
            setPendingPin("");
            setPinPrompt(null);
          }}
          onSubmit={(pin) => void handlePinPromptSubmit(pin)}
        />
        <TabScrollView
          header={
            <PageHeader title="Settings" subtitle="Account and app preferences" />
          }
          keyboardShouldPersistTaps="handled"
        >
          <Card title="Account">
            <Text style={[styles.name, { color: colors.foreground }]}>
              {profile?.name ?? session?.user.name ?? "User"}
            </Text>
            <Text style={[styles.email, { color: colors.mutedForeground }]}>
              {profile?.email ?? session?.user.email}
            </Text>
            {profile?.role ? (
              <Text style={[styles.meta, { color: colors.mutedForeground }]}>
                Role: {profile.role}
              </Text>
            ) : null}
          </Card>

          <Card title="Accounts">
            {accounts.map((account) => {
              const isActive = account.id === activeAccountId;
              return (
                <Pressable
                  key={account.id}
                  accessibilityRole="button"
                  onPress={() => void switchAccount(account.id)}
                  onLongPress={() => confirmRemoveAccount(account.id, account.email)}
                  style={({ pressed }) => [
                    styles.accountRow,
                    {
                      borderColor: colors.border,
                      backgroundColor: isActive ? colors.muted : "transparent",
                    },
                    pressed && styles.pressed,
                  ]}
                >
                  <View style={styles.accountMeta}>
                    <Text style={[styles.accountName, { color: colors.foreground }]}>
                      {account.name || account.email}
                    </Text>
                    <Text style={[styles.accountSub, { color: colors.mutedForeground }]}>
                      {account.email}
                    </Text>
                    <Text style={[styles.accountSub, { color: colors.mutedForeground }]}>
                      {account.instanceUrl.replace(/^https?:\/\//, "")}
                    </Text>
                  </View>
                  {isActive ? (
                    <Text style={[styles.activeBadge, { color: colors.primary }]}>Active</Text>
                  ) : null}
                </Pressable>
              );
            })}
            <Button
              title="Add another account"
              variant="secondary"
              onPress={async () => {
                await authClient.signOut();
                await clearActiveAccount();
                router.replace("/(auth)/sign-in");
              }}
            />
            {accounts.length > 1 ? (
              <Text style={[styles.meta, { color: colors.mutedForeground }]}>
                Long-press an account to remove it from this device.
              </Text>
            ) : null}
          </Card>

          <Card title="Security">
            <View style={styles.settingRow}>
              <View style={styles.settingCopy}>
                <Text style={[styles.settingTitle, { color: colors.foreground }]}>App lock</Text>
                <Text style={[styles.meta, { color: colors.mutedForeground }]}>
                  Require a PIN when reopening the app
                </Text>
              </View>
              <Switch
                value={lockEnabled}
                onValueChange={handleLockToggle}
                trackColor={{ false: colors.border, true: colors.primary }}
              />
            </View>

            {lockEnabled && biometricAvailable ? (
              <View style={styles.settingRow}>
                <View style={styles.settingCopy}>
                  <Text style={[styles.settingTitle, { color: colors.foreground }]}>
                    {biometricLabel}
                  </Text>
                  <Text style={[styles.meta, { color: colors.mutedForeground }]}>
                    Unlock with {biometricLabel.toLowerCase()} when available
                  </Text>
                </View>
                <Switch
                  value={biometricEnabled}
                  onValueChange={handleBiometricToggle}
                  trackColor={{ false: colors.border, true: colors.primary }}
                />
              </View>
            ) : null}

            {lockEnabled ? (
              <>
                <Button title="Change PIN" variant="secondary" onPress={handleChangePin} />
                <Button title="Lock now" variant="secondary" onPress={lock} />
              </>
            ) : null}
          </Card>

          <Card title="Appearance">
            <View style={styles.themeRow}>
              {THEME_OPTIONS.map((option) => {
                const selected = colorMode === option.value;
                return (
                  <Pressable
                    key={option.value}
                    accessibilityRole="button"
                    onPress={() => void setColorMode(option.value)}
                    style={[
                      styles.themeChip,
                      {
                        borderColor: selected ? colors.primary : colors.border,
                        backgroundColor: selected ? colors.muted : "transparent",
                      },
                    ]}
                  >
                    <Text
                      style={[
                        styles.themeChipLabel,
                        { color: selected ? colors.foreground : colors.mutedForeground },
                      ]}
                    >
                      {option.label}
                    </Text>
                  </Pressable>
                );
              })}
            </View>
          </Card>

          <Card title="Server instance">
            <InstanceUrlField onSaved={confirmInstanceChange} />
            <Text style={[styles.currentServer, { color: colors.mutedForeground }]}>
              Connected to {activeAccount?.instanceUrl ?? apiUrl}
            </Text>
          </Card>

          <Card title="App">
            <View style={styles.appRow}>
              <Text style={[styles.meta, { color: colors.mutedForeground }]}>Version</Text>
              <Text style={[styles.appValue, { color: colors.foreground }]}>{appVersion}</Text>
            </View>
            <View style={styles.appRow}>
              <Text style={[styles.meta, { color: colors.mutedForeground }]}>Platform</Text>
              <Text style={[styles.appValue, { color: colors.foreground }]}>
                {Constants.platform?.ios ? "iOS" : "Other"}
              </Text>
            </View>
          </Card>

          <View style={styles.actions}>
            <Button title="Sign Out" variant="danger" onPress={confirmSignOut} />
          </View>
        </TabScrollView>
      </TabPage>
    </AppBackground>
  );
}

const styles = StyleSheet.create({
  name: {
    fontSize: 20,
    fontFamily: fonts.heading,
  },
  email: {
    fontSize: 15,
    fontFamily: fonts.body,
  },
  meta: {
    fontSize: 13,
    fontFamily: fonts.bodyMedium,
  },
  currentServer: {
    fontSize: 12,
    fontFamily: fonts.mono,
  },
  appRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
  },
  appValue: {
    fontSize: 14,
    fontFamily: fonts.bodyMedium,
  },
  accountRow: {
    borderWidth: 1,
    borderRadius: 12,
    padding: spacing.md,
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    gap: spacing.md,
  },
  pressed: {
    opacity: 0.92,
  },
  accountMeta: {
    flex: 1,
    gap: 2,
  },
  accountName: {
    fontSize: 15,
    fontFamily: fonts.bodySemiBold,
  },
  accountSub: {
    fontSize: 12,
    fontFamily: fonts.body,
  },
  activeBadge: {
    fontSize: 12,
    fontFamily: fonts.bodySemiBold,
  },
  themeRow: {
    flexDirection: "row",
    gap: spacing.sm,
  },
  themeChip: {
    flex: 1,
    borderWidth: 1,
    borderRadius: 10,
    minHeight: 40,
    alignItems: "center",
    justifyContent: "center",
    paddingHorizontal: spacing.sm,
  },
  themeChipLabel: {
    fontSize: 13,
    fontFamily: fonts.bodyMedium,
    lineHeight: 18,
    ...(Platform.OS === "android" ? { includeFontPadding: false } : null),
  },
  settingRow: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    gap: spacing.md,
  },
  settingCopy: {
    flex: 1,
    gap: 2,
  },
  settingTitle: {
    fontSize: 15,
    fontFamily: fonts.bodySemiBold,
  },
  actions: {
    marginTop: spacing.sm,
  },
});
