import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useForm } from "@tanstack/react-form";
import { useMutation } from "@tanstack/react-query";
import { ArrowLeft, ArrowRight } from "lucide-react";
import { toast } from "sonner";
import { z } from "zod";

import { MONTHLY_VOLUME_BUCKETS, type Organization } from "@rubis/shared";
import { api } from "@/lib/api";
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { Field } from "@/components/ui/Field";
import { Chip } from "@/components/ui/Chip";
import { Eyebrow } from "@/components/ui/Eyebrow";

const VOLUME_LABELS: Record<(typeof MONTHLY_VOLUME_BUCKETS)[number], string> = {
  "moins-10": "Moins de 10",
  "10-50": "10 à 50",
  "50-100": "50 à 100",
  "100-200": "100 à 200",
  "plus-200": "Plus de 200",
};

const entrepriseSchema = z.object({
  name: z
    .string({ required_error: "Nom de l'entreprise requis" })
    .min(2, "Au moins 2 caractères")
    .max(120),
  // Soit 14 chiffres, soit chaîne vide (= pas renseigné). Pas d'undefined :
  // TanStack Form impose un type input strict aligné sur les defaultValues.
  siret: z
    .string()
    .regex(/^\d{14}$/u, "14 chiffres exactement")
    .or(z.literal("")),
  monthlyVolumeBucket: z.enum(MONTHLY_VOLUME_BUCKETS, {
    required_error: "Sélectionnez un volume",
  }),
});

type EntrepriseInput = z.infer<typeof entrepriseSchema>;

export const Route = createFileRoute("/onboarding/entreprise")({
  component: OnboardingEntreprise,
});

function OnboardingEntreprise() {
  const navigate = useNavigate();

  const updateOrg = useMutation({
    mutationFn: async (input: EntrepriseInput) =>
      api.patch<Organization>("/api/v1/organizations/me", input),
    onSuccess: () => {
      void navigate({ to: "/onboarding/signature" });
    },
    onError: () => {
      toast.error("On n'a pas pu enregistrer. Réessayez dans un instant.");
    },
  });

  const form = useForm({
    defaultValues: {
      name: "",
      siret: "",
      monthlyVolumeBucket: "10-50" as EntrepriseInput["monthlyVolumeBucket"],
    } satisfies EntrepriseInput,
    validators: { onChange: entrepriseSchema },
    onSubmit: async ({ value }) => {
      await updateOrg.mutateAsync(value);
    },
  });

  return (
    <div>
      <Eyebrow>Étape 2</Eyebrow>
      <h1 className="mt-3 font-display text-[34px] font-bold leading-[1.1] tracking-[-0.022em] text-ink">
        Votre <em>entreprise</em>.
      </h1>
      <p className="mt-3 max-w-md text-[15px] leading-relaxed text-ink-2">
        Le nom apparaîtra dans les emails de relance. Le SIRET est optionnel
        mais nécessaire pour les mises en demeure formelles.
      </p>

      <form
        noValidate
        onSubmit={(e) => {
          e.preventDefault();
          void form.handleSubmit();
        }}
        className="mt-10 flex flex-col gap-6"
      >
        <form.Field name="name">
          {(field) => (
            <Field
              label="Nom de l'entreprise"
              htmlFor={field.name}
              error={field.state.meta.errors[0]?.message}
            >
              <Input
                id={field.name}
                name={field.name}
                type="text"
                autoFocus
                placeholder="Boulangerie Dupont SARL"
                value={field.state.value}
                onBlur={field.handleBlur}
                onChange={(e) => field.handleChange(e.target.value)}
                aria-invalid={field.state.meta.errors.length > 0}
              />
            </Field>
          )}
        </form.Field>

        <form.Field name="siret">
          {(field) => (
            <Field
              label="SIRET (optionnel)"
              htmlFor={field.name}
              hint="14 chiffres. Vous pouvez le compléter plus tard."
              error={field.state.meta.errors[0]?.message}
            >
              <Input
                id={field.name}
                name={field.name}
                type="text"
                inputMode="numeric"
                autoComplete="off"
                placeholder="123 456 789 00012"
                value={field.state.value ?? ""}
                onBlur={field.handleBlur}
                onChange={(e) => field.handleChange(e.target.value.replace(/\s/gu, ""))}
                aria-invalid={field.state.meta.errors.length > 0}
              />
            </Field>
          )}
        </form.Field>

        <form.Field name="monthlyVolumeBucket">
          {(field) => (
            <fieldset>
              <legend className="font-sans text-[13px] font-semibold text-ink mb-2">
                Combien de factures émettez-vous par mois ?
              </legend>
              <p className="text-[12.5px] text-ink-3 leading-snug mb-3">
                Sert juste à proposer le bon plan tarifaire par défaut.
                Modifiable n&apos;importe quand.
              </p>
              <div className="flex flex-wrap gap-2">
                {MONTHLY_VOLUME_BUCKETS.map((bucket) => (
                  <Chip
                    key={bucket}
                    selected={field.state.value === bucket}
                    onClick={() => field.handleChange(bucket)}
                  >
                    {VOLUME_LABELS[bucket]}
                  </Chip>
                ))}
              </div>
            </fieldset>
          )}
        </form.Field>

        <div className="mt-3 flex items-center justify-between">
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={() => navigate({ to: "/onboarding/compte" })}
          >
            <ArrowLeft size={15} aria-hidden="true" /> Retour
          </Button>
          <Button type="submit" loading={updateOrg.isPending}>
            Continuer <ArrowRight size={16} aria-hidden="true" />
          </Button>
        </div>
      </form>
    </div>
  );
}
