import React, { useEffect, useState } from "react";
import { Platform, Pressable, TextInput, View } from "react-native";
import Animated, { cancelAnimation, Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming, } from "react-native-reanimated";
import { Ionicons } from "@expo/vector-icons";
import { useColorScheme } from "nativewind";
import { Dialog, DialogContent, DialogFooter } from "./dialog";
import { Text } from "./text";
import AuthService from "../services/auth.service";
import { getDefaultBaseUrl } from "../services/api-config";
import { useAppConfig } from "../context/AppConfigContext";
const HOVER_COLOR = "#22C55E";
/**
 * Settings gear icon that opens the server-configuration dialog.
 * Renders as an absolute-positioned button in the top-right corner.
 * Use on any auth screen to give users a self-hosted-server entry
 * point.
 */
export function ServerSettings({ healthCheckPath = "/api/health", validateHealthResponse, validationFailureMessage, urlPlaceholder = "https://example.com", } = {}) {
    const { colorScheme } = useColorScheme();
    const isDark = colorScheme === "dark";
    const { appName } = useAppConfig();
    const [visible, setVisible] = useState(false);
    const [serverUrl, setServerUrl] = useState("");
    const [testingServer, setTestingServer] = useState(false);
    const [testResult, setTestResult] = useState(null);
    const [retryCount, setRetryCount] = useState(0);
    const isOverridden = serverUrl !== getDefaultBaseUrl();
    const progressAnimation = useSharedValue(0);
    const shimmerAnimation = useSharedValue(0);
    useEffect(() => {
        if (visible) {
            setServerUrl(AuthService.getBaseUrl());
            setTestResult(null);
        }
    }, [visible]);
    useEffect(() => {
        if (testingServer) {
            progressAnimation.value = 0;
            shimmerAnimation.value = 0;
            shimmerAnimation.value = withRepeat(withTiming(1, { duration: 500, easing: Easing.linear }), -1);
        }
        else {
            cancelAnimation(shimmerAnimation);
            shimmerAnimation.value = 0;
        }
    }, [testingServer, progressAnimation, shimmerAnimation]);
    const animatedProgressStyle = useAnimatedStyle(() => ({
        width: `${progressAnimation.value}%`,
    }));
    const animatedShimmerStyle = useAnimatedStyle(() => ({
        transform: [{ translateX: -50 + shimmerAnimation.value * 350 }],
    }));
    const defaultValidate = (body) => {
        if (!body || typeof body !== "object") {
            return false;
        }
        const obj = body;
        return Boolean(obj.status) && Boolean(obj.version);
    };
    const validate = validateHealthResponse ?? defaultValidate;
    const invalidServerMessage = validationFailureMessage ?? `Not a valid ${appName} server`;
    const handleTest = async () => {
        setTestingServer(true);
        setTestResult(null);
        setRetryCount(0);
        progressAnimation.value = 0;
        const urlRegex = /^https?:\/\/[\w-]+(\.[\w-]+)*(:\d+)?(\/.*)?$/;
        if (!urlRegex.test(serverUrl)) {
            setTestResult({
                success: false,
                message: "Invalid URL format. Please use http:// or https://",
            });
            setTestingServer(false);
            return;
        }
        let url;
        try {
            url = new URL(serverUrl);
        }
        catch {
            setTestResult({ success: false, message: "Invalid URL format" });
            setTestingServer(false);
            return;
        }
        const maxRetries = 3;
        const retryDelay = 2000;
        let attemptCount = 0;
        let lastError = null;
        const attemptConnection = async () => {
            attemptCount++;
            setRetryCount(attemptCount);
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), 3000);
            try {
                const healthUrl = `${url.origin}${healthCheckPath}`;
                const response = await fetch(healthUrl, {
                    method: "GET",
                    signal: controller.signal,
                    headers: { Accept: "application/json" },
                });
                if (response.ok) {
                    const data = await response.json();
                    if (!validate(data)) {
                        throw new Error(invalidServerMessage);
                    }
                    return true;
                }
                return false;
            }
            catch (error) {
                lastError = error;
                return false;
            }
            finally {
                clearTimeout(timeoutId);
                progressAnimation.value = withTiming((attemptCount / maxRetries) * 100, {
                    duration: 300,
                    easing: Easing.out(Easing.cubic),
                });
            }
        };
        let success = false;
        for (let i = 0; i < maxRetries; i++) {
            if (i > 0) {
                await new Promise((resolve) => setTimeout(resolve, retryDelay));
            }
            success = await attemptConnection();
            if (success) {
                break;
            }
        }
        if (success) {
            setTestResult({ success: true, message: "Server is reachable!" });
        }
        else if (lastError instanceof Error && lastError.name === "AbortError") {
            setTestResult({
                success: false,
                message: `Connection timeout after ${maxRetries} attempts`,
            });
        }
        else {
            setTestResult({
                success: false,
                message: `Cannot reach server after ${maxRetries} attempts`,
            });
        }
        setTestingServer(false);
        setRetryCount(0);
    };
    const handleSave = async () => {
        try {
            await AuthService.setBaseUrl(serverUrl);
            setVisible(false);
        }
        catch (e) {
            const msg = e instanceof Error ? e.message : "Invalid server URL";
            setTestResult({ success: false, message: msg });
        }
    };
    const handleReset = async () => {
        await AuthService.resetBaseUrl();
        setServerUrl(getDefaultBaseUrl());
        setTestResult(null);
    };
    const close = () => setVisible(false);
    return (<>
      <Pressable onPress={() => setVisible(true)} style={{ position: "absolute", top: 16, right: 24, zIndex: 10 }} accessibilityLabel="Server settings" accessibilityRole="button">
        {({ pressed, hovered }) => {
            const active = pressed || hovered;
            return (<View style={{
                    padding: 8,
                    borderRadius: 4,
                    backgroundColor: active ? HOVER_COLOR : "transparent",
                }}>
              <Ionicons name="settings-outline" size={24} color={active ? "#FFFFFF" : isDark ? "#FFFFFF" : "#000000"}/>
            </View>);
        }}
      </Pressable>

      <Dialog visible={visible} onClose={close} title="Server Configuration" draggable>
        <DialogContent>
          <Text className="font-mono text-sm mb-2" style={{ color: isDark ? "#FFFFFF" : "#000000" }}>
            Configure your self-hosted server URL
          </Text>
          <View className="rounded-lg px-3 flex-row items-center" style={{
            borderWidth: 1,
            borderColor: isDark ? "#333333" : "#E5E5E5",
            paddingVertical: Platform.OS === "ios" ? 12 : 8,
            backgroundColor: isDark ? "#0A0A0A" : "#FAFAFA",
        }}>
            <Ionicons name="server-outline" size={20} color={isDark ? "#999999" : "#666666"} style={{ marginRight: 8 }}/>
            <TextInput value={serverUrl} onChangeText={setServerUrl} placeholder={urlPlaceholder} placeholderTextColor={isDark ? "#666666" : "#999999"} className="font-sans flex-1 text-base" style={{ color: isDark ? "#FFFFFF" : "#000000" }} autoCapitalize="none" autoCorrect={false}/>
          </View>
          {(testingServer || testResult) && (<View style={{
                marginTop: 8,
                padding: 8,
                borderRadius: 6,
                backgroundColor: testingServer
                    ? isDark
                        ? "#22C55E20"
                        : "#22C55E10"
                    : testResult?.success
                        ? isDark
                            ? "#22C55E20"
                            : "#22C55E10"
                        : isDark
                            ? "#EF444420"
                            : "#EF444410",
                borderWidth: 1,
                borderColor: testingServer
                    ? isDark
                        ? "#22C55E40"
                        : "#22C55E30"
                    : testResult?.success
                        ? isDark
                            ? "#22C55E40"
                            : "#22C55E30"
                        : isDark
                            ? "#EF444440"
                            : "#EF444430",
            }}>
              <Text className="font-mono text-xs text-center" style={{
                color: testingServer ? "#22C55E" : testResult?.success ? "#22C55E" : "#EF4444",
            }}>
                {testingServer
                ? `Testing server connection... (Attempt ${retryCount}/3)`
                : testResult?.message}
              </Text>
              {testingServer && (<View style={{
                    height: 3,
                    backgroundColor: isDark ? "#22C55E20" : "#22C55E10",
                    borderRadius: 1.5,
                    marginTop: 6,
                    overflow: "hidden",
                }}>
                  <Animated.View style={[
                    {
                        height: "100%",
                        backgroundColor: "#22C55E",
                        borderRadius: 1.5,
                        overflow: "hidden",
                    },
                    animatedProgressStyle,
                ]}>
                    <Animated.View style={[
                    {
                        position: "absolute",
                        top: 0,
                        left: 0,
                        width: 50,
                        height: "100%",
                        opacity: 0.4,
                    },
                    animatedShimmerStyle,
                ]}>
                      <View style={{
                    width: "100%",
                    height: "100%",
                    backgroundColor: "#FFFFFF",
                    transform: [{ skewX: "-20deg" }],
                }}/>
                    </Animated.View>
                  </Animated.View>
                </View>)}
            </View>)}
        </DialogContent>
        <DialogFooter style={{ justifyContent: "space-between" }}>
          <View className="flex-row gap-3">
            <ServerSettingsButton label="Test" onPress={handleTest} disabled={testingServer} filled/>
            {isOverridden && <ServerSettingsButton label="Reset" onPress={handleReset}/>}
          </View>
          <View className="flex-row gap-3">
            <ServerSettingsButton label="Cancel" onPress={close}/>
            <ServerSettingsButton label="Save" onPress={handleSave} filled/>
          </View>
        </DialogFooter>
      </Dialog>
    </>);
}
/** Reusable dialog button with green hover effect, used by the ServerSettings footer. */
function ServerSettingsButton({ label, onPress, disabled, filled, }) {
    const { colorScheme } = useColorScheme();
    const isDark = colorScheme === "dark";
    return (<Pressable onPress={onPress} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} disabled={disabled}>
      {({ pressed, hovered }) => {
            const active = pressed || hovered;
            const defaultBg = filled ? (isDark ? "#FFFFFF" : "#000000") : "transparent";
            const defaultText = filled
                ? isDark
                    ? "#000000"
                    : "#FFFFFF"
                : isDark
                    ? "#FFFFFF"
                    : "#000000";
            return (<View className="px-4 rounded-lg" style={{
                    paddingVertical: 10,
                    backgroundColor: active ? HOVER_COLOR : defaultBg,
                }}>
            <Text className="font-mono-medium text-sm text-center" style={{ color: active ? "#FFFFFF" : defaultText }}>
              {label}
            </Text>
          </View>);
        }}
    </Pressable>);
}
export default ServerSettings;
//# sourceMappingURL=server-settings.jsx.map