import { useActionMutation } from "@agent-native/core/client/hooks";
import { useT } from "@agent-native/core/client/i18n";
import { zodResolver } from "@hookform/resolvers/zod";
import type { Meal } from "@shared/types";
import { IconPlus, IconChevronDown } from "@tabler/icons-react";
import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { formatLocalDate } from "@/lib/utils";

const formSchema = z.object({
  name: z.string().min(1, "Name is required"),
  calories: z.string().transform((val) => parseInt(val, 10)),
  protein: z
    .string()
    .optional()
    .transform((val) => (val ? parseInt(val, 10) : 0)),
  carbs: z
    .string()
    .optional()
    .transform((val) => (val ? parseInt(val, 10) : 0)),
  fat: z
    .string()
    .optional()
    .transform((val) => (val ? parseInt(val, 10) : 0)),
  date: z.string(),
  notes: z.string().optional(),
});

type FormData = z.input<typeof formSchema>;

interface AddMealDialogProps {
  editingMeal?: Meal | null;
  onOpenChange?: (open: boolean) => void;
  isOpen?: boolean;
  currentDate?: Date;
}

export function AddMealDialog({
  editingMeal,
  onOpenChange,
  isOpen: controlledOpen,
  currentDate = new Date(),
}: AddMealDialogProps) {
  const t = useT();
  const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
  const open = controlledOpen !== undefined ? controlledOpen : uncontrolledOpen;
  const setOpen =
    controlledOpen !== undefined
      ? (v: boolean) => onOpenChange?.(v)
      : setUncontrolledOpen;
  const [showMacros, setShowMacros] = useState(false);
  const isEditing = !!editingMeal;

  const form = useForm<FormData>({
    // zod resolves at multiple minor versions across the workspace; cast the
    // schema so @hookform/resolvers v5's zod-v4 overload doesn't reject a
    // v4.3-internal schema under CI's frozen lockfile. Runtime is unaffected.
    resolver: zodResolver(formSchema as any) as any,
    defaultValues: {
      name: editingMeal?.name || "",
      calories: editingMeal?.calories.toString() || "",
      protein: editingMeal?.protein?.toString() || "",
      carbs: editingMeal?.carbs?.toString() || "",
      fat: editingMeal?.fat?.toString() || "",
      date: editingMeal?.date || formatLocalDate(currentDate),
      notes: editingMeal?.notes || "",
    },
  });

  const createMutation = useActionMutation("log-meal", {
    onSuccess: () => {
      toast.success(t("meals.added"));
      setOpen(false);
      form.reset();
      setShowMacros(false);
    },
    onError: () => toast.error(t("meals.addFailed")),
  });

  const updateMutation = useActionMutation("update-meal", {
    onSuccess: () => {
      toast.success(t("meals.updated"));
      setOpen(false);
      form.reset();
      setShowMacros(false);
    },
    onError: () => toast.error(t("meals.updateFailed")),
  });

  const onSubmit = (data: FormData) => {
    const date = isEditing ? editingMeal!.date : formatLocalDate(currentDate);
    if (isEditing) {
      updateMutation.mutate({
        id: String(editingMeal!.id),
        name: data.name,
        calories: String(data.calories),
        protein: data.protein ? String(data.protein) : undefined,
        carbs: data.carbs ? String(data.carbs) : undefined,
        fat: data.fat ? String(data.fat) : undefined,
        date,
      });
    } else {
      createMutation.mutate({
        name: data.name,
        calories: String(data.calories),
        protein: data.protein ? String(data.protein) : undefined,
        carbs: data.carbs ? String(data.carbs) : undefined,
        fat: data.fat ? String(data.fat) : undefined,
        date,
      });
    }
  };

  const handleOpenChange = (newOpen: boolean) => {
    setOpen(newOpen);
    onOpenChange?.(newOpen);
    if (!newOpen) {
      form.reset();
      setShowMacros(false);
    }
  };

  useEffect(() => {
    if (editingMeal) {
      form.reset({
        name: editingMeal.name,
        calories: editingMeal.calories.toString(),
        protein: editingMeal.protein?.toString() || "",
        carbs: editingMeal.carbs?.toString() || "",
        fat: editingMeal.fat?.toString() || "",
        date: editingMeal.date,
        notes: editingMeal.notes || "",
      });
      setShowMacros(
        (editingMeal.protein ?? 0) > 0 ||
          (editingMeal.carbs ?? 0) > 0 ||
          (editingMeal.fat ?? 0) > 0,
      );
    }
  }, [editingMeal, form]);

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      {!isEditing && (
        <DialogTrigger asChild>
          <Button size="sm" className="gap-1.5 h-8 rounded-md shadow-sm">
            <IconPlus className="h-3.5 w-3.5" /> {t("meals.add")}
          </Button>
        </DialogTrigger>
      )}
      <DialogContent className="sm:max-w-[425px] gap-6">
        <DialogHeader>
          <DialogTitle>
            {isEditing ? t("meals.edit") : t("meals.addNew")}
          </DialogTitle>
          <DialogDescription className="sr-only">
            {isEditing
              ? t("meals.updateDescription")
              : t("meals.logDescription")}
          </DialogDescription>
        </DialogHeader>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="name">{t("meals.nameLabel")}</Label>
            <Input
              id="name"
              {...form.register("name")}
              placeholder={t("meals.namePlaceholder")}
              autoFocus
              autoComplete="off"
            />
            {form.formState.errors.name && (
              <p className="text-sm text-destructive">
                {form.formState.errors.name.message}
              </p>
            )}
          </div>
          <div className="space-y-2">
            <Label htmlFor="calories">Calories</Label>
            <Input
              id="calories"
              type="number"
              inputMode="numeric"
              {...form.register("calories")}
              placeholder="kcal"
            />
            {form.formState.errors.calories && (
              <p className="text-sm text-destructive">
                {form.formState.errors.calories.message}
              </p>
            )}
          </div>
          <button
            type="button"
            onClick={() => setShowMacros(!showMacros)}
            className="flex items-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
          >
            <IconChevronDown
              className={`h-4 w-4 transition-transform ${showMacros ? "rotate-180" : ""}`}
            />
            {t("meals.addNutritionDetails")}
          </button>
          {showMacros && (
            <div className="pt-2 border-t space-y-4 bg-secondary/30 -mx-6 px-6 py-4 rounded">
              <p className="text-xs font-medium text-muted-foreground">
                {t("common.optional")}
              </p>
              <div className="grid grid-cols-3 gap-3">
                <div className="space-y-2">
                  <Label htmlFor="protein">{t("meals.proteinGrams")}</Label>
                  <Input
                    id="protein"
                    type="number"
                    inputMode="numeric"
                    {...form.register("protein")}
                    placeholder="0"
                  />
                </div>
                <div className="space-y-2">
                  <Label htmlFor="carbs">{t("meals.carbsGrams")}</Label>
                  <Input
                    id="carbs"
                    type="number"
                    inputMode="numeric"
                    {...form.register("carbs")}
                    placeholder="0"
                  />
                </div>
                <div className="space-y-2">
                  <Label htmlFor="fat">{t("meals.fatGrams")}</Label>
                  <Input
                    id="fat"
                    type="number"
                    inputMode="numeric"
                    {...form.register("fat")}
                    placeholder="0"
                  />
                </div>
              </div>
            </div>
          )}
          <Button
            type="submit"
            className="w-full"
            disabled={createMutation.isPending || updateMutation.isPending}
          >
            {createMutation.isPending || updateMutation.isPending
              ? t("common.saving")
              : isEditing
                ? t("common.saveChanges")
                : t("meals.save")}
          </Button>
        </form>
      </DialogContent>
    </Dialog>
  );
}
