"use client";

import { useState } from "react";
import { FileText, Loader2 } 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 { 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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/presentation/components/ui/select";
import type { BillingInvoicePreview, BillingProductRole, BillingProfile, BillingProfilePayload } from "@/domain/entities/billing";

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

/** For each role, the product key (or NONE: not invoiced) and the client's price ("": list price). */
type Form = {
  active: boolean;
  mode: string;
  products: Record<BillingProductRole, string>;
  prices: Record<BillingProductRole, string>;
  notes: string;
};

const asInput = (value: number | null | undefined) => (value === null || value === undefined ? "" : String(value));
const asPrice = (value: string) => (value.trim() === "" ? null : Number(value.replace(",", ".")));
const formOf = (p: BillingProfile | null): Form => ({
  active: p?.active ?? false,
  mode: p?.mode ?? "contract",
  products: {
    fleet: p?.fleet_product ?? NONE,
    telematics: p?.telematics_product ?? NONE,
    bundle: p?.bundle_product ?? NONE,
  },
  prices: {
    fleet: asInput(p?.fleet_unit_price),
    telematics: asInput(p?.telematics_unit_price),
    bundle: asInput(p?.bundle_unit_price),
  },
  notes: p?.notes ?? "",
});

/**
 * A client's billing contract on the admin platform (billing automation, part 1): whether the
 * platform invoices it, at which of its own prices, and the invoices those prices give for the
 * month just ended and for the month running.
 */
export function BillingContractPanel({ clientId, version = 0, onChanged }: {
  clientId: number;
  /** Bumped when the vehicles' plans change: the previews are computed again. */
  version?: number;
  onChanged: () => void;
}) {
  const repo = useRepositories().billingRepository;
  const { data, loading, refetch } = useApiQuery(() => repo.getProfile(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>
    );
  }

  // Keyed on the saved profile: the form starts again from what the server holds.
  return data ? (
    <ContractForm
      key={data.profile?.updated_at ?? "none"}
      clientId={clientId}
      data={data}
      onSaved={() => { refetch(); onChanged(); }}
    />
  ) : null;
}

function ContractForm({ clientId, data, onSaved }: { clientId: number; data: BillingProfilePayload; onSaved: () => void }) {
  const t = useT();
  const m = t.billing.manage.contract;
  const locale = useLocale();
  const repo = useRepositories().billingRepository;
  const [form, setForm] = useState<Form>(() => formOf(data.profile));

  const product = (role: BillingProductRole) => (form.products[role] === NONE ? null : form.products[role]);
  const price = (role: BillingProductRole) => (form.products[role] === NONE ? null : asPrice(form.prices[role]));
  const save = useApiMutation(
    () => repo.updateProfile(clientId, {
      active: form.active,
      mode: form.mode as BillingProfile["mode"],
      fleet_product: product("fleet"),
      fleet_unit_price: price("fleet"),
      telematics_product: product("telematics"),
      telematics_unit_price: price("telematics"),
      bundle_product: product("bundle"),
      bundle_unit_price: price("bundle"),
      notes: form.notes.trim() || null,
    }),
    { successMessage: m.saved, onSuccess: onSaved }
  );

  const nf = new Intl.NumberFormat(locale === "fr" ? "fr-FR" : "en-GB", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const euros = (value: number) => `${nf.format(value)} €`;
  const percent = (value: number) =>
    `${new Intl.NumberFormat(locale === "fr" ? "fr-FR" : "en-GB", { maximumFractionDigits: 2 }).format(value)} %`;
  const listPrice = (key: string) => data.products.find((p) => p.key === key)?.list_price ?? 0;
  const setRole = (role: BillingProductRole, patch: { product?: string; price?: string }) =>
    setForm((current) => ({
      ...current,
      products: patch.product === undefined ? current.products : { ...current.products, [role]: patch.product },
      prices: patch.price === undefined ? current.prices : { ...current.prices, [role]: patch.price },
    }));
  const monthName = (ymd?: string) => {
    if (!ymd) return "";
    const [year, month] = ymd.split("-").map(Number);
    return new Date(year, month - 1, 1).toLocaleDateString(locale === "fr" ? "fr-FR" : "en-GB", { month: "long", year: "numeric" });
  };
  const set = (patch: Partial<Form>) => setForm((current) => ({ ...current, ...patch }));

  return (
    <div className="rounded-xl border border-border p-4 space-y-4">
      <div className="flex items-start justify-between gap-4">
        <div className="min-w-0">
          <p className="flex items-center gap-1.5 font-medium text-sm">
            <FileText className="w-4 h-4" />
            {m.title}
          </p>
          <p className="text-xs text-muted-foreground mt-0.5">{data?.profile ? m.activeHelp : m.none}</p>
        </div>
        <label className="flex items-center gap-2 text-xs font-medium whitespace-nowrap">
          {m.active}
          <Switch checked={form.active} onCheckedChange={(active) => set({ active })} />
        </label>
      </div>

      <div className="space-y-1">
        <p className="text-xs font-medium">{m.mode}</p>
        <Select value={form.mode} onValueChange={(mode) => set({ mode })}>
          <SelectTrigger size="sm" className="h-8"><SelectValue /></SelectTrigger>
          <SelectContent>
            {Object.entries(m.modes).map(([value, label]) => (
              <SelectItem key={value} value={value}>{label}</SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>

      {/* For each role, the product from the catalogue (Produits facturés) and the client's price. */}
      {form.mode === "contract" && (
        <div className="space-y-3">
          {ROLES.map((role) => (
            <div key={role} className="space-y-1">
              <p className="text-xs font-medium">{m.roles[role]}</p>
              <div className="grid grid-cols-1 sm:grid-cols-[minmax(0,3fr)_minmax(0,2fr)] gap-3">
                <Select value={form.products[role]} onValueChange={(value) => setRole(role, { product: value })}>
                  <SelectTrigger size="sm" className="h-8 w-full min-w-0"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value={NONE}>{m.notInvoiced}</SelectItem>
                    {data.products.filter((p) => p.role === role).map((p) => (
                      <SelectItem key={p.key} value={p.key}>{p.label}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                {form.products[role] !== NONE && (
                  <div className="space-y-1">
                    <Input
                      type="number"
                      min={0}
                      step="0.01"
                      placeholder={m.clientPrice}
                      aria-label={m.clientPrice}
                      value={form.prices[role]}
                      onChange={(e) => setRole(role, { price: e.target.value })}
                      className="h-8"
                    />
                    <p className="text-[11px] text-muted-foreground">{m.priceHint(euros(listPrice(form.products[role])))}</p>
                  </div>
                )}
              </div>
            </div>
          ))}
        </div>
      )}

      <Textarea placeholder={m.notes} value={form.notes} onChange={(e) => set({ notes: e.target.value })} className="text-sm" />

      <div className="flex justify-end">
        <Button size="sm" disabled={save.loading} onClick={() => save.mutate(undefined)}>
          {save.loading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
          {m.save}
        </Button>
      </div>

      {data.last_month && <Preview title={m.lastMonth(monthName(data.last_month.period_start))} preview={data.last_month} euros={euros} percent={percent} />}
      {data.this_month && <Preview title={m.thisMonth(monthName(data.this_month.period_start))} preview={data.this_month} euros={euros} percent={percent} />}
      {data.next_month && <Preview title={m.nextMonth(monthName(data.next_month.period_start))} preview={data.next_month} euros={euros} percent={percent} />}
    </div>
  );
}

function Preview({ title, preview, euros, percent }: {
  title: string;
  preview: BillingInvoicePreview;
  euros: (value: number) => string;
  percent: (value: number) => string;
}) {
  const t = useT();
  const m = t.billing.manage.contract;

  return (
    <div className="rounded-lg bg-muted/40 p-3 space-y-2">
      <p className="text-xs font-semibold">{title}</p>
      {/* Lines: a contract's products, or the plans the vehicles hold (plans per vehicle, either rule). */}
      {preview.lines && preview.lines.length > 0 ? (
        <table className="w-full text-xs">
          <thead className="text-muted-foreground">
            <tr>
              <th className="text-left font-medium">{m.columns.product}</th>
              <th className="text-right font-medium">{m.columns.quantity}</th>
              <th className="text-right font-medium">{m.columns.list}</th>
              <th className="text-right font-medium">{m.columns.discount}</th>
              <th className="text-right font-medium">{m.columns.total}</th>
            </tr>
          </thead>
          <tbody>
            {preview.lines.map((line) => (
              <tr key={`${line.product}-${line.plan_id ?? ""}`}>
                <td>{line.label}</td>
                <td className="text-right">{line.quantity}</td>
                <td className="text-right whitespace-nowrap">{euros(line.list_price)}</td>
                <td className="text-right">{line.discount_percent > 0 ? percent(line.discount_percent) : "—"}</td>
                <td className="text-right whitespace-nowrap">{euros(line.total_ht)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      ) : (
        <p className="text-xs text-muted-foreground">
          {preview.rule === "plan" ? `${preview.vehicles_count} × ${euros(preview.unit_price)}` : m.empty}
        </p>
      )}
      {/* Plan rule: the prorata of plan changes, invoiced with the month ahead. */}
      {preview.rule === "plan" && (preview.adjustments ?? []).map((adjustment, i) => (
        <div key={i} className="flex justify-between gap-3 text-xs">
          <span className="text-muted-foreground">{adjustment.label}</span>
          <span className="whitespace-nowrap">{adjustment.amount_ht > 0 ? "+" : "−"}{euros(Math.abs(adjustment.amount_ht))}</span>
        </div>
      ))}
      <div className="flex justify-between gap-3 text-xs">
        <span className="text-muted-foreground">
          {preview.counts ? m.counts(preview.counts.fleet, preview.counts.boxes, preview.counts.connected_cars) : ""}
        </span>
        <span className="font-semibold whitespace-nowrap">{m.total} : {euros(preview.amount_ht)}</span>
      </div>
    </div>
  );
}
