import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useMemo, useRef } from "react";
import { Controller, useForm, useWatch } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import { DatePicker } from "@/components/ui/date-picker";
import {
  ResponsiveDialog,
  ResponsiveDialogContent,
  ResponsiveDialogFooter,
  ResponsiveDialogHeader,
  ResponsiveDialogTitle,
} from "@/components/ui/responsive-dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import type { Expense } from "@/lib/api";
import { useExpensesContext } from "../ExpensesProvider";
import { useQuotes, useWallets } from "@/lib/queries";

const paySchema = z.object({
  amountPayed: z.number().positive("El monto debe ser mayor a 0"),
  paymentDate: z.date({ message: "La fecha es obligatoria" }),
  walletId: z
    .number()
    .positive("Seleccioná una billetera")
    .refine((v) => v > 0, "Seleccioná una billetera"),
  usdcConversionRate: z
    .number()
    .positive("La cotización debe ser mayor a 0")
    .optional(),
});

type PayFormValues = z.infer<typeof paySchema>;

interface PayExpenseDialogProps {
  expense: Expense | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}

export function PayExpenseDialog({
  expense,
  open,
  onOpenChange,
}: PayExpenseDialogProps) {
  const { payExpense } = useExpensesContext();
  const amountInputRef = useRef<HTMLInputElement | null>(null);
  const prevWalletRef = useRef(0);
  const { data: wallets } = useWallets();
  const { data: quotes } = useQuotes();
  const defaultWallet = useMemo(
    () => wallets?.find((w) => w.isDefault),
    [wallets],
  );

  const beloSell = useMemo(() => {
    if (!quotes) return null;
    const belo = quotes.find((q) => q.type === "BELO");
    return belo ? Number(belo.sell) : null;
  }, [quotes]);

  const {
    register,
    handleSubmit,
    control,
    formState: { errors, isSubmitting },
    reset,
    setValue,
    trigger,
  } = useForm<PayFormValues>({
    resolver: zodResolver(paySchema),
    defaultValues: {
      amountPayed: 0,
      paymentDate: undefined,
      walletId: 0,
      usdcConversionRate: undefined,
    },
  });
  const { ref: amountPayedRef, ...amountPayedField } = register("amountPayed", {
    setValueAs: (value) => Number(value),
  });

  const usdcConversionRateField = register("usdcConversionRate", {
    setValueAs: (value) => (value === "" ? undefined : Number(value)),
  });

  const selectedWalletId = useWatch({ control, name: "walletId" });
  const selectedWallet = wallets?.find((w) => w.id === selectedWalletId);
  const isUSDC = selectedWallet?.currency === "USDC";

  useEffect(() => {
    if (expense) {
      const defaultId = defaultWallet?.id ?? 0;
      reset({
        amountPayed: Number(expense.amount),
        paymentDate: new Date(),
        walletId: defaultId,
        usdcConversionRate: undefined,
      });
      prevWalletRef.current = defaultId;
    }
  }, [expense, defaultWallet, reset]);

  useEffect(() => {
    if (
      isUSDC &&
      beloSell &&
      selectedWalletId &&
      selectedWalletId !== prevWalletRef.current
    ) {
      setValue("usdcConversionRate", beloSell);
      trigger("usdcConversionRate");
      prevWalletRef.current = selectedWalletId;
    }
  }, [isUSDC, beloSell, selectedWalletId, setValue, trigger]);

  useEffect(() => {
    if (!open || !expense) return;

    const frame = requestAnimationFrame(() => {
      amountInputRef.current?.focus();
      amountInputRef.current?.select();
    });

    return () => cancelAnimationFrame(frame);
  }, [open, expense]);

  function handleClose(open: boolean) {
    onOpenChange(open);
    if (!open) reset();
  }

  async function onSubmit(data: PayFormValues) {
    if (!expense) return;
    await payExpense(expense.id, {
      amountPayed: data.amountPayed,
      paymentDate: data.paymentDate.toISOString(),
      walletId: data.walletId,
      usdcConversionRate: isUSDC ? data.usdcConversionRate : undefined,
    });
    handleClose(false);
  }

  if (!expense) return null;

  return (
    <ResponsiveDialog open={open} onOpenChange={handleClose}>
      <ResponsiveDialogContent>
        <ResponsiveDialogHeader>
          <ResponsiveDialogTitle>Registrar pago</ResponsiveDialogTitle>
        </ResponsiveDialogHeader>

        <div className="flex flex-col gap-1 rounded-lg bg-muted px-3 py-2 text-sm">
          <span className="font-medium">{expense.description}</span>
          <span className="text-muted-foreground">
            Monto original: $
            {Number(expense.amount).toLocaleString("es-AR", {
              minimumFractionDigits: 2,
            })}
          </span>
        </div>

        <form
          id="pay-form"
          onSubmit={handleSubmit(onSubmit)}
          className="flex flex-col gap-4"
        >
          <div className="flex flex-col gap-1.5">
            <label htmlFor="amountPayed" className="text-sm font-medium">
              Monto pagado
            </label>
            <input
              id="amountPayed"
              type="text"
              inputMode="numeric"
              pattern="[0-9]*"
              {...amountPayedField}
              ref={(node) => {
                amountPayedRef(node);
                amountInputRef.current = node;
              }}
              className="h-8 rounded-lg border border-input bg-background px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
            />
            {errors.amountPayed && (
              <span className="text-xs text-destructive">
                {errors.amountPayed.message}
              </span>
            )}
          </div>

          <div className="flex flex-col gap-1.5">
            <label className="text-sm font-medium">Billetera</label>
            <Controller
              control={control}
              name="walletId"
              render={({ field }) => (
                <Select
                  value={field.value ? String(field.value) : ""}
                  onValueChange={(v) => field.onChange(Number(v))}
                >
                  <SelectTrigger className="h-8 w-full">
                    <SelectValue placeholder="Seleccionar billetera" />
                  </SelectTrigger>
                  <SelectContent>
                    {wallets?.map((w) => (
                      <SelectItem key={w.id} value={String(w.id)}>
                        {w.name} ({w.currency})
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              )}
            />
            {errors.walletId && (
              <span className="text-xs text-destructive">
                {errors.walletId.message}
              </span>
            )}
          </div>

          {isUSDC && (
            <div className="flex flex-col gap-1.5">
              <label
                htmlFor="usdcConversionRate"
                className="text-sm font-medium"
              >
                Cotización USDC (ARS por USDC)
              </label>
              <input
                id="usdcConversionRate"
                type="text"
                inputMode="decimal"
                {...usdcConversionRateField}
                className="h-8 rounded-lg border border-input bg-background px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
              />
              {errors.usdcConversionRate && (
                <span className="text-xs text-destructive">
                  {errors.usdcConversionRate.message}
                </span>
              )}
              <span className="text-xs text-muted-foreground">
                Pre-sugerido: {beloSell ?? "—"} ARS/USDC (BELO)
              </span>
            </div>
          )}

          <div className="flex flex-col gap-1.5">
            <span className="text-sm font-medium">Fecha de pago</span>
            <Controller
              control={control}
              name="paymentDate"
              render={({ field }) => (
                <DatePicker
                  value={field.value}
                  onChange={field.onChange}
                  placeholder="Seleccionar fecha"
                />
              )}
            />
            {errors.paymentDate && (
              <span className="text-xs text-destructive">
                {errors.paymentDate.message}
              </span>
            )}
          </div>
        </form>

        <ResponsiveDialogFooter>
          <Button
            variant="outline"
            onClick={() => handleClose(false)}
            disabled={isSubmitting}
          >
            Cancelar
          </Button>
          <Button type="submit" form="pay-form" disabled={isSubmitting}>
            Confirmar pago
          </Button>
        </ResponsiveDialogFooter>
      </ResponsiveDialogContent>
    </ResponsiveDialog>
  );
}
