import { useState } from "react";
import {
  Alert,
  Anchor,
  Button,
  Checkbox,
  Divider,
  Group,
  PasswordInput,
  Stack,
  Text,
  TextInput,
  Title,
  UnstyledButton,
} from "@mantine/core";
import {
  IconArrowLeft,
  IconArrowRight,
  IconDeviceMobile,
  IconLock,
  IconMail,
} from "@tabler/icons-react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useNavigate, Link } from "react-router-dom";
import { useDispatch } from "react-redux";
import { useTranslation } from "react-i18next";
import { useApiMutation } from "@ema-platform/api";
import { notify, useErrorHandler } from "@ema-platform/ui";
import { isValidPhoneNumber, parsePhoneNumberFromString } from "libphonenumber-js";
import { AuthShell } from "../components/AuthShell";
import { loginSuccess, setUser, setCurrentProfile } from "../store/auth.slice";
import type {
  LoginPayload,
  AuthUser,
  CurrentProfile,
} from "../types/auth.types";
import { useAuthConfig } from "../AuthConfig";
import { authStorage } from "../utils/auth-storage";

export function LoginPage() {
  const navigate = useNavigate();
  const dispatch = useDispatch();
  const { t } = useTranslation();
  const { appName, loginRedirectPath, enableSignup, enableForgotPassword } =
    useAuthConfig();
  const [isLoading, setIsLoading] = useState(false);
  const [rememberMe, setRememberMe] = useState(true);
  const [serverError, setServerError] = useState<string | null>(null);
  const { handleError } = useErrorHandler();
  const [loginTrigger] = useApiMutation<LoginPayload>();
  const [meTrigger] = useApiMutation<AuthUser>();
  const [profileTrigger] = useApiMutation<{ profile: CurrentProfile | null }>();

  const handleBack = () => {
    navigate("/");
  };

  // Built inside the component (not module scope) so validation messages
  // pick up the active language — same pattern as ProfilePage's forms.
  const schema = z.object({
    email: z
      .string()
      .trim()
      .transform((value) => {
        // A phone-looking value normalizes to E.164 (bare Ethiopian
        // national numbers, e.g. 09xxxxxxxx, default to +251) so the
        // international check below can validate it; anything else
        // (an email) passes through untouched.
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (emailRegex.test(value)) return value;
        return parsePhoneNumberFromString(value, "ET")?.number ?? value;
      })
      .refine(
        (value) => {
          const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
          return emailRegex.test(value) || isValidPhoneNumber(value);
        },
        {
          message: t(
            "login.emailOrPhoneInvalid",
            "Enter a valid email or phone number",
          ),
        },
      ),
    password: z.string().min(8, {
      message: t("login.passwordMinLength", "Password must be at least 8 characters"),
    }),
  });

  type FormValues = z.infer<typeof schema>;

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormValues>({
    resolver: zodResolver(schema),
  });

  const onSubmit = async (values: FormValues) => {
    setIsLoading(true);
    try {
      const data = await loginTrigger({
        url: "/auth/login",
        method: "POST",
        body: values,
      }).unwrap();

      // Two-step verification on: the server withheld the tokens and mailed a
      // one-time code instead. Storing this response would write an undefined
      // token and 401 the very next request.
      if (data.mfaRequired) {
        navigate("/otp-verify", {
          state: { mode: "mfa", email: values.email },
        });
        return;
      }

      dispatch(loginSuccess(data));

      const me = await meTrigger({
        url: "/auth/me",
        method: "GET",
      }).unwrap();
      dispatch(setUser(me));

      // Warm the profile so screens that need an id have one on first paint.
      // `/profiles/me` provisions an empty profile when the user has none, so
      // unlike the old filtered lookup this cannot come back empty-handed.
      // Sign-in is still never gated on it — a failure here is ignored and
      // `useCurrentProfile` resolves it again on demand.
      try {
        const { profile } = await profileTrigger({
          url: "/profiles/me",
          method: "GET",
        }).unwrap();
        if (profile) {
          authStorage.setProfileId(profile.id);
          dispatch(setCurrentProfile(profile));
        }
      } catch {
        // Offline or a 5xx — the portal still works; the resolver retries.
      }

      if (!me.isPhoneNumberVerified) {
        navigate("/otp-verify", {
          state: {
            email: me.email,
            phoneNumber: me.phoneNumber,
          },
        });
        return;
      }

      navigate(loginRedirectPath);
    } catch (err: unknown) {
      setServerError(handleError(err));
    } finally {
      localStorage.setItem("rememberMe", String(rememberMe));
      setIsLoading(false);
    }
  };

  return (
    <AuthShell>
      <Stack gap="lg">
        <UnstyledButton
          onClick={handleBack}
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            fontSize: 14,
            fontWeight: 600,
            color: "var(--mantine-color-dimmed)",
            cursor: "pointer",
            width: "fit-content",
            transition: "all 150ms ease",
          }}
          onMouseEnter={(e) => {
            e.currentTarget.style.color = "var(--mantine-primary-color-filled)";
            e.currentTarget.style.transform = "translateX(-3px)";
          }}
          onMouseLeave={(e) => {
            e.currentTarget.style.color = "var(--mantine-color-dimmed)";
            e.currentTarget.style.transform = "translateX(0)";
          }}
        >
          <IconArrowLeft size={18} />
          {t("common.back", "Back")}
        </UnstyledButton>

        <div>
          <Title order={2} fz={30}>
            {t("login.welcome", { appName, defaultValue: "Welcome to {{appName}}" })}
          </Title>
          <Text c="dimmed" mt={6}>
            {t("login.subtitle", "Sign in to access your account.")}
          </Text>
        </div>

        {serverError && (
          <Alert
            variant="light"
            color="red"
            withCloseButton
            onClose={() => setServerError(null)}
          >
            {serverError}
          </Alert>
        )}

        <form onSubmit={handleSubmit(onSubmit)}>
          <Stack gap="md">
            <TextInput
              label={t("login.emailOrPhoneLabel", "Email or phone")}
              placeholder={t("login.emailOrPhonePlaceholder", "you@example.com")}
              size="md"
              leftSection={<IconMail size={18} />}
              error={errors.email?.message}
              {...register("email")}
            />
            <PasswordInput
              label={t("login.passwordLabel", "Password")}
              placeholder={t("login.passwordPlaceholder", "Your password")}
              size="md"
              leftSection={<IconLock size={18} />}
              error={errors.password?.message}
              {...register("password")}
            />

            <Group justify="space-between">
              <Checkbox
                label={t("login.rememberMe", "Remember me")}
                size="sm"
                checked={rememberMe}
                onChange={(e) => setRememberMe(e.currentTarget.checked)}
              />
              {enableForgotPassword && (
                <Anchor
                  component={Link}
                  to="/forgot-password"
                  size="sm"
                  fw={600}
                >
                  {t("login.forgotPassword", "Forgot password?")}
                </Anchor>
              )}
            </Group>

            <Button
              type="submit"
              loading={isLoading}
              fullWidth
              size="md"
              rightSection={<IconArrowRight size={18} />}
            >
              {t("login.signIn", "Sign in")}
            </Button>
          </Stack>
        </form>
        {enableSignup && (
          <Text ta="center" size="sm" c="dimmed">
            {t("login.noAccount", "Don't have an account? ")}
            <Anchor component={Link} to="/signup" fw={700}>
              {t("login.createOne", "Create one")}
            </Anchor>
          </Text>
        )}
      </Stack>
    </AuthShell>
  );
}
