import { useEffect } from "react";
import { useForm } from "@tanstack/react-form";
import { useMutation } from "@tanstack/react-query";
import { toast } from "sonner";
import { z } from "zod";

import type { User } from "@rubis/shared";
import { api } from "@/lib/api";
import { authStore, useAuth } from "@/lib/auth";

import { Button } from "@/components/ui/Button";
import { Field } from "@/components/ui/Field";
import { Input } from "@/components/ui/Input";

/**
 * Form section "Compte" — fullName + email.
 * La signature email est dans son propre form (SignatureForm) pour clarté.
 */

type FormValues = {
  fullName: string;
  email: string;
};

const validators = {
  fullName: z.string().min(2, "Au moins 2 caractères").max(120),
  email: z.string().min(1, "Email requis").email("Format d'email invalide"),
};

export function AccountForm() {
  const { user } = useAuth();

  const updateMutation = useMutation({
    mutationFn: (input: FormValues) =>
      api.patch<User>("/api/v1/account/profile", input),
    onSuccess: (updated) => {
      // Synchronise authStore — sinon le topbar / sidebar continuent d'afficher
      // l'ancien fullName.
      const token = authStore.token;
      if (token) authStore.setSession(token, updated);
      toast.success("Compte mis à jour.");
    },
    onError: () => {
      toast.error("Sauvegarde impossible. Réessayez.");
    },
  });

  const initialValues: FormValues = {
    fullName: user?.fullName ?? "",
    email: user?.email ?? "",
  };

  const form = useForm({
    defaultValues: initialValues,
    onSubmit: async ({ value }) => {
      for (const [_, schema, val] of [
        ["fullName", validators.fullName, value.fullName],
        ["email", validators.email, value.email],
      ] as const) {
        const r = schema.safeParse(val);
        if (!r.success) {
          toast.error(r.error.issues[0]?.message ?? "Champ invalide");
          return;
        }
      }
      await updateMutation.mutateAsync(value);
    },
  });

  // Re-sync quand l'user change (rare en pratique mais cohérent)
  useEffect(() => {
    form.reset(initialValues);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user?.id]);

  return (
    <form
      noValidate
      onSubmit={(e) => {
        e.preventDefault();
        void form.handleSubmit();
      }}
      className="flex flex-col gap-5"
    >
      <form.Field name="fullName" validators={{ onChange: validators.fullName }}>
        {(field) => (
          <Field
            label="Prénom et nom"
            htmlFor={field.name}
            error={firstError(field.state.meta.errors)}
          >
            <Input
              id={field.name}
              autoComplete="name"
              value={field.state.value}
              onChange={(e) => field.handleChange(e.target.value)}
            />
          </Field>
        )}
      </form.Field>

      <form.Field name="email" validators={{ onChange: validators.email }}>
        {(field) => (
          <Field
            label="Email"
            htmlFor={field.name}
            hint="Sert d'identifiant de connexion et d'expéditeur des relances."
            error={firstError(field.state.meta.errors)}
          >
            <Input
              id={field.name}
              type="email"
              autoComplete="email"
              value={field.state.value}
              onChange={(e) => field.handleChange(e.target.value)}
            />
          </Field>
        )}
      </form.Field>

      <div className="flex justify-end">
        <Button
          type="submit"
          size="sm"
          loading={updateMutation.isPending}
          disabled={!form.state.isDirty}
        >
          {form.state.isDirty ? "Enregistrer" : "Aucune modification"}
        </Button>
      </div>
    </form>
  );
}

function firstError(errors: unknown[]): string | undefined {
  const first = errors[0];
  if (!first) return undefined;
  if (typeof first === "string") return first;
  if (typeof first === "object" && first !== null && "message" in first) {
    const msg = (first as { message?: unknown }).message;
    if (typeof msg === "string") return msg;
  }
  return undefined;
}
