"use client";

import { useMemo, useState } from "react";
import { Loader2 } from "lucide-react";
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 { Badge } from "@/presentation/components/ui/badge";
import { Dialog, DialogContent, DialogDescription, 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 { EntitlementState, PlanEntitlements, QuotaPeriod, UpdatePlanEntitlementsPayload } from "@/domain/entities/entitlement";

const STATES: EntitlementState[] = ["allow", "preview", "deny"];

type QuotaDraft = { limit: string; period: QuotaPeriod | null; remove: boolean };

/**
 * The plan's entitlements (SCRUM-353), edited from the admin platform: its default, the
 * state of each module and the ceiling of each limit. Only what changed is sent.
 */
export function PlanEntitlementsDialog({ planId, planName, open, onOpenChange }: {
  planId: number | null;
  planName: string;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const t = useT();
  const container = useRepositories();

  const { data, loading } = useApiQuery<PlanEntitlements | null>(
    () => (planId ? container.entitlementRepository.getPlan(planId) : Promise.resolve(null)),
    { deps: [planId, open], enabled: open && !!planId }
  );

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      {/* sm: too, or the base dialog's sm:max-w-lg wins and squeezes the two tables. */}
      <DialogContent className="max-w-4xl sm:max-w-4xl max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>{t.entitlements.planTitle(planName)}</DialogTitle>
          <DialogDescription>{t.entitlements.planHint}</DialogDescription>
        </DialogHeader>

        {loading || !data || data.plan.id !== planId ? (
          <div className="flex justify-center py-10"><Loader2 className="w-6 h-6 animate-spin" /></div>
        ) : (
          // Keyed on the loaded lines: a new load starts a fresh draft.
          <PlanEntitlementsForm key={JSON.stringify(data)} data={data} onDone={() => onOpenChange(false)} />
        )}
      </DialogContent>
    </Dialog>
  );
}

function PlanEntitlementsForm({ data, onDone }: { data: PlanEntitlements; onDone: () => void }) {
  const t = useT();
  const container = useRepositories();
  const [search, setSearch] = useState("");
  const [defaultState, setDefaultState] = useState<EntitlementState>(data.plan.default);
  const [states, setStates] = useState<Record<string, EntitlementState>>(
    () => Object.fromEntries(data.capabilities.map((c) => [c.key, c.state]))
  );
  const [quotas, setQuotas] = useState<Record<string, QuotaDraft>>(
    () => Object.fromEntries(data.quotas.map((q) => [q.key, {
      limit: q.limit === null ? "" : String(q.limit),
      period: q.period,
      remove: false,
    }]))
  );

  const save = useApiMutation(
    (payload: UpdatePlanEntitlementsPayload) => container.entitlementRepository.updatePlan(data.plan.id, payload),
    { successMessage: t.entitlements.saved, onSuccess: onDone }
  );

  const payload = useMemo<UpdatePlanEntitlementsPayload>(() => {
    const capabilities = data.capabilities.flatMap((c) => {
      const next = states[c.key] ?? c.state;
      if (next === c.state && c.source === "line") return [];
      if (c.source === "default" && next === defaultState) return [];
      // A line equal to the (new) default is removed: the default speaks for it.
      return [{ key: c.key, state: next === defaultState ? null : next }];
    });
    const quotaLines = data.quotas.flatMap((q): NonNullable<UpdatePlanEntitlementsPayload["quotas"]> => {
      const draft = quotas[q.key];
      if (!draft) return [];
      if (draft.remove) return q.source === "line" ? [{ key: q.key, remove: true }] : [];
      const limit = draft.limit.trim() === "" ? null : Number(draft.limit);
      const unchanged = q.source === "line" && limit === q.limit && (draft.period ?? null) === (q.period ?? null);
      const untouched = q.source === "default" && draft.limit === (q.limit === null ? "" : String(q.limit));
      return unchanged || untouched ? [] : [{ key: q.key, limit, period: q.periodic ? (draft.period ?? "lifetime") : null }];
    });
    return {
      ...(defaultState !== data.plan.default ? { default: defaultState } : {}),
      capabilities,
      quotas: quotaLines,
    };
  }, [data, states, quotas, defaultState]);

  const filter = (label: string, key: string) => !search || `${label} ${key}`.toLowerCase().includes(search.toLowerCase());

  return (
    <div className="space-y-6">
      {data.plan.unlimited && (
        <p className="text-sm rounded-md bg-amber-50 text-amber-900 p-3">{t.entitlements.unlimitedPlanNotice}</p>
      )}

      <div className="flex flex-wrap items-center gap-3">
        <span className="text-sm font-medium">{t.entitlements.defaultLabel}</span>
        <Select value={defaultState} onValueChange={(v) => setDefaultState(v as EntitlementState)}>
          <SelectTrigger className="w-44"><SelectValue /></SelectTrigger>
          <SelectContent>
            {STATES.map((s) => <SelectItem key={s} value={s}>{t.entitlements.states[s]}</SelectItem>)}
          </SelectContent>
        </Select>
        <Input className="max-w-xs ml-auto" placeholder={t.entitlements.search} value={search} onChange={(e) => setSearch(e.target.value)} />
      </div>

      <div>
        <h3 className="text-sm font-semibold mb-2">{t.entitlements.capabilities}</h3>
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>{t.entitlements.capabilities}</TableHead>
              <TableHead className="w-48">{t.entitlements.planState}</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {data.capabilities.filter((c) => filter(c.label, c.key)).map((c) => {
              const value = states[c.key] ?? c.state;
              return (
                <TableRow key={c.key}>
                  <TableCell>
                    <div className="font-medium">{c.label}</div>
                    <div className="text-xs text-muted-foreground">{c.key}{c.source === "default" ? ` · ${t.entitlements.fromDefault}` : ""}</div>
                  </TableCell>
                  <TableCell>
                    <Select value={value} onValueChange={(v) => setStates({ ...states, [c.key]: v as EntitlementState })}>
                      <SelectTrigger className="w-44"><SelectValue /></SelectTrigger>
                      <SelectContent>
                        {STATES.filter((s) => s !== "preview" || c.preview || value === "preview").map((s) => (
                          <SelectItem key={s} value={s}>{t.entitlements.states[s]}</SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </TableCell>
                </TableRow>
              );
            })}
          </TableBody>
        </Table>
      </div>

      <div>
        <h3 className="text-sm font-semibold mb-2">{t.entitlements.quotas}</h3>
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>{t.entitlements.quotas}</TableHead>
              <TableHead className="w-40">{t.entitlements.limit}</TableHead>
              <TableHead className="w-56" />
            </TableRow>
          </TableHeader>
          <TableBody>
            {data.quotas.filter((q) => filter(q.label, q.key)).map((q) => {
              const draft = quotas[q.key] ?? { limit: "", period: null, remove: false };
              return (
                <TableRow key={q.key} className={draft.remove ? "opacity-50" : ""}>
                  <TableCell>
                    <div className="font-medium">{q.label}</div>
                    <div className="text-xs text-muted-foreground">
                      {q.key}{q.source === "default" ? ` · ${t.entitlements.fromDefault}` : ""}
                    </div>
                  </TableCell>
                  <TableCell>
                    <Input type="number" min={q.counter === "setting" ? undefined : 0} placeholder={t.entitlements.unlimited}
                      value={draft.limit} disabled={draft.remove}
                      onChange={(e) => setQuotas({ ...quotas, [q.key]: { ...draft, limit: e.target.value } })} />
                  </TableCell>
                  <TableCell>
                    {/* One line: the period (or how the limit is counted), then the remove button. */}
                    <div className="flex items-center gap-1">
                      {q.periodic ? (
                        <Select value={draft.period ?? "lifetime"} disabled={draft.remove}
                          onValueChange={(v) => setQuotas({ ...quotas, [q.key]: { ...draft, period: v as QuotaPeriod } })}>
                          <SelectTrigger className="w-36"><SelectValue /></SelectTrigger>
                          <SelectContent>
                            <SelectItem value="lifetime">{t.entitlements.periods.lifetime}</SelectItem>
                            <SelectItem value="month">{t.entitlements.periods.month}</SelectItem>
                          </SelectContent>
                        </Select>
                      ) : <Badge variant="outline">{t.entitlements.counters[q.counter] ?? q.counter}</Badge>}
                      {q.source === "line" && (
                        <Button variant="ghost" size="sm"
                          onClick={() => setQuotas({ ...quotas, [q.key]: { ...draft, remove: !draft.remove } })}>
                          {draft.remove ? "↺" : "×"}
                        </Button>
                      )}
                    </div>
                  </TableCell>
                </TableRow>
              );
            })}
          </TableBody>
        </Table>
      </div>

      <div className="flex justify-end gap-2 sticky bottom-0 bg-background py-2">
        <Button variant="outline" onClick={onDone}>{t.entitlements.cancel}</Button>
        <Button onClick={() => save.mutate(payload)} disabled={save.loading}>
          {save.loading && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
          {t.entitlements.save}
        </Button>
      </div>
    </div>
  );
}
