"use client";

import { useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Plus, Pencil, Trash2, Search, Lock } from "lucide-react";
import { createClient } from "@/lib/supabase/client";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input, Label, Select, FieldError } from "@/components/ui/input";
import { Modal } from "@/components/ui/modal";
import { Badge } from "@/components/ui/badge";
import { EmptyState } from "@/components/shared/empty-state";
import { expenseSchema, type ExpenseInput } from "@/lib/validation/schemas";
import { useTranslations, useLocale } from "@/lib/i18n/i18n-provider";
import { formatMoney, formatDate } from "@/lib/utils";
import { PLANS, type PlanId } from "@/lib/pricing";
import type { Expense, Currency, PaymentMethod } from "@/types/database";

const CATEGORIES = [
  "food",
  "housing",
  "transport",
  "shopping",
  "entertainment",
  "health",
  "bills",
  "subscriptions",
  "travel",
  "education",
  "other"
] as const;

const PAYMENT_METHODS: PaymentMethod[] = ["card", "cash", "transfer", "blik"];

export function ExpensesView({
  initialExpenses,
  currency,
  plan
}: {
  initialExpenses: Expense[];
  currency: Currency;
  plan: PlanId;
}) {
  const t = useTranslations();
  const locale = useLocale();
  const [expenses, setExpenses] = useState(initialExpenses);
  const [modalOpen, setModalOpen] = useState(false);
  const [editing, setEditing] = useState<Expense | null>(null);
  const [search, setSearch] = useState("");
  const [categoryFilter, setCategoryFilter] = useState<string>("all");
  const [sortDesc, setSortDesc] = useState(true);

  const limit = PLANS[plan].limits.maxExpenses;
  const atLimit = limit !== null && expenses.length >= limit;

  const filtered = useMemo(() => {
    let list = expenses;
    if (categoryFilter !== "all") list = list.filter((e) => e.category === categoryFilter);
    if (search.trim()) {
      const q = search.toLowerCase();
      list = list.filter((e) => (e.description ?? "").toLowerCase().includes(q));
    }
    return [...list].sort((a, b) =>
      sortDesc ? b.occurred_on.localeCompare(a.occurred_on) : a.occurred_on.localeCompare(b.occurred_on)
    );
  }, [expenses, search, categoryFilter, sortDesc]);

  function openCreate() {
    setEditing(null);
    setModalOpen(true);
  }

  function openEdit(expense: Expense) {
    setEditing(expense);
    setModalOpen(true);
  }

  async function handleDelete(id: string) {
    const supabase = createClient();
    const prev = expenses;
    setExpenses((e) => e.filter((x) => x.id !== id));
    const { error } = await supabase.from("expenses").delete().eq("id", id);
    if (error) setExpenses(prev);
  }

  return (
    <div className="space-y-4">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="relative flex-1 sm:max-w-xs">
          <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink-400" />
          <Input
            placeholder={t("expenses.searchPlaceholder")}
            className="pl-9"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <div className="flex items-center gap-2">
          <Select value={categoryFilter} onChange={(e) => setCategoryFilter(e.target.value)} className="w-40">
            <option value="all">{t("common.all")}</option>
            {CATEGORIES.map((c) => (
              <option key={c} value={c}>
                {t(`expenses.categories.${c}`)}
              </option>
            ))}
          </Select>
          <Button variant="secondary" size="sm" onClick={() => setSortDesc((s) => !s)}>
            {sortDesc ? "↓" : "↑"} {t("expenses.date")}
          </Button>
          <Button onClick={openCreate} disabled={atLimit}>
            <Plus className="h-4 w-4" /> {t("expenses.add")}
          </Button>
        </div>
      </div>

      {atLimit && (
        <p className="flex items-center gap-2 rounded-xl bg-amber-50 px-4 py-2.5 text-sm text-amber-800">
          <Lock className="h-4 w-4" /> {`Free plan limit reached (${limit} expenses). Upgrade to add more.`}
        </p>
      )}

      <Card>
        {filtered.length === 0 ? (
          <EmptyState title={t("expenses.empty.title")} cta={t("expenses.empty.cta")} onCta={openCreate} />
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-ink-100 text-left text-xs text-ink-400">
                  <th className="pb-2 font-medium">{t("expenses.date")}</th>
                  <th className="pb-2 font-medium">{t("expenses.category")}</th>
                  <th className="pb-2 font-medium">{t("expenses.description")}</th>
                  <th className="pb-2 font-medium">{t("expenses.paymentMethod")}</th>
                  <th className="pb-2 text-right font-medium">{t("expenses.amount")}</th>
                  <th className="pb-2" />
                </tr>
              </thead>
              <tbody className="divide-y divide-ink-100">
                {filtered.map((e) => (
                  <tr key={e.id}>
                    <td className="py-3 text-ink-600">{formatDate(e.occurred_on, locale)}</td>
                    <td className="py-3">
                      <Badge>{t(`expenses.categories.${e.category}`)}</Badge>
                    </td>
                    <td className="py-3 text-ink-600">{e.description || "—"}</td>
                    <td className="py-3 text-ink-600">{t(`expenses.paymentMethods.${e.payment_method}`)}</td>
                    <td className="py-3 text-right font-semibold text-ink-900">
                      {formatMoney(Number(e.amount), e.currency, locale)}
                    </td>
                    <td className="py-3">
                      <div className="flex items-center justify-end gap-1">
                        <button
                          onClick={() => openEdit(e)}
                          aria-label={t("expenses.edit")}
                          className="rounded-lg p-1.5 text-ink-400 hover:bg-ink-100 hover:text-ink-700"
                        >
                          <Pencil className="h-3.5 w-3.5" />
                        </button>
                        <button
                          onClick={() => handleDelete(e.id)}
                          aria-label={t("common.delete")}
                          className="rounded-lg p-1.5 text-ink-400 hover:bg-red-50 hover:text-red-600"
                        >
                          <Trash2 className="h-3.5 w-3.5" />
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </Card>

      <ExpenseModal
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        editing={editing}
        currency={currency}
        onSaved={(expense, isNew) => {
          setExpenses((prev) => (isNew ? [expense, ...prev] : prev.map((e) => (e.id === expense.id ? expense : e))));
          setModalOpen(false);
        }}
      />
    </div>
  );
}

function ExpenseModal({
  open,
  onClose,
  editing,
  currency,
  onSaved
}: {
  open: boolean;
  onClose: () => void;
  editing: Expense | null;
  currency: Currency;
  onSaved: (expense: Expense, isNew: boolean) => void;
}) {
  const t = useTranslations();
  const {
    register,
    handleSubmit,
    reset,
    formState: { errors, isSubmitting }
  } = useForm<ExpenseInput>({
    resolver: zodResolver(expenseSchema),
    values: editing
      ? {
          amount: Number(editing.amount),
          currency: editing.currency,
          category: editing.category as ExpenseInput["category"],
          description: editing.description ?? "",
          paymentMethod: editing.payment_method,
          occurredOn: editing.occurred_on
        }
      : {
          amount: 0,
          currency,
          category: "other",
          description: "",
          paymentMethod: "card",
          occurredOn: new Date().toISOString().slice(0, 10)
        }
  });

  async function onSubmit(values: ExpenseInput) {
    const supabase = createClient();
    const { data: userData } = await supabase.auth.getUser();
    if (!userData.user) return;

    if (editing) {
      const { data, error } = await supabase
        .from("expenses")
        .update({
          amount: values.amount,
          currency: values.currency,
          category: values.category,
          description: values.description,
          payment_method: values.paymentMethod,
          occurred_on: values.occurredOn
        })
        .eq("id", editing.id)
        .select()
        .single();
      if (!error && data) onSaved(data, false);
    } else {
      const { data, error } = await supabase
        .from("expenses")
        .insert({
          user_id: userData.user.id,
          amount: values.amount,
          currency: values.currency,
          category: values.category,
          description: values.description,
          payment_method: values.paymentMethod,
          occurred_on: values.occurredOn
        })
        .select()
        .single();
      if (!error && data) onSaved(data, true);
    }
    reset();
  }

  return (
    <Modal open={open} onClose={onClose} title={editing ? t("expenses.edit") : t("expenses.add")}>
      <form onSubmit={handleSubmit(onSubmit)} noValidate className="space-y-4">
        <div className="grid grid-cols-2 gap-3">
          <div>
            <Label htmlFor="amount">{t("expenses.amount")}</Label>
            <Input id="amount" type="number" step="0.01" error={errors.amount?.message} {...register("amount")} />
            <FieldError>{errors.amount?.message}</FieldError>
          </div>
          <div>
            <Label htmlFor="currency">Currency</Label>
            <Select id="currency" {...register("currency")}>
              <option value="PLN">PLN</option>
              <option value="EUR">EUR</option>
              <option value="USD">USD</option>
              <option value="GBP">GBP</option>
            </Select>
          </div>
        </div>
        <div>
          <Label htmlFor="category">{t("expenses.category")}</Label>
          <Select id="category" {...register("category")}>
            {CATEGORIES.map((c) => (
              <option key={c} value={c}>
                {t(`expenses.categories.${c}`)}
              </option>
            ))}
          </Select>
        </div>
        <div>
          <Label htmlFor="description">{t("expenses.description")}</Label>
          <Input id="description" {...register("description")} />
        </div>
        <div className="grid grid-cols-2 gap-3">
          <div>
            <Label htmlFor="occurredOn">{t("expenses.date")}</Label>
            <Input id="occurredOn" type="date" error={errors.occurredOn?.message} {...register("occurredOn")} />
          </div>
          <div>
            <Label htmlFor="paymentMethod">{t("expenses.paymentMethod")}</Label>
            <Select id="paymentMethod" {...register("paymentMethod")}>
              {PAYMENT_METHODS.map((m) => (
                <option key={m} value={m}>
                  {t(`expenses.paymentMethods.${m}`)}
                </option>
              ))}
            </Select>
          </div>
        </div>
        <div className="flex justify-end gap-2 pt-2">
          <Button type="button" variant="secondary" onClick={onClose}>
            {t("common.cancel")}
          </Button>
          <Button type="submit" loading={isSubmitting}>
            {t("common.save")}
          </Button>
        </div>
      </form>
    </Modal>
  );
}
