"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { Link } from "@/i18n/routing";
import { cn } from "@/lib/utils";
import {
  adminDelete,
  adminGet,
  adminPatch,
  adminPost,
  adminPut,
} from "@/lib/api/admin-client";
import type {
  AdminCafe,
  AdminNotificationRow,
  AdminPlan,
  AdminStats,
  PlanLimitsData,
  GatewayCredentials,
  PaymentGatewayConfig,
  PlatformFeature,
  PlatformIntegrations,
  PlatformSetting,
  SupportTicket,
  SupportTicketDetail,
} from "@/lib/api/admin-types";
import { CafeDiscoverProfilePanel } from "@/components/discover/cafe-discover-profile-panel";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { notify } from "@/lib/notify";
import {
  isTicketClosed,
  TicketStatusBadge,
  type TicketStatus,
} from "@/components/support/ticket-status-badge";

// iOS-style toggle switch used throughout this file
function Toggle({ checked, onChange, disabled }: { checked: boolean; onChange: (v: boolean) => void; disabled?: boolean }) {
  return (
    <button
      type="button"
      role="switch"
      dir="ltr"
      aria-checked={checked}
      disabled={disabled}
      onClick={() => onChange(!checked)}
      className={cn(
        "relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
        checked ? "bg-[#0F6E56]" : "bg-muted-foreground/30"
      )}
    >
      <span
        className={cn(
          "pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out",
          checked ? "translate-x-5" : "translate-x-0"
        )}
      />
    </button>
  );
}

// Styled single-select indicator (replaces raw <input type="radio">).
function RadioDot({
  selected,
  onSelect,
  disabled,
}: {
  selected: boolean;
  onSelect: () => void;
  disabled?: boolean;
}) {
  return (
    <button
      type="button"
      role="radio"
      aria-checked={selected}
      disabled={disabled}
      onClick={onSelect}
      className={cn(
        "relative inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
        selected ? "border-[#0F6E56]" : "border-muted-foreground/40 hover:border-muted-foreground/70"
      )}
    >
      {selected ? <span className="h-2.5 w-2.5 rounded-full bg-[#0F6E56]" /> : null}
    </button>
  );
}

export function AdminDashboardScreen() {
  const t = useTranslations("admin.dashboard");
  const { data } = useQuery({
    queryKey: ["admin", "stats"],
    queryFn: () => adminGet<AdminStats>("/api/admin/dashboard/stats"),
  });

  const stats = data ?? {
    totalCafes: 0,
    activeCafes: 0,
    suspendedCafes: 0,
    openTickets: 0,
    plansConfigured: 0,
  };

  return (
    <div className="space-y-4">
      <h1 className="text-lg font-medium">{t("title")}</h1>
      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
        <StatCard label={t("totalCafes")} value={stats.totalCafes} />
        <StatCard label={t("activeCafes")} value={stats.activeCafes} />
        <StatCard label={t("openTickets")} value={stats.openTickets} />
        <StatCard label={t("plans")} value={stats.plansConfigured} />
      </div>
    </div>
  );
}

function StatCard({ label, value }: { label: string; value: number }) {
  return (
    <Card className="rounded-xl border border-border/80">
      <CardContent className="pt-4">
        <p className="text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
          {label}
        </p>
        <p className="mt-1 text-2xl font-semibold text-primary">{value.toLocaleString("fa-IR")}</p>
      </CardContent>
    </Card>
  );
}

const PLAN_UNLIMITED = 2147483647;

const LIMIT_FIELDS: { key: keyof PlanLimitsData; label: string }[] = [
  { key: "maxOrdersPerDay", label: "maxOrders" },
  { key: "maxTables", label: "maxTables" },
  { key: "maxTerminals", label: "maxTerminals" },
  { key: "maxBranches", label: "maxBranches" },
  { key: "maxMenuCategories", label: "maxCategories" },
  { key: "maxMenuItems", label: "maxItems" },
  { key: "maxCustomers", label: "maxCustomers" },
  { key: "maxReportHistoryDays", label: "maxReportDays" },
  // No SMS limit — marketing SMS is bring-your-own-provider per café.
  { key: "maxMenuAi3dPerMonth", label: "maxAi3d" },
];

function LimitField({ label, value, onChange }: { label: string; value: number; onChange: (n: number) => void }) {
  const unlimited = value >= PLAN_UNLIMITED;
  return (
    <div className="rounded-lg border border-border/70 p-2">
      <div className="flex items-center justify-between gap-2">
        <span className="text-xs font-medium">{label}</span>
        <label className="flex items-center gap-1 text-[11px] text-muted-foreground">
          <input type="checkbox" checked={unlimited} onChange={(e) => onChange(e.target.checked ? PLAN_UNLIMITED : 0)} />∞
        </label>
      </div>
      <Input
        type="number"
        className="mt-1 h-8 text-sm"
        disabled={unlimited}
        value={unlimited ? "" : value}
        onChange={(e) => onChange(Math.max(0, Number(e.target.value)))}
      />
    </div>
  );
}

function PlanCard({
  plan,
  features,
  onSave,
  saving,
}: {
  plan: AdminPlan;
  features: PlatformFeature[];
  onSave: (p: AdminPlan) => void;
  saving: boolean;
}) {
  const t = useTranslations("admin.plans");
  const [draft, setDraft] = useState<AdminPlan>(plan);
  // Re-sync from server after a save/refetch.
  useEffect(() => { setDraft(plan); }, [plan]);

  const setField = <K extends keyof AdminPlan>(k: K, v: AdminPlan[K]) =>
    setDraft((d) => ({ ...d, [k]: v }));
  const setLimit = (k: keyof PlanLimitsData, v: number) =>
    setDraft((d) => ({ ...d, limits: { ...d.limits, [k]: v } }));

  const wildcard = draft.featureKeys.includes("*");
  const toggleFeature = (key: string, on: boolean) =>
    setDraft((d) => {
      const set = new Set(d.featureKeys.filter((k) => k !== "*"));
      if (on) set.add(key);
      else set.delete(key);
      return { ...d, featureKeys: Array.from(set) };
    });

  const groups = Array.from(new Set(features.map((f) => f.moduleGroup)));

  return (
    <Card className="rounded-xl border border-border/80">
      <CardHeader className="flex flex-row items-center justify-between gap-2 pb-2">
        <div>
          <CardTitle className="text-base">{draft.displayNameFa || draft.tier}</CardTitle>
          <p className="text-xs text-muted-foreground">{draft.tier}</p>
        </div>
        <label className="flex items-center gap-1.5 text-xs">
          <input type="checkbox" checked={draft.isActive} onChange={(e) => setField("isActive", e.target.checked)} />
          {t("active")}
        </label>
      </CardHeader>
      <CardContent className="space-y-4">
        <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
          <label className="text-sm">
            {t("nameFa")}
            <Input className="mt-1 h-8" value={draft.displayNameFa} onChange={(e) => setField("displayNameFa", e.target.value)} dir="rtl" />
          </label>
          <label className="text-sm">
            {t("nameEn")}
            <Input className="mt-1 h-8" value={draft.displayNameEn ?? ""} onChange={(e) => setField("displayNameEn", e.target.value)} dir="ltr" />
          </label>
          <label className="text-sm">
            {t("monthlyPrice")}
            <Input type="number" className="mt-1 h-8" value={draft.monthlyPriceToman} onChange={(e) => setField("monthlyPriceToman", Number(e.target.value))} />
          </label>
          <label className="text-sm">
            {t("sortOrder")}
            <Input type="number" className="mt-1 h-8" value={draft.sortOrder} onChange={(e) => setField("sortOrder", Number(e.target.value))} />
          </label>
        </div>

        <label className="flex w-fit items-center gap-1.5 text-xs">
          <input type="checkbox" checked={draft.isBillableOnline} onChange={(e) => setField("isBillableOnline", e.target.checked)} />
          {t("billable")}
        </label>

        <div>
          <p className="mb-2 text-xs font-semibold text-muted-foreground">{t("limitsTitle")}</p>
          <div className="grid gap-2 sm:grid-cols-3 lg:grid-cols-5">
            {LIMIT_FIELDS.map((f) => (
              <LimitField key={f.key} label={t(`limits.${f.label}`)} value={draft.limits[f.key] ?? PLAN_UNLIMITED} onChange={(v) => setLimit(f.key, v)} />
            ))}
          </div>
        </div>

        <div>
          <div className="mb-2 flex items-center justify-between">
            <p className="text-xs font-semibold text-muted-foreground">{t("featuresTitle")}</p>
            <label className="flex items-center gap-1.5 text-xs">
              <input type="checkbox" checked={wildcard} onChange={(e) => setField("featureKeys", e.target.checked ? ["*"] : [])} />
              {t("allFeatures")}
            </label>
          </div>
          {wildcard ? (
            <p className="text-xs text-muted-foreground">{t("allFeaturesNote")}</p>
          ) : (
            <div className="space-y-3">
              {groups.map((g) => (
                <div key={g}>
                  <p className="mb-1 text-[11px] uppercase tracking-wide text-muted-foreground">{g}</p>
                  <div className="grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3">
                    {features
                      .filter((f) => f.moduleGroup === g)
                      .map((f) => (
                        <label
                          key={f.key}
                          className={cn(
                            "flex items-center gap-2 rounded-md border border-border/60 px-2 py-1.5 text-sm",
                            !f.isEnabledGlobally && "opacity-50"
                          )}
                        >
                          <input type="checkbox" checked={draft.featureKeys.includes(f.key)} onChange={(e) => toggleFeature(f.key, e.target.checked)} />
                          <span className="truncate">{f.displayNameFa}</span>
                        </label>
                      ))}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="flex justify-end">
          <button
            type="button"
            onClick={() => onSave(draft)}
            disabled={saving}
            className="rounded-lg bg-primary px-4 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50"
          >
            {t("save")}
          </button>
        </div>
      </CardContent>
    </Card>
  );
}

export function AdminPlansScreen() {
  const t = useTranslations("admin.plans");
  const qc = useQueryClient();
  const { data: plans = [] } = useQuery({
    queryKey: ["admin", "plans"],
    queryFn: () => adminGet<AdminPlan[]>("/api/admin/plans"),
  });
  const { data: features = [] } = useQuery({
    queryKey: ["admin", "features"],
    queryFn: () => adminGet<PlatformFeature[]>("/api/admin/features"),
  });

  const save = useMutation({
    mutationFn: (plan: AdminPlan) =>
      adminPut<AdminPlan>(`/api/admin/plans/${plan.tier}`, {
        displayNameFa: plan.displayNameFa,
        displayNameEn: plan.displayNameEn,
        monthlyPriceToman: plan.monthlyPriceToman,
        isBillableOnline: plan.isBillableOnline,
        isActive: plan.isActive,
        sortOrder: plan.sortOrder,
        limits: plan.limits,
        featureKeys: plan.featureKeys,
      }),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ["admin", "plans"] });
      notify.success(t("saved"));
    },
  });

  const ordered = [...plans].sort((a, b) => a.sortOrder - b.sortOrder);

  return (
    <div className="space-y-4">
      <h1 className="text-lg font-medium">{t("title")}</h1>
      {ordered.map((plan) => (
        <PlanCard
          key={plan.tier}
          plan={plan}
          features={features}
          onSave={(p) => save.mutate(p)}
          saving={save.isPending}
        />
      ))}
    </div>
  );
}

export function AdminSettingsScreen() {
  const t = useTranslations("admin.settings");
  const qc = useQueryClient();
  const { data: settings = [] } = useQuery({
    queryKey: ["admin", "settings"],
    queryFn: () => adminGet<PlatformSetting[]>("/api/admin/settings"),
  });

  const save = useMutation({
    mutationFn: ({ key, value }: { key: string; value: string }) =>
      adminPatch(`/api/admin/settings/${encodeURIComponent(key)}`, { value }),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ["admin", "settings"] });
      notify.success(t("saved"));
    },
  });

  return (
    <div className="space-y-4">
      <h1 className="text-lg font-medium">{t("title")}</h1>
      <div className="space-y-2">
        {settings.map((s) => {
          const isBool = s.value === "true" || s.value === "false";
          return (
            <Card key={s.id} className="rounded-xl border border-border/80 p-4">
              <div className={isBool ? "flex items-center justify-between gap-3" : undefined}>
                <div className="min-w-0">
                  <p className="text-sm font-medium text-foreground">{s.key}</p>
                  {s.descriptionFa ? (
                    <p className="text-[11px] text-muted-foreground">{s.descriptionFa}</p>
                  ) : null}
                </div>
                {isBool ? (
                  <Toggle
                    checked={s.value === "true"}
                    onChange={(v) => save.mutate({ key: s.key, value: String(v) })}
                    disabled={save.isPending}
                  />
                ) : (
                  <Input
                    className="mt-2"
                    defaultValue={s.value}
                    onBlur={(e) => save.mutate({ key: s.key, value: e.target.value })}
                  />
                )}
              </div>
            </Card>
          );
        })}
      </div>
    </div>
  );
}

export function AdminFeaturesScreen() {
  const t = useTranslations("admin.features");
  const qc = useQueryClient();
  const { data: features = [] } = useQuery({
    queryKey: ["admin", "features"],
    queryFn: () => adminGet<PlatformFeature[]>("/api/admin/features"),
  });

  const toggle = useMutation({
    mutationFn: (f: PlatformFeature) =>
      adminPatch(`/api/admin/features/${f.key}`, {
        displayNameFa: f.displayNameFa,
        displayNameEn: f.displayNameEn,
        moduleGroup: f.moduleGroup,
        isEnabledGlobally: !f.isEnabledGlobally,
      }),
    onSuccess: () => void qc.invalidateQueries({ queryKey: ["admin", "features"] }),
  });

  return (
    <div className="space-y-4">
      <h1 className="text-lg font-medium">{t("title")}</h1>
      <div className="grid gap-2 sm:grid-cols-2">
        {features.map((f) => (
          <Card key={f.id} className="flex items-center justify-between rounded-xl border p-3">
            <div>
              <p className="text-sm font-medium">{f.displayNameFa}</p>
              <p className="text-xs text-muted-foreground">{f.key}</p>
            </div>
            <Button
              size="sm"
              variant={f.isEnabledGlobally ? "default" : "outline"}
              onClick={() => toggle.mutate(f)}
            >
              {f.isEnabledGlobally ? t("enabled") : t("disabled")}
            </Button>
          </Card>
        ))}
      </div>
    </div>
  );
}

export function AdminCafesScreen() {
  const t = useTranslations("admin.cafes");
  const qc = useQueryClient();
  const [profileCafeId, setProfileCafeId] = useState<string | null>(null);
  const { data: cafes = [] } = useQuery({
    queryKey: ["admin", "cafes"],
    queryFn: () => adminGet<AdminCafe[]>("/api/admin/cafes"),
  });

  const patch = useMutation({
    mutationFn: ({ id, isSuspended }: { id: string; isSuspended: boolean }) =>
      adminPatch(`/api/admin/cafes/${id}`, { isSuspended }),
    onSuccess: () => void qc.invalidateQueries({ queryKey: ["admin", "cafes"] }),
  });

  return (
    <div className="space-y-4">
      <h1 className="text-lg font-medium">{t("title")}</h1>
      <div className="space-y-2">
        {cafes.map((c) => (
          <Card key={c.id} className="rounded-xl border p-4 space-y-3">
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div>
                <p className="font-medium">{c.name}</p>
                <p className="text-xs text-muted-foreground">
                  {c.slug} · {c.planTier}
                  {c.isSuspended ? (
                    <Badge variant="outline" className="ms-2 border-destructive text-destructive">
                      {t("suspended")}
                    </Badge>
                  ) : null}
                </p>
              </div>
              <div className="flex flex-wrap gap-2">
                <Button
                  size="sm"
                  variant={profileCafeId === c.id ? "secondary" : "outline"}
                  onClick={() => setProfileCafeId(profileCafeId === c.id ? null : c.id)}
                >
                  {t("discoverProfile.edit")}
                </Button>
                <Button
                  size="sm"
                  variant={c.isSuspended ? "default" : "outline"}
                  onClick={() => patch.mutate({ id: c.id, isSuspended: !c.isSuspended })}
                >
                  {c.isSuspended ? t("activate") : t("suspend")}
                </Button>
              </div>
            </div>
            <RecoveryKeyPanel cafe={c} />
            {profileCafeId === c.id ? (
              <CafeDiscoverProfilePanel cafeId={c.id} mode="admin" compact />
            ) : null}
          </Card>
        ))}
      </div>
    </div>
  );
}

/**
 * Generate / revoke a café's permanent recovery key. The raw key is returned
 * once on generate — shown here for copy, never retrievable again.
 */
function RecoveryKeyPanel({ cafe }: { cafe: AdminCafe }) {
  const t = useTranslations("admin.cafes.recoveryKey");
  const qc = useQueryClient();
  const [revealed, setRevealed] = useState<string | null>(null);
  const [copied, setCopied] = useState(false);

  const generate = useMutation({
    mutationFn: () => adminPost<{ cafeId: string; key: string }>(`/api/admin/cafes/${cafe.id}/recovery-key`),
    onSuccess: (data) => {
      setRevealed(data.key);
      setCopied(false);
      void qc.invalidateQueries({ queryKey: ["admin", "cafes"] });
    },
    onError: () => notify.error(t("generateFailed")),
  });

  const revoke = useMutation({
    mutationFn: () => adminDelete(`/api/admin/cafes/${cafe.id}/recovery-key`),
    onSuccess: () => {
      setRevealed(null);
      notify.success(t("revoked"));
      void qc.invalidateQueries({ queryKey: ["admin", "cafes"] });
    },
    onError: () => notify.error(t("revokeFailed")),
  });

  const copy = async () => {
    if (!revealed) return;
    try {
      await navigator.clipboard.writeText(revealed);
      setCopied(true);
    } catch {
      /* clipboard blocked — user can still select the text */
    }
  };

  return (
    <div className="rounded-lg border border-border/70 bg-muted/20 p-3 text-sm">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <div>
          <p className="font-medium">{t("title")}</p>
          <p className="text-xs text-muted-foreground">
            {cafe.hasRecoveryKey ? t("active") : t("none")}
            {cafe.hasRecoveryKey && cafe.recoveryKeyCreatedAt
              ? ` · ${new Date(cafe.recoveryKeyCreatedAt).toLocaleDateString("fa-IR")}`
              : ""}
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          <Button size="sm" variant="outline" onClick={() => generate.mutate()} disabled={generate.isPending}>
            {cafe.hasRecoveryKey ? t("regenerate") : t("generate")}
          </Button>
          {cafe.hasRecoveryKey ? (
            <Button
              size="sm"
              variant="outline"
              className="border-destructive text-destructive hover:bg-destructive/10"
              onClick={() => revoke.mutate()}
              disabled={revoke.isPending}
            >
              {t("revoke")}
            </Button>
          ) : null}
        </div>
      </div>

      {revealed ? (
        <div className="mt-3 space-y-2 rounded-lg border border-primary/30 bg-primary/5 p-3">
          <p className="text-xs font-medium text-primary">{t("revealHint")}</p>
          <div className="flex items-center gap-2">
            <code className="flex-1 select-all rounded bg-background px-3 py-2 font-mono text-base tracking-wider" dir="ltr">
              {revealed}
            </code>
            <Button size="sm" onClick={() => void copy()}>
              {copied ? t("copied") : t("copy")}
            </Button>
          </div>
        </div>
      ) : null}
    </div>
  );
}

export function AdminTicketsScreen() {
  const t = useTranslations("admin.tickets");
  const [filter, setFilter] = useState<"all" | "open" | "closed">("all");

  const { data: tickets = [], isLoading } = useQuery({
    queryKey: ["admin", "tickets"],
    queryFn: () => adminGet<SupportTicket[]>("/api/admin/tickets"),
  });

  const visible =
    filter === "all"
      ? tickets
      : filter === "open"
        ? tickets.filter((x) => !isTicketClosed(x.status as TicketStatus))
        : tickets.filter((x) => isTicketClosed(x.status as TicketStatus));

  return (
    <div className="space-y-4">
      <h1 className="text-lg font-medium">{t("title")}</h1>
      <div className="flex flex-wrap gap-2">
        {(["all", "open", "closed"] as const).map((key) => (
          <Button
            key={key}
            size="sm"
            variant={filter === key ? "default" : "outline"}
            onClick={() => setFilter(key)}
          >
            {t(`filter.${key}`)}
          </Button>
        ))}
      </div>
      {isLoading ? (
        <p className="text-sm text-muted-foreground">{t("loading")}</p>
      ) : visible.length === 0 ? (
        <Card className="rounded-xl border border-dashed p-8 text-center text-sm text-muted-foreground">
          {t("empty")}
        </Card>
      ) : (
        <div className="space-y-2">
          {visible.map((ticket) => (
            <Link key={ticket.id} href={`/admin/tickets/${ticket.id}`}>
              <Card className="rounded-xl border p-4 transition hover:border-primary">
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <p className="font-medium">{ticket.subject}</p>
                  <TicketStatusBadge status={ticket.status as TicketStatus} />
                </div>
                <p className="mt-2 text-xs text-muted-foreground">
                  {ticket.cafeName} · {ticket.messageCount} {t("messages")}
                </p>
              </Card>
            </Link>
          ))}
        </div>
      )}
    </div>
  );
}

export function AdminTicketDetailScreen() {
  const t = useTranslations("admin.tickets");
  const params = useParams();
  const ticketId = params.ticketId as string;
  const qc = useQueryClient();
  const [reply, setReply] = useState("");

  const { data, isLoading } = useQuery({
    queryKey: ["admin", "ticket", ticketId],
    queryFn: () => adminGet<SupportTicketDetail>(`/api/admin/tickets/${ticketId}`),
  });

  const closed = data ? isTicketClosed(data.ticket.status as TicketStatus) : false;

  const sendReply = useMutation({
    mutationFn: () =>
      adminPost<SupportTicketDetail>(`/api/admin/tickets/${ticketId}/messages`, {
        body: reply,
      }),
    onSuccess: () => {
      setReply("");
      void qc.invalidateQueries({ queryKey: ["admin", "ticket", ticketId] });
      void qc.invalidateQueries({ queryKey: ["admin", "tickets"] });
      notify.success(t("replySent"));
    },
    onError: () => notify.error(t("replyFailed")),
  });

  const setStatus = useMutation({
    mutationFn: (status: "Resolved" | "Closed") =>
      adminPatch<SupportTicketDetail>(`/api/admin/tickets/${ticketId}`, { status }),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ["admin", "ticket", ticketId] });
      void qc.invalidateQueries({ queryKey: ["admin", "tickets"] });
      notify.success(t("statusUpdated"));
    },
  });

  if (isLoading) return <p className="text-sm text-muted-foreground">{t("loading")}</p>;
  if (!data) return <p className="text-sm text-muted-foreground">{t("notFound")}</p>;

  return (
    <div className="mx-auto max-w-2xl space-y-4">
      <Link href="/admin/tickets" className="text-sm text-primary">
        ← {t("back")}
      </Link>
      <Card className="rounded-xl border p-4">
        <div className="flex flex-wrap items-start justify-between gap-2">
          <div>
            <h1 className="text-lg font-medium">{data.ticket.subject}</h1>
            <p className="text-sm text-muted-foreground">{data.ticket.cafeName}</p>
          </div>
          <TicketStatusBadge status={data.ticket.status as TicketStatus} />
        </div>
        {!closed ? (
          <div className="mt-4 flex flex-wrap gap-2">
            <Button
              size="sm"
              variant="outline"
              disabled={setStatus.isPending}
              onClick={() => setStatus.mutate("Resolved")}
            >
              {t("resolve")}
            </Button>
            <Button
              size="sm"
              variant="destructive"
              disabled={setStatus.isPending}
              onClick={() => setStatus.mutate("Closed")}
            >
              {t("close")}
            </Button>
          </div>
        ) : (
          <p className="mt-2 text-sm text-muted-foreground">{t("closedHint")}</p>
        )}
      </Card>
      <div className="space-y-2">
        {data.messages.map((m) => (
          <Card
            key={m.id}
            className={`rounded-xl border p-3 ${
              m.senderKind === "Admin"
                ? "border-primary/30 bg-[#E1F5EE]/40 ms-8"
                : "border-border/80 me-8"
            }`}
          >
            <p className="text-xs font-medium text-muted-foreground">
              {m.senderKind === "Admin" ? t("fromAdmin") : t("fromCafe")}
              {m.senderName ? ` · ${m.senderName}` : ""}
            </p>
            <p className="mt-1 text-sm whitespace-pre-wrap">{m.body}</p>
          </Card>
        ))}
      </div>
      {!closed ? (
        <Card className="space-y-2 rounded-xl border p-4">
          <textarea
            className="min-h-20 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
            value={reply}
            onChange={(e) => setReply(e.target.value)}
            placeholder={t("replyPlaceholder")}
          />
          <Button
            disabled={!reply.trim() || sendReply.isPending}
            onClick={() => sendReply.mutate()}
          >
            {t("sendReply")}
          </Button>
        </Card>
      ) : null}
    </div>
  );
}

export function AdminIntegrationsScreen() {
  const t = useTranslations("admin.integrations");
  const qc = useQueryClient();
  const { data } = useQuery({
    queryKey: ["admin", "integrations"],
    queryFn: () => adminGet<PlatformIntegrations>("/api/admin/integrations"),
  });

  const [activeGateway, setActiveGateway] = useState("zarinpal");
  const [gateways, setGateways] = useState<PaymentGatewayConfig[]>([]);
  const mergeCreds = (
    prev: PaymentGatewayConfig["credentials"],
    patch: Partial<GatewayCredentials>
  ): GatewayCredentials => ({
    username: prev?.username ?? "",
    password: prev?.password ?? "",
    branchCode: prev?.branchCode ?? "",
    terminalCode: prev?.terminalCode ?? "",
    clientId: prev?.clientId ?? "",
    clientSecret: prev?.clientSecret ?? "",
    baseUrl: prev?.baseUrl ?? "",
    hasStoredPassword: prev?.hasStoredPassword ?? false,
    hasStoredClientSecret: prev?.hasStoredClientSecret ?? false,
    ...patch,
  });
  const [openAi, setOpenAi] = useState({
    isEnabled: false,
    apiKey: "",
    model: "gpt-4o-mini",
    coffeeAdvisorEnabled: true,
  });
  const [meshy, setMeshy] = useState({
    isEnabled: false,
    apiKey: "",
    menu3dEnabled: true,
  });

  useEffect(() => {
    if (!data) return;
    setActiveGateway(data.activePaymentGateway);
    setGateways(data.paymentGateways.map((g) => ({ ...g })));
    setOpenAi({
      isEnabled: data.ai.openAi.isEnabled,
      apiKey: data.ai.openAi.apiKey ?? "",
      model: data.ai.openAi.model,
      coffeeAdvisorEnabled: data.ai.openAi.coffeeAdvisorEnabled,
    });
    setMeshy({
      isEnabled: data.ai.meshy.isEnabled,
      apiKey: data.ai.meshy.apiKey ?? "",
      menu3dEnabled: data.ai.meshy.menu3dEnabled,
    });
  }, [data]);

  const list = gateways.length > 0 ? gateways : data?.paymentGateways ?? [];

  const save = useMutation({
    mutationFn: () =>
      adminPut<PlatformIntegrations>("/api/admin/integrations", {
        activePaymentGateway: activeGateway,
        // Save from `list` (what's rendered/edited), not `gateways` — if the
        // gateways state hasn't hydrated, `list` falls back to the fetched data,
        // and edits go through updateGateway which seeds it. This keeps the
        // rendered, edited, and saved arrays the same source (was dropping
        // edits like the Zarinpal merchantId when gateways was empty).
        paymentGateways: list.map((g) => ({
          id: g.id,
          isEnabled: g.isEnabled,
          merchantId: g.id === "zarinpal" ? g.merchantId : undefined,
          apiKey: g.id === "nextpay" || g.id === "vandar" ? g.apiKey : undefined,
          sandbox: g.sandbox,
          credentials:
            g.id === "tara" || g.id === "snapppay"
              ? {
                  username: g.credentials?.username ?? "",
                  password: g.credentials?.password ?? "",
                  branchCode: g.credentials?.branchCode ?? "",
                  terminalCode: g.credentials?.terminalCode ?? "",
                  clientId: g.credentials?.clientId ?? "",
                  clientSecret: g.credentials?.clientSecret ?? "",
                  baseUrl: g.credentials?.baseUrl ?? "",
                }
              : undefined,
        })),
        // SMS is bring-your-own-provider per café — no platform SMS config here.
        ai: { openAi, meshy },
      }),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ["admin", "integrations"] });
      notify.success(t("saved"));
    },
  });

  const updateGateway = (id: string, patch: Partial<PaymentGatewayConfig>) => {
    setGateways((prev) => {
      // Seed from fetched data on the first edit so an edit is never dropped
      // because the state hadn't hydrated yet.
      const base = prev.length > 0 ? prev : data?.paymentGateways?.map((g) => ({ ...g })) ?? [];
      return base.map((g) => (g.id === id ? { ...g, ...patch } : g));
    });
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between gap-3">
        <h1 className="text-lg font-medium">{t("title")}</h1>
        <Button onClick={() => save.mutate()} disabled={save.isPending || list.length === 0}>
          {t("save")}
        </Button>
      </div>

      <section className="space-y-3">
        <p className="text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
          {t("paymentTitle")}
        </p>
        {list.map((g) => (
          <Card key={g.id} className="rounded-xl border border-border/80 p-4 space-y-3">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div className="flex items-center gap-2">
                <RadioDot
                  selected={activeGateway === g.id}
                  onSelect={() => setActiveGateway(g.id)}
                />
                <span className="font-medium">{g.displayNameFa}</span>
                {activeGateway === g.id ? (
                  <Badge className="bg-[#E1F5EE] text-[#0F6E56]">{t("active")}</Badge>
                ) : null}
              </div>
              <div className="flex items-center gap-2 text-sm">
                <Toggle
                  checked={g.isEnabled}
                  onChange={(v) => updateGateway(g.id, { isEnabled: v })}
                />
                <span>{t("enabled")}</span>
              </div>
            </div>
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Toggle
                checked={g.sandbox}
                onChange={(v) => updateGateway(g.id, { sandbox: v })}
              />
              <span>{t("sandbox")}</span>
            </div>
            {g.id === "zarinpal" ? (
              <label className="block text-sm">
                {t("merchantId")}
                <Input
                  className="mt-1"
                  placeholder={g.hasStoredSecret ? "••••••••" : ""}
                  value={g.merchantId ?? ""}
                  onChange={(e) => updateGateway(g.id, { merchantId: e.target.value })}
                />
              </label>
            ) : null}
            {g.id === "nextpay" || g.id === "vandar" ? (
              <label className="block text-sm">
                {t("apiKey")}
                <Input
                  className="mt-1"
                  type="password"
                  placeholder={g.hasStoredSecret ? "••••••••" : ""}
                  value={g.apiKey ?? ""}
                  onChange={(e) => updateGateway(g.id, { apiKey: e.target.value })}
                />
              </label>
            ) : null}
            {g.id === "tara" ? (
              <div className="grid gap-2 sm:grid-cols-2">
                <p className="sm:col-span-2 text-xs text-muted-foreground">{t("taraHint")}</p>
                <label className="block text-sm">
                  {t("username")}
                  <Input
                    className="mt-1"
                    value={g.credentials?.username ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { username: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm">
                  {t("password")}
                  <Input
                    className="mt-1"
                    type="password"
                    placeholder={g.credentials?.hasStoredPassword ? "••••••••" : ""}
                    value={g.credentials?.password ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { password: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm">
                  {t("branchCode")}
                  <Input
                    className="mt-1"
                    value={g.credentials?.branchCode ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { branchCode: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm">
                  {t("terminalCode")}
                  <Input
                    className="mt-1"
                    value={g.credentials?.terminalCode ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { terminalCode: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm sm:col-span-2">
                  {t("baseUrl")}
                  <Input
                    className="mt-1"
                    dir="ltr"
                    placeholder="https://stage.tara-club.ir/club/api/v1"
                    value={g.credentials?.baseUrl ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { baseUrl: e.target.value }),
                      })
                    }
                  />
                </label>
              </div>
            ) : null}
            {g.id === "snapppay" ? (
              <div className="grid gap-2 sm:grid-cols-2">
                <p className="sm:col-span-2 text-xs text-muted-foreground">{t("snappPayHint")}</p>
                <label className="block text-sm">
                  {t("clientId")}
                  <Input
                    className="mt-1"
                    dir="ltr"
                    value={g.credentials?.clientId ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { clientId: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm">
                  {t("clientSecret")}
                  <Input
                    className="mt-1"
                    type="password"
                    dir="ltr"
                    placeholder={g.credentials?.hasStoredClientSecret ? "••••••••" : ""}
                    value={g.credentials?.clientSecret ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { clientSecret: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm">
                  {t("username")}
                  <Input
                    className="mt-1"
                    value={g.credentials?.username ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { username: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm">
                  {t("password")}
                  <Input
                    className="mt-1"
                    type="password"
                    placeholder={g.credentials?.hasStoredPassword ? "••••••••" : ""}
                    value={g.credentials?.password ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { password: e.target.value }),
                      })
                    }
                  />
                </label>
                <label className="block text-sm sm:col-span-2">
                  {t("baseUrl")}
                  <Input
                    className="mt-1"
                    dir="ltr"
                    placeholder="https://api.snapppay.ir"
                    value={g.credentials?.baseUrl ?? ""}
                    onChange={(e) =>
                      updateGateway(g.id, {
                        credentials: mergeCreds(g.credentials, { baseUrl: e.target.value }),
                      })
                    }
                  />
                </label>
              </div>
            ) : null}
          </Card>
        ))}
      </section>

      <section className="space-y-3">
        <p className="text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
          {t("aiTitle")}
        </p>
        <Card className="rounded-xl border border-border/80 p-4 space-y-3">
          <p className="text-sm font-medium">{t("openAiTitle")}</p>
          <p className="text-xs text-muted-foreground">{t("openAiHint")}</p>
          <div className="flex items-center gap-2 text-sm">
            <Toggle
              checked={openAi.isEnabled}
              onChange={(v) => setOpenAi((o) => ({ ...o, isEnabled: v }))}
            />
            <span>{t("enabled")}</span>
          </div>
          <label className="block text-sm">
            {t("openAiApiKey")}
            <Input
              className="mt-1"
              type="password"
              dir="ltr"
              placeholder={data?.ai.openAi.hasStoredApiKey ? "••••••••" : "sk-..."}
              value={openAi.apiKey}
              onChange={(e) => setOpenAi((o) => ({ ...o, apiKey: e.target.value }))}
            />
          </label>
          <label className="block text-sm">
            {t("openAiModel")}
            <select
              className="mt-1 block w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
              dir="ltr"
              value={openAi.model}
              onChange={(e) => setOpenAi((o) => ({ ...o, model: e.target.value }))}
            >
              <option value="gpt-4o-mini">gpt-4o-mini (fast, cheap)</option>
              <option value="gpt-4o">gpt-4o (best quality)</option>
              <option value="gpt-4-turbo">gpt-4-turbo</option>
              <option value="gpt-4">gpt-4</option>
              <option value="gpt-3.5-turbo">gpt-3.5-turbo (legacy)</option>
            </select>
          </label>
          <div className="flex items-center gap-2 text-sm">
            <Toggle
              checked={openAi.coffeeAdvisorEnabled}
              onChange={(v) => setOpenAi((o) => ({ ...o, coffeeAdvisorEnabled: v }))}
            />
            <span>{t("coffeeAdvisorEnabled")}</span>
          </div>
        </Card>
        <Card className="rounded-xl border border-border/80 p-4 space-y-3">
          <p className="text-sm font-medium">{t("meshyTitle")}</p>
          <p className="text-xs text-muted-foreground">{t("meshyHint")}</p>
          <div className="flex items-center gap-2 text-sm">
            <Toggle
              checked={meshy.isEnabled}
              onChange={(v) => setMeshy((m) => ({ ...m, isEnabled: v }))}
            />
            <span>{t("enabled")}</span>
          </div>
          <label className="block text-sm">
            {t("meshyApiKey")}
            <Input
              className="mt-1"
              type="password"
              dir="ltr"
              placeholder={data?.ai.meshy.hasStoredApiKey ? "••••••••" : ""}
              value={meshy.apiKey}
              onChange={(e) => setMeshy((m) => ({ ...m, apiKey: e.target.value }))}
            />
          </label>
          <div className="flex items-center gap-2 text-sm">
            <Toggle
              checked={meshy.menu3dEnabled}
              onChange={(v) => setMeshy((m) => ({ ...m, menu3dEnabled: v }))}
            />
            <span>{t("menu3dEnabled")}</span>
          </div>
        </Card>
      </section>
    </div>
  );
}

export function AdminNotificationsScreen() {
  const t = useTranslations("admin.notifications");
  const tc = useTranslations("common");
  const qc = useQueryClient();
  const [title, setTitle] = useState("");
  const [body, setBody] = useState("");

  const { data } = useQuery({
    queryKey: ["admin", "notifications"],
    queryFn: () =>
      adminGet<{ items: AdminNotificationRow[]; total: number }>(
        "/api/admin/notifications?limit=100"
      ),
  });

  const broadcast = useMutation({
    mutationFn: () =>
      adminPost<{ cafeCount: number; notificationCount: number }>(
        "/api/admin/notifications/broadcast",
        { title, body }
      ),
    onSuccess: (res) => {
      setTitle("");
      setBody("");
      void qc.invalidateQueries({ queryKey: ["admin", "notifications"] });
      notify.success(t("broadcastSent", { count: res.notificationCount }));
    },
  });

  const remove = useMutation({
    mutationFn: (id: string) => adminDelete(`/api/admin/notifications/${id}`),
    onSuccess: () => void qc.invalidateQueries({ queryKey: ["admin", "notifications"] }),
  });

  const items = data?.items ?? [];

  return (
    <div className="space-y-6">
      <h1 className="text-lg font-medium">{t("title")}</h1>

      <Card className="rounded-xl border border-border/80 p-4 space-y-3">
        <p className="text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
          {t("broadcastTitle")}
        </p>
        <Input
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          placeholder={t("broadcastTitlePlaceholder")}
        />
        <Input
          value={body}
          onChange={(e) => setBody(e.target.value)}
          placeholder={t("broadcastBodyPlaceholder")}
        />
        <Button
          disabled={!title.trim() || broadcast.isPending}
          onClick={() => broadcast.mutate()}
        >
          {t("sendBroadcast")}
        </Button>
      </Card>

      <section className="space-y-2">
        <p className="text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground">
          {t("allNotifications")} ({data?.total ?? items.length})
        </p>
        {items.length === 0 ? (
          <p className="text-sm text-muted-foreground">{t("empty")}</p>
        ) : (
          items.map((n) => (
            <Card key={n.id} className="flex items-start justify-between gap-3 rounded-xl border p-4">
              <div className="min-w-0">
                <p className="text-sm font-medium">{n.title}</p>
                {n.body ? <p className="mt-1 text-sm text-muted-foreground">{n.body}</p> : null}
                <p className="mt-2 text-[11px] text-muted-foreground">
                  {n.cafeName} · {n.type} · {new Date(n.createdAt).toLocaleString("fa-IR")}
                </p>
              </div>
              <Button
                variant="outline"
                size="sm"
                className="shrink-0 text-destructive"
                disabled={remove.isPending}
                onClick={() => remove.mutate(n.id)}
              >
                {tc("delete")}
              </Button>
            </Card>
          ))
        )}
      </section>
    </div>
  );
}
