"use client";

import { useState } from "react";
import { Loader2, Pencil, Plus } from "lucide-react";
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 { Input } from "@/presentation/components/ui/input";
import { Switch } from "@/presentation/components/ui/switch";
import { Textarea } from "@/presentation/components/ui/textarea";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/presentation/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/presentation/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/presentation/components/ui/table";
import type { BillingProduct, BillingProductPayload, BillingProductRole } from "@/domain/entities/billing";

const ROLES: BillingProductRole[] = ["fleet", "telematics", "bundle"];

/**
 * The products the contract clients are invoiced and their list prices (Abonnements > Produits
 * facturés): add one, rename it, change its price, its invoice text, its Pennylane id, or stop
 * offering it. A product's role is set at creation: it says which vehicles its lines count.
 */
export function BillingProductsTab() {
  const t = useT();
  const m = t.billing.products;
  const locale = useLocale();
  const repo = useRepositories().billingRepository;
  const { data: products, loading, refetch } = useApiQuery(() => repo.getProducts(), { deps: [] });
  // null: closed; "new": creating; a product: editing it.
  const [editing, setEditing] = useState<BillingProduct | "new" | null>(null);

  const euros = (value: number) =>
    `${new Intl.NumberFormat(locale === "fr" ? "fr-FR" : "en-GB", { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(value)} €`;

  return (
    <div className="space-y-4">
      <div className="flex items-start justify-between gap-4">
        <p className="text-sm text-muted-foreground max-w-3xl">{m.intro}</p>
        <Button size="sm" className="gap-1.5 shrink-0" onClick={() => setEditing("new")}>
          <Plus className="w-4 h-4" />
          {m.newProduct}
        </Button>
      </div>

      <div className="rounded-xl border border-border">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>{m.columns.product}</TableHead>
              <TableHead>{m.columns.role}</TableHead>
              <TableHead className="text-right">{m.columns.price}</TableHead>
              <TableHead>{m.columns.pennylane}</TableHead>
              <TableHead className="text-right">{m.columns.clients}</TableHead>
              <TableHead>{m.columns.status}</TableHead>
              <TableHead className="w-20" />
            </TableRow>
          </TableHeader>
          <TableBody>
            {loading && !products ? (
              <TableRow>
                <TableCell colSpan={7}>
                  <Loader2 className="w-4 h-4 animate-spin text-muted-foreground" />
                </TableCell>
              </TableRow>
            ) : (
              (products ?? []).map((product) => (
                <TableRow key={product.id} className={product.active ? "" : "opacity-60"}>
                  <TableCell className="max-w-sm whitespace-normal">
                    <p className="text-sm font-medium">{product.label}</p>
                    {product.description && <p className="text-xs text-muted-foreground line-clamp-2">{product.description}</p>}
                  </TableCell>
                  <TableCell className="text-sm">{m.roles[product.role]}</TableCell>
                  <TableCell className="text-sm text-right whitespace-nowrap tabular-nums">{m.perVehicle(euros(product.list_price))}</TableCell>
                  <TableCell className="text-sm tabular-nums">{product.pennylane_product_id ?? "—"}</TableCell>
                  <TableCell className="text-sm text-right tabular-nums">{product.clients_count}</TableCell>
                  <TableCell>
                    <Badge variant={product.active ? "secondary" : "outline"}>{product.active ? m.active : m.inactive}</Badge>
                  </TableCell>
                  <TableCell>
                    <Button size="sm" variant="outline" className="gap-1.5" onClick={() => setEditing(product)}>
                      <Pencil className="w-3.5 h-3.5" />
                      {m.edit}
                    </Button>
                  </TableCell>
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      <Dialog open={editing !== null} onOpenChange={(open) => !open && setEditing(null)}>
        <DialogContent onOpenAutoFocus={(e) => e.preventDefault()}>
          {editing !== null && (
            <ProductForm
              key={editing === "new" ? "new" : editing.id}
              product={editing === "new" ? null : editing}
              onDone={() => { setEditing(null); refetch(); }}
            />
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}

function ProductForm({ product, onDone }: { product: BillingProduct | null; onDone: () => void }) {
  const t = useT();
  const m = t.billing.products;
  const d = m.dialog;
  const repo = useRepositories().billingRepository;
  const [label, setLabel] = useState(product?.label ?? "");
  const [role, setRole] = useState<BillingProductRole>(product?.role ?? "telematics");
  const [price, setPrice] = useState(product ? String(product.list_price) : "");
  const [description, setDescription] = useState(product?.description ?? "");
  const [pennylane, setPennylane] = useState(product?.pennylane_product_id ?? "");
  const [active, setActive] = useState(product?.active ?? true);
  // A product on a contract stays on: its clients' contracts change first.
  const locked = !!product && product.active && product.clients_count > 0;

  const save = useApiMutation(
    () => {
      const payload: BillingProductPayload = {
        label: label.trim(),
        list_price: Number(price.replace(",", ".")),
        description: description.trim() || null,
        pennylane_product_id: pennylane.trim() || null,
      };
      return product
        ? repo.updateProduct(product.id, { ...payload, active })
        : repo.createProduct({ ...payload, role });
    },
    { successMessage: product ? m.saved : m.created, onSuccess: onDone }
  );

  const valid = label.trim() !== "" && price.trim() !== "" && !Number.isNaN(Number(price.replace(",", ".")));

  return (
    <>
      <DialogHeader>
        <DialogTitle>{product ? d.titleEdit : d.titleCreate}</DialogTitle>
      </DialogHeader>

      <div className="space-y-3">
        <Field label={d.label}>
          <Input value={label} onChange={(e) => setLabel(e.target.value)} maxLength={191} className="h-8" />
        </Field>
        <Field label={d.role} hint={d.roleFixed}>
          <Select value={role} onValueChange={(value) => setRole(value as BillingProductRole)} disabled={!!product}>
            <SelectTrigger size="sm" className="h-8"><SelectValue /></SelectTrigger>
            <SelectContent>
              {ROLES.map((value) => (
                <SelectItem key={value} value={value}>{m.roles[value]}</SelectItem>
              ))}
            </SelectContent>
          </Select>
        </Field>
        <Field label={d.price}>
          <Input type="number" min={0} step="0.01" value={price} onChange={(e) => setPrice(e.target.value)} className="h-8" />
        </Field>
        <Field label={d.description}>
          <Textarea value={description} onChange={(e) => setDescription(e.target.value)} maxLength={2000} className="text-sm" />
        </Field>
        <Field label={d.pennylane} hint={d.pennylaneHint}>
          <Input inputMode="numeric" value={pennylane} onChange={(e) => setPennylane(e.target.value.replace(/\D/g, ""))} className="h-8" />
        </Field>
        {product && (
          <div className="space-y-1">
            <label className="flex items-center justify-between gap-3 text-xs font-medium">
              {d.active}
              <Switch checked={active} onCheckedChange={setActive} disabled={locked} />
            </label>
            {locked && <p className="text-[11px] text-muted-foreground">{d.activeLocked(product.clients_count)}</p>}
          </div>
        )}
      </div>

      <DialogFooter>
        <Button size="sm" disabled={!valid || save.loading} onClick={() => save.mutate(undefined)}>
          {save.loading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
          {product ? d.save : d.create}
        </Button>
      </DialogFooter>
    </>
  );
}

function Field({ label, hint, children }: { label: string; hint?: string; children: React.ReactNode }) {
  return (
    <div className="space-y-1">
      <p className="text-xs font-medium">{label}</p>
      {children}
      {hint && <p className="text-[11px] text-muted-foreground">{hint}</p>}
    </div>
  );
}
