"use client";

import { useMemo, useState } from "react";
import { AlertTriangle, Car, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { useRepositories } from "@/di/repository-provider";
import { useApiQuery } from "@/presentation/hooks/use-api-query";
import { useApiMutation } from "@/presentation/hooks/use-api-mutation";
import { useT, useLocale } from "@/shared/i18n/client";
import { Badge } from "@/presentation/components/ui/badge";
import { Button } from "@/presentation/components/ui/button";
import { Checkbox } from "@/presentation/components/ui/checkbox";
import { Input } from "@/presentation/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/presentation/components/ui/select";
import type { VehiclePlansState } from "@/domain/entities/billing";

const ownPrice = (plan: VehiclePlansState["plans"][number]) => (plan.own_price ? String(plan.unit_price) : "");

/**
 * Plans per vehicle (2026-09-28): the plans each of the client's vehicles is billed, set here by
 * Dadycar (the client sets them too, from its billing page), and the client's own price per plan.
 * The company's offer keeps opening its modules.
 */
export function BillingVehiclePlansPanel({ clientId, version = 0, onChanged }: {
  clientId: number;
  /** Bumped when the contract changes: its rule and "billed" state are read again. */
  version?: number;
  onChanged: () => void;
}) {
  const repo = useRepositories().billingRepository;
  const { data, loading, refetch } = useApiQuery(() => repo.getVehiclePlans(clientId), { deps: [clientId, version] });

  if (loading && !data) {
    return (
      <div className="rounded-xl border border-border p-4">
        <Loader2 className="w-4 h-4 animate-spin text-muted-foreground" />
      </div>
    );
  }

  // The price inputs start again from what the server holds once prices are saved.
  return data ? (
    <VehiclePlansForm
      key={data.plans.map((plan) => `${plan.id}:${ownPrice(plan)}`).join("|")}
      clientId={clientId}
      data={data}
      onSaved={() => { refetch(); onChanged(); }}
    />
  ) : null;
}

function VehiclePlansForm({ clientId, data, onSaved }: { clientId: number; data: VehiclePlansState; onSaved: () => void }) {
  const t = useT();
  const m = t.billing.manage.vehiclePlans;
  const locale = useLocale();
  const repo = useRepositories().billingRepository;
  const [prices, setPrices] = useState<Record<number, string>>(() => Object.fromEntries(data.plans.map((plan) => [plan.id, ownPrice(plan)])));
  const [query, setQuery] = useState("");
  const [selected, setSelected] = useState<Set<number>>(() => new Set());
  const [planId, setPlanId] = useState(data.plans[0] ? String(data.plans[0].id) : "");

  const nf = new Intl.NumberFormat(locale === "fr" ? "fr-FR" : "en-GB", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const euros = (value: number) => `${nf.format(value)} €`;
  const planName = (id: number) => data.plans.find((plan) => plan.id === id)?.name ?? `#${id}`;
  const byOffer = new Set(data.billed_by_offer?.vehicle_ids ?? []);

  const vehicles = useMemo(() => {
    const q = query.trim().toLowerCase();
    return q
      ? data.vehicles.filter((v) => [v.numberplate, v.mark, v.model].some((s) => s?.toLowerCase().includes(q)))
      : data.vehicles;
  }, [data.vehicles, query]);
  const allChecked = vehicles.length > 0 && vehicles.every((v) => selected.has(v.id));
  const changedPrices = data.plans.filter((plan) => (prices[plan.id] ?? "").trim() !== ownPrice(plan));

  const savePrices = useApiMutation(
    () => repo.updatePlanPrices(clientId, changedPrices.map((plan) => {
      const value = (prices[plan.id] ?? "").trim();
      return { subscription_plan_id: plan.id, unit_price: value === "" ? null : Number(value.replace(",", ".")) };
    })),
    { successMessage: m.pricesSaved, onSuccess: onSaved }
  );

  const change = useApiMutation(
    (action: "add" | "remove") => repo.updateVehiclePlans(clientId, {
      vehicle_ids: [...selected],
      add: action === "add" ? [Number(planId)] : [],
      remove: action === "remove" ? [Number(planId)] : [],
    }),
    {
      onSuccess: (state) => {
        const prorata = state?.result?.adjustment?.amount_ht;
        toast.success(prorata
          ? `${m.updated}. ${m.prorata(`${prorata > 0 ? "+" : "−"}${euros(Math.abs(prorata))}`)}`
          : m.updated);
        onSaved();
      },
    }
  );

  const toggle = (id: number, on: boolean) => setSelected((current) => {
    const next = new Set(current);
    if (on) next.add(id); else next.delete(id);
    return next;
  });
  const toggleAll = (on: boolean) => setSelected((current) => {
    const next = new Set(current);
    vehicles.forEach((v) => (on ? next.add(v.id) : next.delete(v.id)));
    return next;
  });

  return (
    <div className="rounded-xl border border-border p-4 space-y-4">
      <div className="min-w-0">
        <p className="flex items-center gap-1.5 font-medium text-sm">
          <Car className="w-4 h-4" />
          {m.title}
        </p>
        <p className="text-xs text-muted-foreground mt-0.5">
          {data.in_use
            ? m.inUse
            : data.billed_by_offer
              ? m.offerNotInUse(planName(data.billed_by_offer.plan_id), data.billed_by_offer.vehicle_ids.length)
              : null}
        </p>
      </div>

      {!data.in_use && data.rule === "contract" && (
        <div className="flex gap-2 rounded-lg bg-amber-50 dark:bg-amber-950/30 border border-amber-200 dark:border-amber-900 p-3 text-xs text-amber-800 dark:text-amber-300">
          <AlertTriangle className="w-4 h-4 shrink-0 mt-0.5" />
          <span>{m.contractNotInUse}</span>
        </div>
      )}
      {!data.billed && <p className="text-xs text-muted-foreground">{m.notBilled}</p>}

      {/* The client's price per plan */}
      <div className="space-y-2">
        <table className="w-full text-xs">
          <thead className="text-muted-foreground">
            <tr>
              <th className="text-left font-medium">{m.columns.plan}</th>
              <th className="text-right font-medium">{m.columns.list}</th>
              <th className="text-right font-medium">{m.columns.price}</th>
              <th className="text-right font-medium">{m.columns.vehicles}</th>
            </tr>
          </thead>
          <tbody>
            {data.plans.map((plan) => (
              <tr key={plan.id}>
                <td className="py-1">
                  {plan.name}
                  {!plan.on_sale && <span className="text-muted-foreground"> ({m.offSale})</span>}
                </td>
                <td className="text-right whitespace-nowrap">{euros(plan.list_price)}</td>
                <td className="py-1">
                  <Input
                    type="number"
                    min={0}
                    step="0.01"
                    placeholder={nf.format(plan.list_price)}
                    value={prices[plan.id] ?? ""}
                    onChange={(e) => setPrices((current) => ({ ...current, [plan.id]: e.target.value }))}
                    className="h-7 w-24 ml-auto text-right"
                  />
                </td>
                <td className="text-right">{plan.vehicles}</td>
              </tr>
            ))}
          </tbody>
        </table>
        <div className="flex items-center justify-between gap-3">
          <p className="text-[11px] text-muted-foreground">{m.priceHint}</p>
          <Button size="sm" variant="outline" disabled={changedPrices.length === 0 || savePrices.loading} onClick={() => savePrices.mutate(undefined)}>
            {savePrices.loading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
            {m.savePrices}
          </Button>
        </div>
      </div>

      {/* The vehicles and their plans */}
      <div className="space-y-2 border-t border-border pt-4">
        <div className="flex flex-wrap items-center gap-2">
          <Input placeholder={m.search} value={query} onChange={(e) => setQuery(e.target.value)} className="h-8 flex-1 min-w-40" />
          <Select value={planId} onValueChange={setPlanId}>
            <SelectTrigger size="sm" className="h-8 w-44"><SelectValue placeholder={m.choosePlan} /></SelectTrigger>
            <SelectContent>
              {data.plans.map((plan) => (
                <SelectItem key={plan.id} value={String(plan.id)}>{plan.name}</SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Button size="sm" disabled={selected.size === 0 || !planId || change.loading} onClick={() => change.mutate("add")}>
            {change.loading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
            {m.add}
          </Button>
          <Button size="sm" variant="outline" disabled={selected.size === 0 || !planId || change.loading} onClick={() => change.mutate("remove")}>
            {m.remove}
          </Button>
        </div>

        {data.vehicles.length === 0 ? (
          <p className="text-xs text-muted-foreground">{m.noVehicle}</p>
        ) : (
          <div className="max-h-72 overflow-y-auto rounded-lg border border-border">
            <table className="w-full text-xs">
              <thead className="sticky top-0 bg-background text-muted-foreground">
                <tr>
                  <th className="w-8 p-2">
                    <Checkbox checked={allChecked} onCheckedChange={(on) => toggleAll(on === true)} aria-label={m.selectAll} />
                  </th>
                  <th className="text-left font-medium p-2">{m.columns.vehicle}</th>
                  <th className="text-left font-medium p-2">{m.columns.plan}</th>
                </tr>
              </thead>
              <tbody>
                {vehicles.map((v) => (
                  <tr key={v.id} className="border-t border-border">
                    <td className="p-2">
                      <Checkbox checked={selected.has(v.id)} onCheckedChange={(on) => toggle(v.id, on === true)} aria-label={v.numberplate ?? String(v.id)} />
                    </td>
                    <td className="p-2">
                      <span className="font-medium">{v.numberplate ?? `#${v.id}`}</span>{" "}
                      <span className="text-muted-foreground">{[v.mark, v.model].filter(Boolean).join(" ")}</span>
                      {v.connected && <span className="text-emerald-600"> · {m.connected}</span>}
                    </td>
                    <td className="p-2">
                      <div className="flex flex-wrap gap-1">
                        {v.plan_ids.map((id) => <Badge key={id} variant="secondary">{planName(id)}</Badge>)}
                        {data.billed_by_offer && byOffer.has(v.id) && (
                          <Badge variant="outline">{planName(data.billed_by_offer.plan_by_vehicle?.[v.id] ?? data.billed_by_offer.plan_id)} · {m.byOffer}</Badge>
                        )}
                        {v.plan_ids.length === 0 && !byOffer.has(v.id) && <span className="text-muted-foreground">{m.none}</span>}
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}

        <div className="flex justify-between gap-3 text-xs">
          <span className="text-muted-foreground">{m.selected(selected.size)}</span>
          <span className="font-semibold">{m.totals(data.totals.with_plan, data.totals.vehicles, euros(data.totals.amount_ht))}</span>
        </div>
      </div>
    </div>
  );
}
