"use client";

import clsx from "clsx";
import { useState } from "react";
import { Check, Layers, Pencil, Plus } from "lucide-react";
import { Badge, Button, Dialog, EmptyState, Field, Input, PageHeader, Panel, Select, Skeleton } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { useSession } from "@/components/session";
import { limitText } from "@/components/billing/plan-badge";
import { api, ApiError } from "@/lib/api";
import { formatPaise, paiseToInput } from "@/lib/format";
import { useApi } from "@/lib/use-api";
import type { Plan } from "@/lib/types";

type Form = {
  code: string;
  name: string;
  description: string;
  price: string;
  interval: "month" | "year";
  trial_days: string;
  numbers: string;
  team: string;
  contacts: string;
  campaigns: boolean;
  bot_flows: boolean;
  api_access: boolean;
  is_active: boolean;
  is_default: boolean;
  sort: string;
};

const toForm = (p?: Plan): Form => ({
  code: p?.code ?? "",
  name: p?.name ?? "",
  description: p?.description ?? "",
  price: p ? paiseToInput(p.list_price_paise) : "",
  interval: p?.interval ?? "month",
  trial_days: String(p?.trial_days ?? 0),
  numbers: p?.limits.whatsapp_numbers === null || !p ? "" : String(p.limits.whatsapp_numbers),
  team: p?.limits.team_members === null || !p ? "" : String(p.limits.team_members),
  contacts: p?.limits.contacts === null || !p ? "" : String(p.limits.contacts),
  campaigns: p?.features.campaigns ?? true,
  bot_flows: p?.features.bot_flows ?? false,
  api_access: p?.features.api_access ?? false,
  is_active: p?.is_active ?? true,
  is_default: p?.is_default ?? false,
  sort: String(p?.sort ?? 0),
});

function PlanDialog({ plan, onClose, onDone }: { plan?: Plan; onClose: () => void; onDone: () => void }) {
  const toast = useToast();
  const [f, setF] = useState<Form>(() => toForm(plan));
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [busy, setBusy] = useState(false);
  const set = (k: keyof Form) => (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => setF({ ...f, [k]: e.target.type === "checkbox" ? (e.target as HTMLInputElement).checked : e.target.value });
  async function save() {
    setBusy(true);
    setErrors({});
    const body = {
      code: f.code,
      name: f.name,
      description: f.description || null,
      price: f.price,
      interval: f.interval,
      trial_days: Number(f.trial_days || 0),
      limits: { whatsapp_numbers: f.numbers, team_members: f.team, contacts: f.contacts },
      features: { campaigns: f.campaigns, bot_flows: f.bot_flows, api_access: f.api_access },
      is_active: f.is_active,
      is_default: f.is_default,
      sort: Number(f.sort || 0),
    };
    try {
      if (plan) await api.patch(`/admin/plans/${plan.id}`, body);
      else await api.post("/admin/plans", body);
      toast("success", plan ? "Plan saved" : "Plan created");
      onDone();
    } catch (e) {
      if (e instanceof ApiError && Object.keys(e.fields).length) setErrors(e.fields);
      else toast("error", (e as Error).message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <Dialog
      open
      onClose={onClose}
      size="lg"
      title={plan ? `Edit ${plan.name}` : "New plan"}
      description="Existing subscribers keep the price they signed up at until they change plan. Limits and features apply straight away."
      footer={
        <>
          <Button onClick={onClose}>Cancel</Button>
          <Button variant="primary" loading={busy} onClick={save}>
            {plan ? "Save plan" : "Create plan"}
          </Button>
        </>
      }
    >
      <div className="grid gap-4 sm:grid-cols-3">
        <Field label="Name" htmlFor="pl-name" error={errors.name}>
          <Input id="pl-name" value={f.name} onChange={set("name")} invalid={!!errors.name} />
        </Field>
        <Field label="Code" htmlFor="pl-code" error={errors.code} hint="Stable id, e.g. growth">
          <Input id="pl-code" value={f.code} onChange={set("code")} invalid={!!errors.code} />
        </Field>
        <Field label="Order" htmlFor="pl-sort">
          <Input id="pl-sort" inputMode="numeric" value={f.sort} onChange={set("sort")} />
        </Field>
        <div className="sm:col-span-3">
          <Field label="Description" htmlFor="pl-desc" optional>
            <Input id="pl-desc" value={f.description} onChange={set("description")} />
          </Field>
        </div>
        <Field label="Price (₹, before GST)" htmlFor="pl-price" error={errors.price}>
          <Input id="pl-price" inputMode="decimal" value={f.price} onChange={set("price")} invalid={!!errors.price} />
        </Field>
        <Field label="Billed every" htmlFor="pl-int">
          <Select id="pl-int" value={f.interval} onChange={set("interval")}>
            <option value="month">Month</option>
            <option value="year">Year</option>
          </Select>
        </Field>
        <Field label="Trial days" htmlFor="pl-trial" error={errors.trial_days}>
          <Input id="pl-trial" inputMode="numeric" value={f.trial_days} onChange={set("trial_days")} invalid={!!errors.trial_days} />
        </Field>
        <Field label="WhatsApp numbers" htmlFor="pl-num" hint="Empty = unlimited" error={errors["limits.whatsapp_numbers"]}>
          <Input id="pl-num" inputMode="numeric" value={f.numbers} onChange={set("numbers")} />
        </Field>
        <Field label="Team members" htmlFor="pl-team" hint="Empty = unlimited" error={errors["limits.team_members"]}>
          <Input id="pl-team" inputMode="numeric" value={f.team} onChange={set("team")} />
        </Field>
        <Field label="Contacts" htmlFor="pl-contacts" hint="Empty = unlimited" error={errors["limits.contacts"]}>
          <Input id="pl-contacts" inputMode="numeric" value={f.contacts} onChange={set("contacts")} />
        </Field>
        <fieldset className="space-y-2 sm:col-span-3">
          <legend className="mb-1 text-[13px] font-medium">Included</legend>
          {(
            [
              ["campaigns", "Campaigns"],
              ["bot_flows", "Bot flows"],
              ["api_access", "API access"],
              ["is_active", "Available to customers"],
              ["is_default", "Sign-up plan (new customers start a trial of it)"],
            ] as const
          ).map(([k, l]) => (
            <label key={k} className="flex items-center gap-2 text-sm">
              <input type="checkbox" className="size-4 accent-teal" checked={f[k]} onChange={set(k)} />
              {l}
            </label>
          ))}
        </fieldset>
      </div>
    </Dialog>
  );
}

export default function AdminPlansPage() {
  const { can } = useSession();
  const { data, reload } = useApi<{ data: Plan[] }>("/admin/plans");
  const [editing, setEditing] = useState<Plan | "new" | null>(null);
  const manage = can("platform.plans.manage");
  return (
    <>
      <PageHeader
        title="Plans"
        description="Subscription plans, their limits and features. Resellers can resell them within their allowed markup."
        actions={
          manage && (
            <Button variant="primary" icon={<Plus className="size-4" />} onClick={() => setEditing("new")}>
              New plan
            </Button>
          )
        }
      />
      {!data ? (
        <Skeleton className="h-48" />
      ) : data.data.length === 0 ? (
        <Panel>
          <EmptyState icon={<Layers />} title="No plans yet" body="Until a plan exists, customers aren't billed for subscriptions and no limits apply." />
        </Panel>
      ) : (
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          {data.data.map((p) => (
            <Panel key={p.id} className={clsx("flex flex-col p-5", !p.is_active && "opacity-70")}>
              <div className="flex items-start justify-between gap-2">
                <div>
                  <h2 className="flex flex-wrap items-center gap-2 font-semibold">
                    {p.name}
                    {p.is_default && <Badge tone="amber">Sign-up trial</Badge>}
                    {!p.is_active && <Badge>Hidden</Badge>}
                  </h2>
                  <p className="text-[13px] text-muted">{p.code}</p>
                </div>
                {manage && (
                  <button onClick={() => setEditing(p)} className="rounded p-1.5 text-muted hover:bg-paper hover:text-teal" aria-label={`Edit ${p.name}`}>
                    <Pencil className="size-4" />
                  </button>
                )}
              </div>
              <p className="tabular mt-3 text-2xl font-semibold text-ink">
                {formatPaise(p.list_price_paise, { compact: true })}
                <span className="text-sm font-normal text-muted">/{p.interval}</span>
              </p>
              {p.trial_days > 0 && <p className="text-[13px] text-muted">{p.trial_days}-day trial</p>}
              <ul className="mt-3 flex-1 space-y-1 text-sm">
                <li>{limitText(p.limits.whatsapp_numbers)} numbers, {limitText(p.limits.team_members)} team, {limitText(p.limits.contacts)} contacts</li>
                {(["campaigns", "bot_flows", "api_access"] as const).map((k) => (
                  <li key={k} className={clsx("flex items-center gap-1.5", !p.features[k] && "text-muted line-through decoration-line")}>
                    <Check className={clsx("size-3.5", p.features[k] ? "text-teal" : "text-transparent")} />
                    {k === "campaigns" ? "Campaigns" : k === "bot_flows" ? "Bot flows" : "API access"}
                  </li>
                ))}
              </ul>
              <p className="mt-4 border-t border-line pt-3 text-[13px] text-muted">{p.subscribers ?? 0} subscribers</p>
            </Panel>
          ))}
        </div>
      )}
      {editing && <PlanDialog plan={editing === "new" ? undefined : editing} onClose={() => setEditing(null)} onDone={() => (setEditing(null), reload())} />}
    </>
  );
}
