import { withClickTracking } from "../../services/telemetry";
import React, { useEffect, useMemo, useState } from "react";
import { KeyboardAvoidingView, Platform, ScrollView, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { useNavigation } from "../../context/NavigationContext";
import { StatusBar } from "expo-status-bar";
import { Ionicons } from "@expo/vector-icons";
import { useColorScheme } from "nativewind";
import * as Haptics from "expo-haptics";
import { Heading, MutedText, Text } from "../../components/text";
import { Button, IconButton } from "../../components/button";
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "../../components/card";
import { EmailInput, Input, PasswordInput } from "../../components/input";
import { Checkbox } from "../../components/checkbox";
import { Separator, SeparatorWithText } from "../../components/separator";
import PasswordStrengthMeter from "../../components/auth/PasswordStrengthMeter";
import PwnedPasswordWarning from "../../components/auth/PwnedPasswordWarning";
import ShakeField from "../../forms/shake-field";
import FormError from "../../forms/form-error";
import { useAuth } from "../../hooks/useAuth";
import { useShakeAnimation } from "../../hooks/useShakeAnimation";
import { validateEmail } from "../../utils/validation";
import { checkPasswordPwned, debounce, getPwnedMessage } from "../../services/hibp";
import { getCachedPolicy } from "../../services/hibp-cache";
import { useAppConfig } from "../../context/AppConfigContext";
const SCROLL_CONTENT_STYLE = { flexGrow: 1 };
const DEFAULT_POLICY = { enabled: false, enforce: false, block_threshold: 0 };
export function RegisterScreen({ topAccessory, socialAuth, passwordLabel = "Password", passwordPlaceholder = "Create a strong password", } = {}) {
    const { register: authRegister } = useAuth();
    const router = useNavigation();
    const { appName, Logo, routes } = useAppConfig();
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [confirmPassword, setConfirmPassword] = useState("");
    const [isLoading, setIsLoading] = useState(false);
    const [agreeToTerms, setAgreeToTerms] = useState(false);
    const [displayName, setDisplayName] = useState("");
    const [errors, setErrors] = useState({});
    const { colorScheme } = useColorScheme();
    const isDark = colorScheme === "dark";
    const [pwnedPasswordInfo, setPwnedPasswordInfo] = useState(null);
    const emailShake = useShakeAnimation();
    const displayNameShake = useShakeAnimation();
    const passwordShake = useShakeAnimation();
    const confirmShake = useShakeAnimation();
    const termsShake = useShakeAnimation();
    const firstError = errors.email ?? errors.displayName ?? errors.password ?? errors.confirmPassword ?? errors.terms;
    const checkPasswordDebounced = useMemo(() => debounce(async (pass) => {
        const policy = getCachedPolicy() ?? DEFAULT_POLICY;
        if (!policy.enabled || pass.length < 8) {
            setPwnedPasswordInfo(null);
            return;
        }
        const result = await checkPasswordPwned(pass);
        if (result.isPwned) {
            const message = getPwnedMessage(result);
            setPwnedPasswordInfo({ ...message, count: result.count });
        }
        else {
            setPwnedPasswordInfo(null);
        }
    }, 1000), []);
    useEffect(() => () => checkPasswordDebounced.cancel(), [checkPasswordDebounced]);
    const validateForm = () => {
        const newErrors = {};
        if (!email) {
            newErrors.email = "Email is required";
        }
        else if (!validateEmail(email)) {
            newErrors.email = "Please enter a valid email";
        }
        if (!displayName) {
            newErrors.displayName = "Display name is required";
        }
        else if (displayName.length > 100) {
            newErrors.displayName = "Display name must be 100 characters or less";
        }
        if (!password) {
            newErrors.password = "Password is required";
        }
        else if (password.length < 8) {
            newErrors.password = "Password must be at least 8 characters";
        }
        if (!confirmPassword) {
            newErrors.confirmPassword = "Please confirm your password";
        }
        else if (password !== confirmPassword) {
            newErrors.confirmPassword = "Passwords do not match";
        }
        if (!agreeToTerms) {
            newErrors.terms = "You must agree to the terms and privacy policy";
        }
        return newErrors;
    };
    const handleRegister = async () => {
        // Re-entry guard. The HIBP probe and register POST both run
        // network round-trips; a double-submit before `setIsLoading(true)`
        // lands would otherwise duplicate-fire the register endpoint
        // (and depending on idempotency could create a second account
        // attempt with the same email).
        if (isLoading) {
            return;
        }
        const newErrors = validateForm();
        if (Object.keys(newErrors).length > 0) {
            setErrors(newErrors);
            if (newErrors.email) {
                emailShake.shake();
            }
            if (newErrors.displayName) {
                displayNameShake.shake();
            }
            if (newErrors.password) {
                passwordShake.shake();
            }
            if (newErrors.confirmPassword) {
                confirmShake.shake();
            }
            if (newErrors.terms) {
                termsShake.shake();
            }
            await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
            return;
        }
        setErrors({});
        setIsLoading(true);
        const hibpPolicy = getCachedPolicy() ?? DEFAULT_POLICY;
        if (hibpPolicy.enabled) {
            const pwnedResult = await checkPasswordPwned(password);
            if (pwnedResult.isPwned) {
                const message = getPwnedMessage(pwnedResult);
                setPwnedPasswordInfo({ ...message, count: pwnedResult.count });
                if (hibpPolicy.enforce && pwnedResult.count > hibpPolicy.block_threshold) {
                    await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
                    passwordShake.shake();
                    confirmShake.shake();
                    setIsLoading(false);
                    return;
                }
            }
            else {
                setPwnedPasswordInfo(null);
            }
        }
        try {
            await authRegister(email.trim().toLowerCase(), password, displayName.trim());
            await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
        }
        catch (error) {
            await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
            const errorMessage = error instanceof Error ? error.message : "Registration failed";
            if (errorMessage.includes("email") && errorMessage.includes("exists")) {
                setErrors({ email: "This email is already registered" });
                emailShake.shake();
            }
            else if (errorMessage.includes("password")) {
                setErrors({ password: errorMessage });
                passwordShake.shake();
            }
            else {
                setErrors({ email: errorMessage });
                emailShake.shake();
            }
        }
        finally {
            setIsLoading(false);
        }
    };
    return (<SafeAreaView className="flex-1 bg-background dark:bg-black">
      <StatusBar style={isDark ? "light" : "dark"}/>
      <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"} className="flex-1">
        <ScrollView className="flex-1" contentContainerStyle={SCROLL_CONTENT_STYLE} keyboardShouldPersistTaps="handled" showsVerticalScrollIndicator={false}>
          <View className="flex-1 justify-between px-6">
            <View className="mt-4">
              <IconButton variant="ghost" size="sm" telemetryId="auth.register.push" onPress={() => router.push(routes.welcome)} accessibilityLabel="Go back" accessibilityRole="button">
                <Ionicons name="arrow-back" size={24} color={isDark ? "#FFFFFF" : "#000000"}/>
              </IconButton>
            </View>
            {topAccessory}

            <View className="flex-1 items-center justify-center">
              <View className="mb-6 items-center">
                <View className="flex-row items-center">
                  <Logo width={72} height={72} style={{ marginRight: -2 }}/>
                  <Heading className="text-4xl">{appName}</Heading>
                </View>
              </View>

              <Card className="w-full max-w-[360px]">
                <CardHeader>
                  <CardTitle>Create Account</CardTitle>
                </CardHeader>

                <CardContent className="gap-3">
                  <ShakeField shake={emailShake} label="Email">
                    <EmailInput value={email} onChangeText={(text) => {
            setEmail(text);
            if (errors.email) {
                setErrors({ ...errors, email: undefined });
            }
        }} autoFocus placeholder="you@example.com" autoComplete="email" invalid={!!errors.email} accessibilityLabel="Email address" testID="signup-email-input"/>
                  </ShakeField>

                  <ShakeField shake={displayNameShake} label="Display Name">
                    <Input value={displayName} onChangeText={(text) => {
            setDisplayName(text);
            if (errors.displayName) {
                setErrors({ ...errors, displayName: undefined });
            }
        }} placeholder="Your display name" leftIcon={<Ionicons name="person-outline" size={20} color={isDark ? "#A3A3A3" : "#737373"}/>} autoCapitalize="words" autoCorrect={false} maxLength={100} invalid={!!errors.displayName} accessibilityLabel="Display name" testID="signup-displayname-input"/>
                  </ShakeField>

                  <View>
                    <ShakeField shake={passwordShake} label={passwordLabel}>
                      <PasswordInput value={password} onChangeText={(text) => {
            setPassword(text);
            if (errors.password) {
                setErrors({ ...errors, password: undefined });
            }
            checkPasswordDebounced(text);
        }} placeholder={passwordPlaceholder} autoComplete="password-new" invalid={!!errors.password} accessibilityLabel={passwordLabel} testID="signup-password-input"/>
                    </ShakeField>
                    <View className="mt-2">
                      <PasswordStrengthMeter password={password}/>
                      <PwnedPasswordWarning pwnedInfo={pwnedPasswordInfo}/>
                    </View>
                  </View>

                  <ShakeField shake={confirmShake} label="Confirm Password">
                    <PasswordInput value={confirmPassword} onChangeText={(text) => {
            setConfirmPassword(text);
            if (errors.confirmPassword) {
                setErrors({ ...errors, confirmPassword: undefined });
            }
        }} placeholder="Re-enter your password" autoComplete="password-new" returnKeyType="done" onSubmitEditing={handleRegister} invalid={!!errors.confirmPassword} accessibilityLabel="Confirm password" testID="signup-confirm-password-input"/>
                  </ShakeField>

                  <Separator className="my-2"/>

                  <ShakeField shake={termsShake} rotate={false}>
                    <View className="flex-row items-start gap-2">
                      <Checkbox checked={agreeToTerms} onCheckedChange={(checked) => {
            setAgreeToTerms(!!checked);
            if (errors.terms) {
                setErrors({ ...errors, terms: undefined });
            }
        }} accessibilityLabel="Agree to terms of service and privacy policy" accessibilityRole="checkbox"/>
                      <Text className="flex-1 text-sm">
                        I agree to the{" "}
                        <Text className="text-sm underline" onPress={withClickTracking("auth.register.push_2", () => router.push(routes.termsOfService))} accessibilityRole="link" accessibilityLabel="Terms of Service">
                          Terms of Service
                        </Text>{" "}
                        and{" "}
                        <Text className="text-sm underline" onPress={withClickTracking("auth.register.push_3", () => router.push(routes.privacyPolicy))} accessibilityRole="link" accessibilityLabel="Privacy Policy">
                          Privacy Policy
                        </Text>
                      </Text>
                    </View>
                  </ShakeField>
                </CardContent>

                <CardFooter className="flex-col items-stretch gap-3 border-t-0">
                  <MutedText className="text-center text-sm">
                    Already have an account?{" "}
                    <Text className="text-sm text-foreground underline" onPress={withClickTracking("auth.register.push_4", () => router.push(routes.login))} accessibilityRole="link" accessibilityLabel="Sign in">
                      Sign In
                    </Text>
                  </MutedText>

                  <FormError message={firstError}/>

                  <Button className="w-full" isLoading={isLoading} telemetryId="auth.register.register" onPress={handleRegister} disabled={Platform.OS === "web" && !email && !password} accessibilityLabel="Create account" accessibilityRole="button" accessibilityHint="Double tap to create your account" testID="signup-submit">
                    Create Account
                  </Button>

                  {socialAuth ? (<>
                      <SeparatorWithText />
                      {socialAuth}
                    </>) : null}
                </CardFooter>
              </Card>

              <View className="mb-6"/>
            </View>
          </View>
        </ScrollView>
      </KeyboardAvoidingView>
    </SafeAreaView>);
}
export default RegisterScreen;
//# sourceMappingURL=RegisterScreen.jsx.map