"use client";

import { useState } from "react";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import { useRepositories } from "@/di/repository-provider";
import { useT } from "@/shared/i18n/client";
import { useApiQuery } from "@/presentation/hooks/use-api-query";
import { useApiMutation } from "@/presentation/hooks/use-api-mutation";
import { Button } from "@/presentation/components/ui/button";
import { Input } from "@/presentation/components/ui/input";
import { Textarea } from "@/presentation/components/ui/textarea";
import { Dialog, DialogContent, 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 { CompanySubscriptionState, PlanChangePreview } from "@/domain/entities/subscription";
import type { SubscriptionPlan } from "@/domain/entities/subscription-plan";

const euros = (value: number) =>
  `${value.toLocaleString("fr-FR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })} €`;
const day = (iso: string) => new Date(iso).toLocaleDateString("fr-FR", { day: "2-digit", month: "long", year: "numeric" });
/** A YYYY-MM-DD date read as a calendar day, never shifted by the browser's time zone. */
const calendarDay = (ymd: string) => {
  const [year, month, date] = ymd.slice(0, 10).split("-").map(Number);
  return new Date(year, month - 1, date).toLocaleDateString("fr-FR", { day: "2-digit", month: "long", year: "numeric" });
};

/** The last day of the current month, as the date input wants it. */
const endOfMonth = () => {
  const now = new Date();
  const last = new Date(now.getFullYear(), now.getMonth() + 1, 0);
  return `${last.getFullYear()}-${String(last.getMonth() + 1).padStart(2, "0")}-${String(last.getDate()).padStart(2, "0")}`;
};

/**
 * A company's subscription on the admin platform (billing automation, part 2): its plan,
 * changed after a look at what it costs or gives back this month; its cancellation, at a
 * date of our choice, and undone before it; the prorated amounts waiting for the next
 * invoice; its 15-day trial of Fleet Business while it runs; the history of all of it.
 */
export function CompanySubscriptionPanel({ companyId, currentPlan, plans, onPlanChanged }: {
  companyId: number;
  currentPlan: { id: number; name: string } | null;
  plans: SubscriptionPlan[];
  onPlanChanged: () => void;
}) {
  const t = useT();
  const m = t.subscriptionChanges;
  const container = useRepositories();

  const [pending, setPending] = useState<{ plan: SubscriptionPlan; preview: PlanChangePreview } | null>(null);
  const [previewing, setPreviewing] = useState(false);
  const [cancelOpen, setCancelOpen] = useState(false);
  const [endsAt, setEndsAt] = useState(endOfMonth);
  const [reason, setReason] = useState("");

  const { data: state, loading, refetch } = useApiQuery<CompanySubscriptionState>(
    () => container.subscriptionRepository.getCompanySubscription(companyId),
    { deps: [companyId] }
  );

  const changePlan = useApiMutation(
    (planId: number) => container.subscriptionRepository.updateCompanyPlan(companyId, { subscription_plan_id: planId }),
    { successMessage: m.planChanged, onSuccess: () => { setPending(null); refetch(); onPlanChanged(); } }
  );
  const cancel = useApiMutation(
    () => container.subscriptionRepository.cancelCompanySubscription(companyId, { ends_at: endsAt, reason: reason.trim() || null }),
    { successMessage: m.cancelled, onSuccess: () => { setCancelOpen(false); setReason(""); refetch(); } }
  );
  const undo = useApiMutation(
    () => container.subscriptionRepository.undoCompanyCancellation(companyId),
    { successMessage: m.undone, onSuccess: () => refetch() }
  );

  // Picking a plan shows what the change costs before anything is saved.
  const pick = async (planId: string) => {
    const plan = plans.find((p) => String(p.id) === planId);
    if (!plan || plan.id === currentPlan?.id) return;
    setPreviewing(true);
    try {
      setPending({ plan, preview: await container.subscriptionRepository.previewCompanyPlan(companyId, plan.id) });
    } catch (err) {
      const message = (err as { response?: { data?: { message?: string } } }).response?.data?.message;
      toast.error(message || "Une erreur est survenue");
    } finally {
      setPreviewing(false);
    }
  };

  const adjustment = pending?.preview.adjustment;
  const cancellation = state?.cancellation;
  // The 15-day trial of Fleet Business under way (2026-09-29); once over, the history tells it.
  const trial = state?.trial?.running ? state.trial : null;
  const brand = trial?.card?.brand ? trial.card.brand.charAt(0).toUpperCase() + trial.card.brand.slice(1) : "";

  return (
    <div className="space-y-3 rounded-lg border p-4">
      <div className="flex flex-wrap items-center gap-3">
        <span className="text-sm font-semibold">{m.title}</span>
        <Select value={currentPlan ? String(currentPlan.id) : ""} onValueChange={pick} disabled={previewing || changePlan.loading}>
          <SelectTrigger className="w-80"><SelectValue placeholder={t.entitlements.noPlan} /></SelectTrigger>
          <SelectContent>
            {/* Monthly and yearly plans share their names: the frequency tells them apart. */}
            {plans.map((p) => (
              <SelectItem key={p.id} value={String(p.id)}>
                {p.display_name || p.name}{p.billing_frequency in m.frequencies ? ` · ${m.frequencies[p.billing_frequency as keyof typeof m.frequencies]}` : ""}
              </SelectItem>
            ))}
            {currentPlan && !plans.some((p) => p.id === currentPlan.id) && (
              <SelectItem value={String(currentPlan.id)}>{currentPlan.name}</SelectItem>
            )}
          </SelectContent>
        </Select>
        {previewing && <Loader2 className="w-4 h-4 animate-spin" />}
        <div className="ml-auto flex gap-2">
          {cancellation && !cancellation.ended ? (
            <Button variant="outline" size="sm" onClick={() => undo.mutate(undefined)} disabled={undo.loading}>{m.undo}</Button>
          ) : !cancellation && (
            <Button variant="outline" size="sm" onClick={() => { setEndsAt(endOfMonth()); setCancelOpen(true); }}>{m.cancel}</Button>
          )}
        </div>
      </div>

      {loading && !state ? (
        <div className="flex justify-center py-4"><Loader2 className="w-5 h-5 animate-spin" /></div>
      ) : state && (
        <>
          <p className="text-sm text-muted-foreground">
            {cancellation
              ? cancellation.ended
                ? m.endedOn(calendarDay(cancellation.ends_on))
                : m.endsOn(calendarDay(cancellation.ends_on), m.sources[cancellation.source])
              : m.noCancellation}
            {cancellation?.reason ? ` ${m.reason} : ${cancellation.reason}` : ""}
          </p>
          {trial && (
            <p className="text-sm text-muted-foreground">
              {trial.stopped
                ? m.trialStopped(calendarDay(trial.ends_on))
                : m.trialRunning(currentPlan?.name ?? "Fleet Business", calendarDay(trial.ends_on),
                  trial.method === "card" && trial.card ? m.trialCard(brand, trial.card.last_four) : m.trialSepa)}
            </p>
          )}

          {state.pending_adjustments.length > 0 && (
            <div>
              <div className="text-sm font-medium mb-1">{m.pending}</div>
              {state.pending_adjustments.map((a) => (
                <div key={a.id} className="flex justify-between gap-3 text-sm">
                  <span className="text-muted-foreground">{a.label}</span>
                  <span className="whitespace-nowrap font-medium">{a.amount_ht > 0 ? "+" : "−"}{euros(Math.abs(a.amount_ht))} HT</span>
                </div>
              ))}
            </div>
          )}

          <div>
            <div className="text-sm font-medium mb-1">{m.history}</div>
            {state.history.length === 0 ? (
              <p className="text-sm text-muted-foreground">{m.empty}</p>
            ) : (
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{m.date}</TableHead>
                    <TableHead>{m.event}</TableHead>
                    <TableHead>{m.by}</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {state.history.map((h) => (
                    <TableRow key={h.id}>
                      <TableCell className="whitespace-nowrap">{h.created_at ? day(h.created_at) : "—"}</TableCell>
                      {/* Wraps: a vehicle plans change or a reason can be long, and must not push "Par" out. */}
                      <TableCell className="whitespace-normal">
                        <div>
                          {m.kinds[h.kind]}
                          {h.kind === "plan_change" && ` : ${h.from_plan ?? "—"} → ${h.to_plan ?? "—"}`}
                          {h.kind === "cancellation" && ` : ${calendarDay(h.effective_on)}`}
                          {h.kind === "vehicle_plans" && h.detail && ` : ${h.detail}`}
                          {h.kind === "trial_started" && ` : ${h.to_plan ?? "—"} ${m.trialUntil(calendarDay(h.effective_on))}`}
                          {(h.kind === "trial_stopped" || h.kind === "trial_resumed") && ` (${m.trialEndsOn(calendarDay(h.effective_on))})`}
                        </div>
                        {h.reason && <div className="text-xs text-muted-foreground">{h.reason}</div>}
                        {h.adjustments.map((a, i) => (
                          <div key={i} className="text-xs text-muted-foreground">
                            {a.amount_ht > 0 ? "+" : "−"}{euros(Math.abs(a.amount_ht))} HT{a.invoiced ? ` (${m.invoiced})` : ""}
                          </div>
                        ))}
                      </TableCell>
                      <TableCell className="whitespace-nowrap">{h.by ?? m.sources[h.source]}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            )}
          </div>
        </>
      )}

      <Dialog open={!!pending} onOpenChange={(open) => { if (!open) setPending(null); }}>
        <DialogContent>
          <DialogHeader><DialogTitle>{pending ? m.confirmPlanTitle(pending.plan.display_name || pending.plan.name) : ""}</DialogTitle></DialogHeader>
          {pending && (
            <div className="space-y-2 text-sm">
              <p className="text-muted-foreground">{m.appliesNow}</p>
              <p>
                {adjustment
                  ? adjustment.amount_ht > 0
                    ? m.supplement(euros(adjustment.amount_ht), adjustment.vehicles, adjustment.days, adjustment.days_in_month)
                    : m.credit(euros(-adjustment.amount_ht), adjustment.vehicles, adjustment.days, adjustment.days_in_month)
                  : m.noAdjustment}
              </p>
              <p>
                {pending.preview.next_month.vehicle_plans
                  ? m.nextMonthVehiclePlans(pending.preview.next_month.vehicles_count, euros(pending.preview.next_month.amount_ht))
                  : m.nextMonth(pending.preview.next_month.vehicles_count, euros(pending.preview.next_month.amount_ht))}
              </p>
              <div className="flex justify-end gap-2 pt-2">
                <Button variant="outline" onClick={() => setPending(null)}>{t.entitlements.cancel}</Button>
                <Button onClick={() => changePlan.mutate(pending.plan.id)} disabled={changePlan.loading}>{m.confirmChange}</Button>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>

      <Dialog open={cancelOpen} onOpenChange={setCancelOpen}>
        <DialogContent>
          <DialogHeader><DialogTitle>{m.cancelTitle}</DialogTitle></DialogHeader>
          <div className="space-y-3 text-sm">
            <p className="text-muted-foreground">{m.cancelHint}</p>
            <label className="block space-y-1">
              <span className="font-medium">{m.endDate}</span>
              <Input type="date" value={endsAt} onChange={(e) => setEndsAt(e.target.value)} />
            </label>
            <Textarea placeholder={m.reasonPlaceholder} value={reason} onChange={(e) => setReason(e.target.value)} />
            <div className="flex justify-end gap-2">
              <Button variant="outline" onClick={() => setCancelOpen(false)}>{m.close}</Button>
              <Button variant="destructive" onClick={() => cancel.mutate(undefined)} disabled={cancel.loading || !endsAt}>{m.confirmCancel}</Button>
            </div>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
