"use client";

import * as React from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { CurrencyInput } from "@/components/ui/currency-input";
import { FormField } from "@/components/ui/form-field";
import { Input } from "@/components/ui/input";
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group";
import { TagInput } from "@/components/ui/tag-input";
import { Textarea } from "@/components/ui/textarea";
import { useCreatePackage } from "@/hooks/catalog/useCreatePackage";
import { useUpdatePackage } from "@/hooks/catalog/useUpdatePackage";
import { useTranslation } from "@/hooks/useTranslation";
import {
  washPackageSchema,
  type WashPackageFormValues,
} from "@/lib/validations/catalog.schema";
import type { CreateWashPackageRequest, WashPackage } from "@/types/catalog";

import { PackageIconPicker } from "./PackageIconPicker";

const EMPTY_FORM: WashPackageFormValues = {
  name: "",
  description: "",
  estimatedDuration: "60",
  features: [],
  icon: "",
  minPrice: "",
  maxPrice: "",
};

function toFormValues(pkg: WashPackage | null): WashPackageFormValues {
  if (!pkg) return EMPTY_FORM;
  return {
    name: pkg.name,
    description: pkg.description ?? "",
    estimatedDuration: String(pkg.estimatedDuration),
    features: pkg.features,
    icon: pkg.icon ?? "",
    minPrice: String(pkg.minPrice),
    maxPrice: String(pkg.maxPrice),
  };
}

interface WashPackageFormDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** The package being edited, or null to create a new one */
  editing: WashPackage | null;
}

/**
 * Create/edit form for one admin catalog package.
 *
 * One dialog covers both modes — the fields, validation, and copy are
 * identical, only the endpoint differs. Edit sends every field rather than a
 * diff: `UpdateWashPackageDto` accepts them all, and a full payload keeps the
 * submitted state and the stored state impossible to drift apart.
 *
 * `isActive` is deliberately absent: the backend's update DTO doesn't declare
 * it (and rejects unknown keys), so there is no way to change it here.
 */
export function WashPackageFormDialog({
  open,
  onOpenChange,
  editing,
}: WashPackageFormDialogProps) {
  const { t } = useTranslation();

  const form = useForm<WashPackageFormValues>({
    resolver: zodResolver(washPackageSchema),
    defaultValues: toFormValues(editing),
  });

  const close = () => onOpenChange(false);
  const createPackage = useCreatePackage({ onSuccess: close });
  const updatePackage = useUpdatePackage({ onSuccess: close });
  const isPending = createPackage.isPending || updatePackage.isPending;

  // Re-seed on every open — the same dialog instance serves "new package" and
  // whichever row was picked, and the stored values may have changed since it
  // first mounted.
  React.useEffect(() => {
    if (open) form.reset(toFormValues(editing));
  }, [open, editing, form]);

  function onSubmit(values: WashPackageFormValues) {
    // description/icon are optional backend-side — omit them rather than
    // storing an empty string when the admin left them blank.
    const payload: CreateWashPackageRequest = {
      name: values.name.trim(),
      estimatedDuration: Number(values.estimatedDuration),
      features: values.features,
      minPrice: Number(values.minPrice),
      maxPrice: Number(values.maxPrice),
      ...(values.description.trim()
        ? { description: values.description.trim() }
        : {}),
      ...(values.icon ? { icon: values.icon } : {}),
    };

    if (editing) updatePackage.mutate({ packageId: editing.id, ...payload });
    else createPackage.mutate(payload);
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>
            {editing ? t("catalog.form.editTitle") : t("catalog.form.newTitle")}
          </DialogTitle>
          <DialogDescription>{t("catalog.form.description")}</DialogDescription>
        </DialogHeader>

        {/* The form wraps both the fields and the footer (the submit button has
            to be inside it), so it — not DialogContent — is the flex child that
            has to pass the height down. `min-h-0 flex-1` keeps that chain
            unbroken so DialogBody can actually scroll. */}
        <form
          className="flex min-h-0 flex-1 flex-col gap-5"
          onSubmit={form.handleSubmit(onSubmit)}
        >
          <DialogBody className="flex flex-col gap-5">
            <FormField
              control={form.control}
              name="name"
              label={t("catalog.form.name")}
              description={t("catalog.form.nameHint")}
              render={({ field, hasError, id }) => (
                <Input
                  id={id}
                  placeholder={t("catalog.form.namePlaceholder")}
                  aria-invalid={hasError}
                  {...field}
                />
              )}
            />

            <FormField
              control={form.control}
              name="description"
              label={t("catalog.form.descriptionLabel")}
              render={({ field, hasError, id }) => (
                <Textarea
                  id={id}
                  placeholder={t("catalog.form.descriptionPlaceholder")}
                  aria-invalid={hasError}
                  {...field}
                />
              )}
            />

            <FormField
              control={form.control}
              name="estimatedDuration"
              label={t("catalog.form.duration")}
              render={({ field, hasError, id }) => (
                <InputGroup dir="ltr">
                  <InputGroupInput
                    id={id}
                    inputMode="numeric"
                    className="font-numeric"
                    aria-invalid={hasError}
                    {...field}
                  />
                  <InputGroupAddon align="inline-end">
                    <InputGroupText className="text-main-text">
                      {t("catalog.form.durationUnit")}
                    </InputGroupText>
                  </InputGroupAddon>
                </InputGroup>
              )}
            />

            {/* The range every provider must price inside — the core of the
              admin-owned-pricing model, so the two bounds sit together. */}
            <div className="grid gap-5 sm:grid-cols-2">
              <FormField
                control={form.control}
                name="minPrice"
                label={t("catalog.form.minPrice")}
                render={({ field, hasError, id }) => (
                  <CurrencyInput
                    id={id}
                    placeholder="0"
                    aria-invalid={hasError}
                    value={field.value}
                    onChange={field.onChange}
                    onBlur={field.onBlur}
                    name={field.name}
                  />
                )}
              />
              <FormField
                control={form.control}
                name="maxPrice"
                label={t("catalog.form.maxPrice")}
                render={({ field, hasError, id }) => (
                  <CurrencyInput
                    id={id}
                    placeholder="0"
                    aria-invalid={hasError}
                    value={field.value}
                    onChange={field.onChange}
                    onBlur={field.onBlur}
                    name={field.name}
                  />
                )}
              />
            </div>

            <FormField
              control={form.control}
              name="features"
              label={t("catalog.form.features")}
              description={t("catalog.form.featuresHint")}
              render={({ field, hasError, id }) => (
                <TagInput
                  id={id}
                  placeholder={t("catalog.form.featuresPlaceholder")}
                  aria-invalid={hasError}
                  value={field.value}
                  onChange={field.onChange}
                  onBlur={field.onBlur}
                  name={field.name}
                />
              )}
            />

            <FormField
              control={form.control}
              name="icon"
              label={t("catalog.form.icon")}
              description={t("catalog.form.iconHint")}
              render={({ field, id }) => (
                <PackageIconPicker
                  id={id}
                  value={field.value}
                  onChange={field.onChange}
                />
              )}
            />
          </DialogBody>

          <DialogFooter>
            <Button type="button" variant="secondary" onClick={close}>
              {t("common.cancel")}
            </Button>
            <Button type="submit" loading={isPending}>
              {editing ? t("common.save") : t("catalog.form.create")}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
