"use client";

import clsx from "clsx";
import Link from "next/link";
import { useParams } from "next/navigation";
import { useState } from "react";
import { ArrowLeft } from "lucide-react";
import { Badge, Button, ConfirmDialog, Dialog, Field, Input, Panel, Select, Skeleton } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { useSession } from "@/components/session";
import { PAYMENT_STATUS, SubscriptionBadge } from "@/components/billing/plan-badge";
import { api, ApiError } from "@/lib/api";
import { formatDate, formatDateTime, formatPaise, ROLE_LABELS } from "@/lib/format";
import { useApi } from "@/lib/use-api";
import type { CustomerRow, Earnings, LedgerEntry, Payment, Plan } from "@/lib/types";
import { bpToPct, newKey, StatTile } from "./common";
import { RefundDialog } from "./refund-dialog";

type Detail = CustomerRow & {
  members: { id: number; name: string; email: string; role: string; last_login_at: string | null }[];
  payments: Payment[];
  ledger: LedgerEntry[];
  usage_30d: Record<string, { messages: number; estimated_paise: number; charged_paise: number }>;
  reseller: { commission_rate_bp: number; max_markup_bp: number; customers: number; earnings: Earnings } | null;
};

function PlanDialog({ id, plans, onClose, onDone }: { id: number; plans: Plan[]; onClose: () => void; onDone: () => void }) {
  const toast = useToast();
  const [planId, setPlanId] = useState(String(plans[0]?.id ?? ""));
  const [trial, setTrial] = useState("0");
  const [busy, setBusy] = useState(false);
  async function save() {
    setBusy(true);
    try {
      await api.post(`/admin/organizations/${id}/subscription`, { plan_id: Number(planId), trial_days: Number(trial) });
      toast("success", "Plan assigned");
      onDone();
    } catch (e) {
      toast("error", (e as Error).message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <Dialog
      open
      onClose={onClose}
      title="Assign plan"
      description="Starts the plan now without a payment (for trials, offline payments or corrections). With trial days it runs as a trial."
      footer={
        <>
          <Button onClick={onClose}>Cancel</Button>
          <Button variant="primary" loading={busy} onClick={save}>
            Assign
          </Button>
        </>
      }
    >
      <div className="grid gap-4 sm:grid-cols-2">
        <Field label="Plan" htmlFor="ap-plan">
          <Select id="ap-plan" value={planId} onChange={(e) => setPlanId(e.target.value)}>
            {plans.map((p) => (
              <option key={p.id} value={p.id}>
                {p.name}
              </option>
            ))}
          </Select>
        </Field>
        <Field label="Trial days" htmlFor="ap-trial" hint="0 = active for one month">
          <Input id="ap-trial" inputMode="numeric" value={trial} onChange={(e) => setTrial(e.target.value)} />
        </Field>
      </div>
    </Dialog>
  );
}

function AdjustDialog({ id, onClose, onDone }: { id: number; onClose: () => void; onDone: () => void }) {
  const toast = useToast();
  const [direction, setDirection] = useState<"credit" | "debit">("credit");
  const [amount, setAmount] = useState("");
  const [reason, setReason] = useState("");
  const [key] = useState(newKey);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [busy, setBusy] = useState(false);
  async function save() {
    setBusy(true);
    setErrors({});
    try {
      await api.post(`/admin/organizations/${id}/wallet-adjustment`, { direction, amount, reason, idempotency_key: key });
      toast("success", "Wallet adjusted");
      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}
      title="Adjust wallet"
      description="Adds an entry to the customer's ledger. Entries are permanent; correct a mistake with an opposite adjustment."
      footer={
        <>
          <Button onClick={onClose}>Cancel</Button>
          <Button variant="primary" loading={busy} onClick={save}>
            {direction === "credit" ? "Add credit" : "Deduct"}
          </Button>
        </>
      }
    >
      <div className="grid gap-4 sm:grid-cols-2">
        <Field label="Type" htmlFor="aw-dir">
          <Select id="aw-dir" value={direction} onChange={(e) => setDirection(e.target.value as "credit" | "debit")}>
            <option value="credit">Credit (add money)</option>
            <option value="debit">Debit (take money)</option>
          </Select>
        </Field>
        <Field label="Amount (₹)" htmlFor="aw-amount" error={errors.amount}>
          <Input id="aw-amount" inputMode="decimal" value={amount} onChange={(e) => setAmount(e.target.value)} invalid={!!errors.amount} />
        </Field>
        <div className="sm:col-span-2">
          <Field label="Reason" htmlFor="aw-reason" error={errors.reason}>
            <Input id="aw-reason" value={reason} onChange={(e) => setReason(e.target.value)} invalid={!!errors.reason} placeholder="e.g. Goodwill credit for delivery issue on 12 Oct" />
          </Field>
        </div>
      </div>
    </Dialog>
  );
}

export function CustomerDetail() {
  const { id } = useParams<{ id: string }>();
  const toast = useToast();
  const { can } = useSession();
  const { data, error, reload } = useApi<{ data: Detail }>(`/admin/organizations/${id}`);
  const plans = useApi<{ data: Plan[] }>("/admin/plans");
  const [dialog, setDialog] = useState<"plan" | "adjust" | "status" | null>(null);
  const [refund, setRefund] = useState<Payment | null>(null);
  const [busy, setBusy] = useState(false);
  const c = data?.data;

  async function setStatus() {
    if (!c) return;
    setBusy(true);
    try {
      await api.post(`/admin/organizations/${c.id}/status`, { status: c.status === "active" ? "suspended" : "active" });
      toast("success", c.status === "active" ? `${c.name} suspended` : `${c.name} reactivated`);
      setDialog(null);
      reload();
    } catch (e) {
      toast("error", (e as Error).message);
    } finally {
      setBusy(false);
    }
  }

  if (error) return <p className="rounded-md bg-brick-soft px-4 py-3 text-sm text-brick">{error}</p>;
  if (!c) return <Skeleton className="h-96" />;
  const usage = Object.values(c.usage_30d);
  const backHref = c.type === "reseller" ? "/admin/resellers" : "/admin/customers";
  const manage = can("platform.organizations.manage");

  return (
    <>
      <Link href={backHref} className="mb-3 inline-flex items-center gap-1.5 text-sm text-muted hover:text-teal">
        <ArrowLeft className="size-4" /> {c.type === "reseller" ? "Resellers" : "Customers"}
      </Link>
      <header className="mb-6 flex flex-col gap-4 md:flex-row md:items-start md:justify-between">
        <div>
          <h1 className="flex flex-wrap items-center gap-3 text-2xl font-semibold tracking-tight text-ink">
            {c.name} <Badge tone={c.status === "active" ? "teal" : "brick"}>{c.status === "active" ? "Active" : "Suspended"}</Badge>
          </h1>
          <p className="mt-1 text-sm text-muted">
            {c.type === "reseller" ? "Reseller" : c.reseller_name ? `Customer of ${c.reseller_name}` : "Direct customer"}, since {formatDate(c.created_at)}
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          {manage && c.type === "customer" && <Button onClick={() => setDialog("plan")}>Assign plan</Button>}
          {can("platform.billing.manage") && c.type === "customer" && <Button onClick={() => setDialog("adjust")}>Adjust wallet</Button>}
          {manage && (
            <Button variant={c.status === "active" ? "danger" : "primary"} onClick={() => setDialog("status")}>
              {c.status === "active" ? "Suspend" : "Reactivate"}
            </Button>
          )}
        </div>
      </header>

      <div className="mb-6 grid grid-cols-2 gap-3 lg:grid-cols-4">
        {c.type === "customer" ? (
          <>
            <StatTile label="Plan" value={c.subscription ? c.subscription.plan.name : "Not billed"} sub={c.subscription ? <SubscriptionBadge status={c.subscription.status} /> : undefined} />
            <StatTile label="Renews or ends" value={c.subscription ? formatDate(c.subscription.current_period_end) : "—"} />
            <StatTile label="Wallet" value={formatPaise(c.wallet_paise)} />
            <StatTile label="Template messages, 30 days" value={usage.reduce((a, u) => a + u.messages, 0).toLocaleString("en-IN")} sub={`${formatPaise(usage.reduce((a, u) => a + u.charged_paise, 0))} charged`} />
          </>
        ) : (
          c.reseller && (
            <>
              <StatTile label="Customers" value={c.reseller.customers} />
              <StatTile label="Commission" value={bpToPct(c.reseller.commission_rate_bp)} sub={`Max markup ${bpToPct(c.reseller.max_markup_bp)}`} />
              <StatTile label="Earned" value={formatPaise(c.reseller.earnings.earned)} />
              <StatTile label="Outstanding" value={formatPaise(c.reseller.earnings.outstanding)} />
            </>
          )
        )}
      </div>

      <div className="grid grid-cols-1 gap-6 xl:grid-cols-2">
        <Panel>
          <h2 className="border-b border-line px-5 py-3 font-semibold">Payments</h2>
          {c.payments.length === 0 ? (
            <p className="px-5 py-8 text-center text-sm text-muted">No payments.</p>
          ) : (
            <ul className="divide-y divide-line">
              {c.payments.map((p) => (
                <li key={p.id} className="flex items-center gap-3 px-5 py-3 text-sm">
                  <div className="min-w-0 flex-1">
                    <p className="font-medium">
                      {p.purpose === "recharge" ? "Wallet recharge" : "Plan"} <span className="tabular">{formatPaise(p.total_paise)}</span>
                    </p>
                    <p className="truncate text-[13px] text-muted">
                      {formatDateTime(p.paid_at ?? p.created_at)}, {p.provider === "wallet" ? "from wallet" : p.receipt}
                      {p.refunded_paise ? `, ${formatPaise(p.refunded_paise)} refunded` : ""}
                    </p>
                  </div>
                  <Badge tone={PAYMENT_STATUS[p.status]?.tone ?? "neutral"}>{PAYMENT_STATUS[p.status]?.label ?? p.status}</Badge>
                  {can("platform.billing.manage") && (p.status === "paid" || p.status === "partially_refunded") && p.provider !== "wallet" && (
                    <Button size="sm" variant="ghost" onClick={() => setRefund(p)}>
                      Refund
                    </Button>
                  )}
                </li>
              ))}
            </ul>
          )}
        </Panel>
        <Panel>
          <h2 className="border-b border-line px-5 py-3 font-semibold">{c.type === "customer" ? "Wallet ledger" : "Team"}</h2>
          {c.type === "customer" ? (
            c.ledger.length === 0 ? (
              <p className="px-5 py-8 text-center text-sm text-muted">No wallet entries.</p>
            ) : (
              <ul className="divide-y divide-line">
                {c.ledger.map((l) => (
                  <li key={l.id} className="flex items-center gap-3 px-5 py-3 text-sm">
                    <div className="min-w-0 flex-1">
                      <p className="truncate">{l.description}</p>
                      <p className="text-[13px] text-muted">{formatDateTime(l.created_at)}</p>
                    </div>
                    <span className={clsx("tabular font-medium", l.amount_paise > 0 && "text-teal")}>
                      {l.amount_paise > 0 ? "+" : ""}
                      {formatPaise(l.amount_paise)}
                    </span>
                  </li>
                ))}
              </ul>
            )
          ) : null}
          {c.type === "customer" && <h2 className="border-y border-line px-5 py-3 font-semibold">Team</h2>}
          <ul className="divide-y divide-line">
            {c.members.map((m) => (
              <li key={m.id} className="flex items-center gap-3 px-5 py-3 text-sm">
                <div className="min-w-0 flex-1">
                  <p className="font-medium">{m.name}</p>
                  <p className="truncate text-[13px] text-muted">{m.email}</p>
                </div>
                <span className="text-[13px] text-muted">{ROLE_LABELS[m.role] ?? m.role}</span>
              </li>
            ))}
          </ul>
        </Panel>
      </div>

      {dialog === "plan" && plans.data && <PlanDialog id={c.id} plans={plans.data.data.filter((p) => p.is_active)} onClose={() => setDialog(null)} onDone={() => (setDialog(null), reload())} />}
      {dialog === "adjust" && <AdjustDialog id={c.id} onClose={() => setDialog(null)} onDone={() => (setDialog(null), reload())} />}
      <ConfirmDialog
        open={dialog === "status"}
        title={c.status === "active" ? `Suspend ${c.name}?` : `Reactivate ${c.name}?`}
        message={c.status === "active" ? "Nobody in this workspace can use Devwebs until it is reactivated. Their data is kept." : "The workspace can be used again straight away."}
        confirmLabel={c.status === "active" ? "Suspend" : "Reactivate"}
        loading={busy}
        onConfirm={setStatus}
        onClose={() => setDialog(null)}
      />
      {refund && <RefundDialog payment={refund} onClose={() => setRefund(null)} onDone={() => (setRefund(null), reload())} />}
    </>
  );
}
