import { Ionicons } from "@expo/vector-icons";
import { useEffect, useState } from "react";
import { Pressable, StyleSheet, Text, View } from "react-native";

import { Input } from "@/components/ui/Input";
import { fonts, spacing } from "@/constants/theme";
import { useAccounts } from "@/contexts/AccountsContext";
import { useAppTheme } from "@/contexts/ThemeContext";
import { DEFAULT_API_URL, OFFICIAL_SERVER_PLACEHOLDER, invalidServerUrlMessage } from "@/lib/config";
import {
  formatServerHost,
  isServerConfigValid,
  resolveServerMode,
  resolveServerUrl,
  SERVER_MODE_OPTIONS,
  type ServerMode,
} from "@/lib/server-mode";

type AuthServerPickerProps = {
  onReadyChange?: (ready: boolean) => void;
  /** When true, picker sits inside the auth card with no outer margin. */
  embedded?: boolean;
};

function modeSummary(mode: ServerMode, selfHostedUrl: string) {
  if (mode === "official") return "Official";
  const host = formatServerHost(selfHostedUrl);
  return host || "Self-hosted";
}

export function AuthServerPicker({ onReadyChange, embedded = false }: AuthServerPickerProps) {
  const { colors } = useAppTheme();
  const { apiUrl, setInstanceUrl } = useAccounts();
  const [expanded, setExpanded] = useState(false);
  const [mode, setMode] = useState<ServerMode>(() => resolveServerMode(apiUrl));
  const [selfHostedUrl, setSelfHostedUrl] = useState(() =>
    resolveServerMode(apiUrl) === "self-hosted" ? apiUrl : "",
  );
  const [urlError, setUrlError] = useState<string | null>(null);

  const ready = isServerConfigValid(mode, selfHostedUrl);

  useEffect(() => {
    onReadyChange?.(ready);
  }, [ready, onReadyChange]);

  useEffect(() => {
    const nextMode = resolveServerMode(apiUrl);
    setMode(nextMode);
    if (nextMode === "self-hosted") {
      setSelfHostedUrl(apiUrl);
    }
  }, [apiUrl]);

  async function applyMode(nextMode: ServerMode) {
    setMode(nextMode);
    setUrlError(null);

    if (nextMode === "official") {
      try {
        await setInstanceUrl(DEFAULT_API_URL);
        setExpanded(false);
      } catch (err) {
        setUrlError(err instanceof Error ? err.message : "Could not set server");
      }
      return;
    }

    setExpanded(true);
    const resolved = resolveServerUrl("self-hosted", selfHostedUrl);
    if (!resolved) return;

    try {
      await setInstanceUrl(resolved);
    } catch (err) {
      setUrlError(err instanceof Error ? err.message : "Could not set server");
    }
  }

  async function commitSelfHostedUrl() {
    const resolved = resolveServerUrl("self-hosted", selfHostedUrl);
    if (!resolved) {
      setUrlError(invalidServerUrlMessage());
      return;
    }

    try {
      const saved = await setInstanceUrl(resolved);
      setSelfHostedUrl(saved);
      setUrlError(null);
      setExpanded(false);
    } catch (err) {
      setUrlError(err instanceof Error ? err.message : "Could not save server URL");
    }
  }

  return (
    <View style={[styles.wrapper, embedded && styles.wrapperEmbedded]}>
      <Pressable
        accessibilityRole="button"
        accessibilityState={{ expanded }}
        onPress={() => setExpanded((open) => !open)}
        hitSlop={8}
        style={({ pressed }) => [styles.trigger, pressed && styles.pressed]}
      >
        <Text style={[styles.triggerText, { color: colors.mutedForeground }]}>
          Server ·{" "}
          <Text style={[styles.summary, { color: colors.foreground }]}>
            {modeSummary(mode, selfHostedUrl)}
          </Text>
        </Text>
        <Ionicons
          name={expanded ? "chevron-up" : "chevron-down"}
          size={16}
          color={colors.mutedForeground}
        />
      </Pressable>

      {expanded ? (
        <View
          style={[
            styles.panel,
            { backgroundColor: colors.cardGlass, borderColor: colors.borderGlass },
          ]}
        >
          {SERVER_MODE_OPTIONS.map((option) => {
            const selected = option.value === mode;
            return (
              <Pressable
                key={option.value}
                accessibilityRole="button"
                accessibilityState={{ selected }}
                onPress={() => void applyMode(option.value)}
                style={({ pressed }) => [
                  styles.option,
                  {
                    borderColor: colors.border,
                    backgroundColor: selected ? colors.muted : "transparent",
                  },
                  pressed && styles.pressed,
                ]}
              >
                <Text style={[styles.optionLabel, { color: colors.foreground }]}>
                  {option.label}
                </Text>
                {selected ? (
                  <Ionicons name="checkmark" size={18} color={colors.primary} />
                ) : null}
              </Pressable>
            );
          })}

          {mode === "self-hosted" ? (
            <>
              <Input
                label="Server URL"
                value={selfHostedUrl}
                onChangeText={(value) => {
                  setSelfHostedUrl(value);
                  setUrlError(null);
                }}
                onBlur={() => void commitSelfHostedUrl()}
                onSubmitEditing={() => void commitSelfHostedUrl()}
                autoCapitalize="none"
                autoCorrect={false}
                keyboardType="url"
                placeholder={OFFICIAL_SERVER_PLACEHOLDER}
                required
                error={urlError ?? undefined}
              />
              <Text style={[styles.hint, { color: colors.mutedForeground }]}>
                Use your Mac&apos;s LAN IP on a physical device.
              </Text>
            </>
          ) : null}
        </View>
      ) : null}
    </View>
  );
}

const styles = StyleSheet.create({
  wrapper: {
    gap: spacing.sm,
    marginBottom: spacing.md,
  },
  wrapperEmbedded: {
    marginBottom: 0,
  },
  trigger: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    gap: spacing.xs,
    minHeight: 36,
  },
  pressed: {
    opacity: 0.7,
  },
  triggerText: {
    fontSize: 13,
    fontFamily: fonts.body,
  },
  summary: {
    fontFamily: fonts.bodyMedium,
    fontSize: 13,
  },
  panel: {
    borderWidth: 1,
    borderRadius: 14,
    padding: spacing.md,
    gap: spacing.sm,
  },
  option: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    minHeight: 44,
    paddingHorizontal: spacing.md,
    borderRadius: 10,
    borderWidth: 1,
  },
  optionLabel: {
    fontFamily: fonts.bodyMedium,
    fontSize: 15,
  },
  hint: {
    fontSize: 12,
    fontFamily: fonts.body,
    lineHeight: 16,
  },
});
