import { useEffect, useState } from "react";
import { X } from "lucide-react";
import { useCategories } from "../hooks/useCategories";
import {
  useCreateTransaction,
  useUpdateTransaction,
} from "../hooks/useTransactions";
import { eurosToCents, centsToEuros } from "../utils/format";
import { useToast } from "../context/ToastContext";
import type { Transaction, TransactionType } from "../api/types";

interface Props {
  isOpen: boolean;
  onClose: () => void;
  transaction?: Transaction;
}

interface FormState {
  amount: string;
  type: TransactionType;
  category_id: string;
  description: string;
  transaction_date: string;
}

function todayISO(): string {
  return new Date().toISOString().slice(0, 10);
}

const DEFAULT_FORM: FormState = {
  amount: "",
  type: "expense",
  category_id: "",
  description: "",
  transaction_date: todayISO(),
};

export default function TransactionForm({ isOpen, onClose, transaction }: Props) {
  const { data: categories = [] } = useCategories();
  const createMutation = useCreateTransaction();
  const updateMutation = useUpdateTransaction();
  const { addToast } = useToast();

  const [form, setForm] = useState<FormState>(DEFAULT_FORM);
  const [errors, setErrors] = useState<Partial<Record<keyof FormState, string>>>({});

  const isEditing = !!transaction;
  const isPending = createMutation.isPending || updateMutation.isPending;

  // Populate form when editing
  useEffect(() => {
    if (transaction) {
      setForm({
        amount: String(centsToEuros(transaction.amount_cents)),
        type: transaction.type,
        category_id: transaction.category.id,
        description: transaction.description ?? "",
        transaction_date: transaction.transaction_date,
      });
    } else {
      setForm(DEFAULT_FORM);
    }
    setErrors({});
  }, [transaction, isOpen]);

  const filteredCategories = categories.filter(
    (c) => c.type === form.type || c.type === "both",
  );

  function set<K extends keyof FormState>(key: K, value: FormState[K]) {
    setForm((prev) => {
      const next = { ...prev, [key]: value };
      // Reset category when type changes and current category is incompatible
      if (key === "type") {
        const cat = categories.find((c) => c.id === prev.category_id);
        if (cat && cat.type !== "both" && cat.type !== value) {
          next.category_id = "";
        }
      }
      return next;
    });
    if (errors[key]) setErrors((e) => ({ ...e, [key]: undefined }));
  }

  function validate(): boolean {
    const errs: Partial<Record<keyof FormState, string>> = {};
    const amountNum = parseFloat(form.amount);
    if (!form.amount || isNaN(amountNum) || amountNum <= 0)
      errs.amount = "Montant invalide (doit être > 0)";
    if (!form.category_id) errs.category_id = "Catégorie requise";
    if (!form.transaction_date) errs.transaction_date = "Date requise";
    setErrors(errs);
    return Object.keys(errs).length === 0;
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!validate()) return;

    const payload = {
      amount_cents: eurosToCents(parseFloat(form.amount)),
      type: form.type,
      category_id: form.category_id,
      description: form.description || undefined,
      transaction_date: form.transaction_date,
    };

    if (isEditing && transaction) {
      updateMutation.mutate(
        { id: transaction.id, payload },
        {
          onSuccess: () => {
            addToast({ type: "success", message: "Transaction modifiée" });
            onClose();
          },
          onError: () =>
            addToast({ type: "error", message: "Erreur lors de la modification" }),
        },
      );
    } else {
      createMutation.mutate(payload, {
        onSuccess: () => {
          addToast({ type: "success", message: "Transaction ajoutée" });
          onClose();
        },
        onError: () =>
          addToast({ type: "error", message: "Erreur lors de l'ajout" }),
      });
    }
  }

  if (!isOpen) return null;

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
      onClick={onClose}
    >
      <div
        className="w-full max-w-md rounded-xl bg-white shadow-xl"
        onClick={(e) => e.stopPropagation()}
      >
        {/* Header */}
        <div className="flex items-center justify-between border-b px-5 py-4">
          <h2 className="text-base font-semibold text-slate-800">
            {isEditing ? "Modifier la transaction" : "Nouvelle transaction"}
          </h2>
          <button
            onClick={onClose}
            className="text-slate-400 hover:text-slate-700"
            aria-label="Fermer"
          >
            <X size={18} />
          </button>
        </div>

        <form onSubmit={handleSubmit} className="space-y-4 p-5">
          {/* Type toggle */}
          <div>
            <label className="mb-1.5 block text-sm font-medium text-slate-700">
              Type
            </label>
            <div className="flex rounded-lg border border-slate-200 p-1">
              {(["expense", "income"] as TransactionType[]).map((t) => (
                <button
                  key={t}
                  type="button"
                  onClick={() => set("type", t)}
                  className={`flex-1 rounded-md py-1.5 text-sm font-medium transition-colors ${
                    form.type === t
                      ? t === "expense"
                        ? "bg-red-100 text-red-700"
                        : "bg-green-100 text-green-700"
                      : "text-slate-500 hover:text-slate-700"
                  }`}
                >
                  {t === "expense" ? "Dépense" : "Revenu"}
                </button>
              ))}
            </div>
          </div>

          {/* Amount */}
          <div>
            <label
              htmlFor="tx-amount"
              className="mb-1.5 block text-sm font-medium text-slate-700"
            >
              Montant (€)
            </label>
            <input
              id="tx-amount"
              type="number"
              step="0.01"
              min="0.01"
              value={form.amount}
              onChange={(e) => set("amount", e.target.value)}
              placeholder="0,00"
              className={`w-full rounded-lg border px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30 ${
                errors.amount ? "border-red-400" : "border-slate-200"
              }`}
            />
            {errors.amount && (
              <p className="mt-1 text-xs text-red-500">{errors.amount}</p>
            )}
          </div>

          {/* Date */}
          <div>
            <label
              htmlFor="tx-date"
              className="mb-1.5 block text-sm font-medium text-slate-700"
            >
              Date
            </label>
            <input
              id="tx-date"
              type="date"
              value={form.transaction_date}
              onChange={(e) => set("transaction_date", e.target.value)}
              className={`w-full rounded-lg border px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30 ${
                errors.transaction_date ? "border-red-400" : "border-slate-200"
              }`}
            />
            {errors.transaction_date && (
              <p className="mt-1 text-xs text-red-500">{errors.transaction_date}</p>
            )}
          </div>

          {/* Category */}
          <div>
            <label
              htmlFor="tx-category"
              className="mb-1.5 block text-sm font-medium text-slate-700"
            >
              Catégorie
            </label>
            <select
              id="tx-category"
              value={form.category_id}
              onChange={(e) => set("category_id", e.target.value)}
              className={`w-full rounded-lg border px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30 ${
                errors.category_id ? "border-red-400" : "border-slate-200"
              }`}
            >
              <option value="">— Choisir une catégorie —</option>
              {filteredCategories.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </select>
            {errors.category_id && (
              <p className="mt-1 text-xs text-red-500">{errors.category_id}</p>
            )}
          </div>

          {/* Description */}
          <div>
            <label
              htmlFor="tx-description"
              className="mb-1.5 block text-sm font-medium text-slate-700"
            >
              Description{" "}
              <span className="font-normal text-slate-400">(optionnel)</span>
            </label>
            <input
              id="tx-description"
              type="text"
              value={form.description}
              onChange={(e) => set("description", e.target.value)}
              placeholder="Ex. : Courses Carrefour"
              className="w-full rounded-lg border border-slate-200 px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"
            />
          </div>

          {/* Actions */}
          <div className="flex justify-end gap-3 pt-2">
            <button
              type="button"
              onClick={onClose}
              className="rounded-lg border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50"
            >
              Annuler
            </button>
            <button
              type="submit"
              disabled={isPending}
              className="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white hover:bg-primary/90 disabled:opacity-50"
            >
              {isPending
                ? "Enregistrement…"
                : isEditing
                  ? "Modifier"
                  : "Ajouter"}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}
