import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Pencil, Plus, Trash2 } from "lucide-react";
import { supabase } from "@/integrations/supabase/client";
import { AccountSelect } from "@/components/AccountSelect";
import { EmptyState, SectionCard } from "@/components/ui-kit";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { formatMoney } from "@/lib/format";
import {
  deleteBookingCostRule,
  listBookingCostRules,
  saveBookingCostRule,
  setBookingCostRuleActive,
  type BookingCostRule,
} from "@/lib/erp";

const COST_TYPES = [
  { value: "crew", label: "Crew / operator" },
  { value: "talent", label: "Talent / model fee" },
  { value: "equipment", label: "Equipment rental" },
  { value: "props", label: "Props & wardrobe" },
  { value: "location", label: "Location & permits" },
  { value: "travel", label: "Travel & logistics" },
  { value: "editing", label: "Editing / post-production" },
  { value: "other", label: "Other direct cost" },
];

type FormState = {
  id?: string;
  name: string;
  cost_type: string;
  cost_account_id: string | null;
  basis: "percent" | "fixed";
  rate: string;
  service_id: string;
  room_id: string;
  is_paid: boolean;
  paid_from_account_id: string | null;
  vendor_id: string;
  description: string;
};

const EMPTY: FormState = {
  name: "",
  cost_type: "crew",
  cost_account_id: null,
  basis: "percent",
  rate: "",
  service_id: "",
  room_id: "",
  is_paid: false,
  paid_from_account_id: null,
  vendor_id: "",
  description: "",
};

/** Cost categories that auto-post direct costs the moment a booking is approved. */
export function BookingCostRules({ canEdit }: { canEdit: boolean }) {
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const [form, setForm] = useState<FormState>(EMPTY);

  const { data: rules = [], isLoading } = useQuery({
    queryKey: ["booking-cost-rules"],
    queryFn: listBookingCostRules,
  });

  const { data: lookups } = useQuery({
    queryKey: ["booking-cost-rule-lookups"],
    queryFn: async () => {
      const [services, rooms, vendors] = await Promise.all([
        supabase.from("services").select("id, name").order("name").limit(300),
        supabase.from("rooms").select("id, name").order("name").limit(300),
        supabase.from("vendors").select("id, name").order("name").limit(300),
      ]);
      return {
        services: (services.data ?? []) as { id: string; name: string }[],
        rooms: (rooms.data ?? []) as { id: string; name: string }[],
        vendors: (vendors.data ?? []) as { id: string; name: string }[],
      };
    },
  });

  const invalidate = () => {
    qc.invalidateQueries({ queryKey: ["booking-cost-rules"] });
  };

  const save = useMutation({
    mutationFn: async () => {
      if (!form.name.trim()) throw new Error("Give the cost category a name");
      if (!form.cost_account_id) throw new Error("Pick the cost of sales account it posts to");
      const rate = Number(form.rate || 0);
      if (!Number.isFinite(rate) || rate < 0) throw new Error("Enter a valid rate or amount");
      if (form.is_paid && !form.paid_from_account_id) throw new Error("Pick the account it is paid from");
      return saveBookingCostRule({
        ...(form.id ? { id: form.id } : {}),
        name: form.name.trim(),
        cost_type: form.cost_type,
        cost_account_id: form.cost_account_id,
        basis: form.basis,
        rate,
        service_id: form.service_id || null,
        room_id: form.room_id || null,
        is_paid: form.is_paid,
        paid_from_account_id: form.paid_from_account_id,
        vendor_id: form.vendor_id || null,
        description: form.description.trim() || null,
      });
    },
    onSuccess: () => {
      toast.success(form.id ? "Cost category updated" : "Cost category added");
      setOpen(false);
      setForm(EMPTY);
      invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const toggle = useMutation({
    mutationFn: ({ id, active }: { id: string; active: boolean }) => setBookingCostRuleActive(id, active),
    onSuccess: invalidate,
    onError: (e: Error) => toast.error(e.message),
  });

  const remove = useMutation({
    mutationFn: (id: string) => deleteBookingCostRule(id),
    onSuccess: () => {
      toast.success("Cost category removed");
      invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  function edit(rule: BookingCostRule) {
    setForm({
      id: rule.id,
      name: rule.name,
      cost_type: rule.cost_type,
      cost_account_id: rule.cost_account_id,
      basis: rule.basis,
      rate: String(rule.rate ?? ""),
      service_id: rule.service_id ?? "",
      room_id: rule.room_id ?? "",
      is_paid: rule.is_paid,
      paid_from_account_id: rule.paid_from_account_id,
      vendor_id: rule.vendor_id ?? "",
      description: rule.description ?? "",
    });
    setOpen(true);
  }

  return (
    <SectionCard
      className="mt-4"
      title="Automatic cost categories on approval"
      actions={
        canEdit && (
          <Button
            size="sm"
            onClick={() => {
              setForm(EMPTY);
              setOpen(true);
            }}
          >
            <Plus className="mr-2 h-4 w-4" /> Add category
          </Button>
        )
      }
    >
      <p className="mb-3 text-sm text-muted-foreground">
        When an administrator approves a booking, every active category below posts its own cost entry to the right
        ledger account — a percentage of the booking value or a fixed amount. Existing entries are never duplicated.
      </p>

      {isLoading ? (
        <p className="text-sm text-muted-foreground">Loading…</p>
      ) : rules.length === 0 ? (
        <EmptyState
          title="No automatic cost categories"
          description="Add one so approved bookings immediately carry their crew, props or rental cost."
        />
      ) : (
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Category</TableHead>
                <TableHead>Cost account</TableHead>
                <TableHead>Applies to</TableHead>
                <TableHead>Amount</TableHead>
                <TableHead>Settlement</TableHead>
                <TableHead>Active</TableHead>
                <TableHead className="text-right">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {rules.map((r) => (
                <TableRow key={r.id}>
                  <TableCell className="font-medium">
                    {r.name}
                    <span className="block text-xs font-normal text-muted-foreground capitalize">
                      {COST_TYPES.find((t) => t.value === r.cost_type)?.label ?? r.cost_type}
                    </span>
                  </TableCell>
                  <TableCell className="text-muted-foreground">
                    {r.accounts ? `${r.accounts.code} · ${r.accounts.name}` : "—"}
                  </TableCell>
                  <TableCell className="text-muted-foreground">
                    {r.services?.name ?? r.rooms?.name ?? "Every booking"}
                  </TableCell>
                  <TableCell>
                    {r.basis === "percent" ? `${Number(r.rate)}% of booking value` : formatMoney(Number(r.rate))}
                  </TableCell>
                  <TableCell>
                    <Badge variant={r.is_paid ? "secondary" : "outline"}>
                      {r.is_paid ? "Paid immediately" : "Accrued as payable"}
                    </Badge>
                  </TableCell>
                  <TableCell>
                    <Switch
                      checked={r.is_active}
                      disabled={!canEdit || toggle.isPending}
                      onCheckedChange={(v) => toggle.mutate({ id: r.id, active: v })}
                    />
                  </TableCell>
                  <TableCell className="text-right">
                    {canEdit ? (
                      <div className="flex justify-end gap-1">
                        <Button size="icon" variant="ghost" aria-label="Edit category" onClick={() => edit(r)}>
                          <Pencil className="h-4 w-4" />
                        </Button>
                        <Button
                          size="icon"
                          variant="ghost"
                          aria-label="Delete category"
                          onClick={() => remove.mutate(r.id)}
                        >
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    ) : (
                      <span className="text-xs text-muted-foreground">View only</span>
                    )}
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>
      )}

      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>{form.id ? "Edit cost category" : "Add cost category"}</DialogTitle>
          </DialogHeader>
          <div className="grid gap-3 sm:grid-cols-2">
            <div className="sm:col-span-2">
              <Label htmlFor="rn">Name</Label>
              <Input
                id="rn"
                value={form.name}
                onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
                placeholder="Crew fee on approval"
              />
            </div>
            <div>
              <Label htmlFor="rt">Cost type</Label>
              <Select value={form.cost_type} onValueChange={(v) => setForm((f) => ({ ...f, cost_type: v }))}>
                <SelectTrigger id="rt">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {COST_TYPES.map((t) => (
                    <SelectItem key={t.value} value={t.value}>
                      {t.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label htmlFor="rb">Basis</Label>
              <Select
                value={form.basis}
                onValueChange={(v) => setForm((f) => ({ ...f, basis: v as "percent" | "fixed" }))}
              >
                <SelectTrigger id="rb">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="percent">Percent of booking value</SelectItem>
                  <SelectItem value="fixed">Fixed amount</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="sm:col-span-2">
              <Label htmlFor="rac">Cost of sales account</Label>
              <AccountSelect
                id="rac"
                typeCodes={["COS", "EXPENSE"]}
                value={form.cost_account_id}
                onChange={(v) => setForm((f) => ({ ...f, cost_account_id: v }))}
                placeholder="Select cost account"
              />
            </div>
            <div>
              <Label htmlFor="rr">{form.basis === "percent" ? "Rate (%)" : "Amount"}</Label>
              <Input
                id="rr"
                inputMode="decimal"
                value={form.rate}
                onChange={(e) => setForm((f) => ({ ...f, rate: e.target.value }))}
                placeholder="0"
              />
            </div>
            <div>
              <Label htmlFor="rv">Vendor (optional)</Label>
              <Select
                value={form.vendor_id || "none"}
                onValueChange={(v) => setForm((f) => ({ ...f, vendor_id: v === "none" ? "" : v }))}
              >
                <SelectTrigger id="rv">
                  <SelectValue placeholder="No vendor" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">No vendor</SelectItem>
                  {(lookups?.vendors ?? []).map((v) => (
                    <SelectItem key={v.id} value={v.id}>
                      {v.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label htmlFor="rs">Only for service</Label>
              <Select
                value={form.service_id || "any"}
                onValueChange={(v) => setForm((f) => ({ ...f, service_id: v === "any" ? "" : v }))}
              >
                <SelectTrigger id="rs">
                  <SelectValue placeholder="Any service" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="any">Any service</SelectItem>
                  {(lookups?.services ?? []).map((s) => (
                    <SelectItem key={s.id} value={s.id}>
                      {s.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label htmlFor="rm">Only for room</Label>
              <Select
                value={form.room_id || "any"}
                onValueChange={(v) => setForm((f) => ({ ...f, room_id: v === "any" ? "" : v }))}
              >
                <SelectTrigger id="rm">
                  <SelectValue placeholder="Any room" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="any">Any room</SelectItem>
                  {(lookups?.rooms ?? []).map((r) => (
                    <SelectItem key={r.id} value={r.id}>
                      {r.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="flex items-center justify-between rounded-md border border-border p-3 sm:col-span-2">
              <div>
                <p className="text-sm font-medium">Paid immediately</p>
                <p className="text-xs text-muted-foreground">
                  Off = the cost sits in Accounts Payable until the vendor is paid.
                </p>
              </div>
              <Switch checked={form.is_paid} onCheckedChange={(v) => setForm((f) => ({ ...f, is_paid: v }))} />
            </div>
            {form.is_paid && (
              <div className="sm:col-span-2">
                <Label htmlFor="rpf">Paid from</Label>
                <AccountSelect
                  id="rpf"
                  typeCodes={["CASH"]}
                  value={form.paid_from_account_id}
                  onChange={(v) => setForm((f) => ({ ...f, paid_from_account_id: v }))}
                  placeholder="Cash or bank account"
                />
              </div>
            )}
            <div className="sm:col-span-2">
              <Label htmlFor="rd">Description on the ledger entry</Label>
              <Textarea
                id="rd"
                value={form.description}
                onChange={(e) => setForm((f) => ({ ...f, description: e.target.value }))}
                placeholder="Crew cost accrued when the booking was approved"
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button onClick={() => save.mutate()} disabled={save.isPending}>
              {form.id ? "Save changes" : "Add category"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </SectionCard>
  );
}
