"use client";

import { useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { Alert } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { FormField } from "@/components/ui/form-field";
import { Input } from "@/components/ui/input";
import { AuthCard } from "@/features/auth/auth-card";
import { usePortalSession } from "@/features/portal/portal-session";
import { useT } from "@/i18n";
import { applyFieldErrors, friendlyErrorMessage } from "@/lib/errors";
import { isApiError } from "@/services/http";
import { loginStoreUser } from "@/services/portal";

const formSchema = z.object({
  email: z.string().email("errors.email"),
  password: z.string().min(1, "errors.required"),
});

type FormValues = z.infer<typeof formSchema>;

export default function PortalLoginPage() {
  const t = useT();
  const router = useRouter();
  const { signIn } = usePortalSession();
  const [serverError, setServerError] = useState<string | null>(null);

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    mode: "onTouched",
    defaultValues: { email: "", password: "" },
  });

  async function onSubmit(values: FormValues) {
    setServerError(null);
    try {
      const response = await loginStoreUser(values);
      if (!response.Model) {
        setServerError(t("errors.generic"));
        return;
      }
      signIn(response.Model.user, response.Model.token);

      /*
       * A store that has applied but not been approved can sign in — that is deliberate, so
       * they can set their integration up while they wait. But signing in and landing on a
       * portal where half the sections refuse to open reads as a broken account, so say the
       * quiet part at the moment it is least ambiguous: as they come through the door.
       *
       * The home screen carries the same status, at length and with the reviewer's note. This
       * is the glance; that is the explanation.
       */
      if (response.Model.user.store?.status === "pending") {
        toast.info(t("portal.status.pending.title"), {
          description: t("portal.status.pending.body"),
        });
      }

      router.replace("/portal");
    } catch (error) {
      // A wrong password is a 401 with a message worth showing as it is; a closed store is a 403.
      if (isApiError(error) && (error.status === 401 || error.status === 403)) {
        setServerError(error.message.startsWith("errors.") ? friendlyErrorMessage(error, t) : error.message);
        return;
      }
      const shown = applyFieldErrors(error, (field, message) => form.setError(field as keyof FormValues, { message }), {
        only: ["email", "password"],
      });
      if (shown === 0) setServerError(friendlyErrorMessage(error, t));
    }
  }

  return (
    <AuthCard
      title={t("portal.login.title")}
      subtitle={t("portal.login.subtitle")}
      footer={
        <p className="text-xs text-muted-foreground">
          {t("portal.login.noAccount")}{" "}
          <Link href="/portal/register" className="font-medium text-primary underline-offset-4 hover:underline">
            {t("portal.login.register")}
          </Link>
        </p>
      }
    >
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4" noValidate>
        {serverError ? <Alert variant="destructive" title={serverError} /> : null}
        <FormField label={t("auth.email")} htmlFor="email" error={form.formState.errors.email?.message}>
          <Input id="email" type="email" autoComplete="email" {...form.register("email")} />
        </FormField>
        <FormField label={t("auth.password")} htmlFor="password" error={form.formState.errors.password?.message}>
          <Input id="password" type="password" autoComplete="current-password" {...form.register("password")} />
        </FormField>
        <Button type="submit" className="w-full" size="lg" loading={form.formState.isSubmitting}>
          {t("auth.signIn")}
        </Button>
      </form>
    </AuthCard>
  );
}
