// src/pages/AdminPlans.jsx (UPDATED - plan_type personal/org + storage unit input -> bytes + monthly/yearly fields)
import React, { useEffect, useMemo, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { createPortal } from "react-dom";
import PageShell from "./_pageShell";
import { api } from "../services/api";
import { useToast } from "../components/ToastProvider";
import DropdownPortal from "../components/DropdownPortal";
import {
  TbRefresh,
  TbSearch,
  TbPlus,
  TbPencil,
  TbTrash,
  TbCheck,
  TbX,
  TbAlertTriangle,
  TbBox,
  TbUsers,
  TbUser,
  TbClock,
  TbDatabase,
  TbShieldCheck,
  TbBolt,
  TbBuilding,
  TbUserCircle,
  TbPercentage,
} from "react-icons/tb";

/* ---------------- helpers ---------------- */
function cn(...a) {
  return a.filter(Boolean).join(" ");
}
function toFa(v) {
  try {
    return String(v).toLocaleString("fa-IR");
  } catch {
    return String(v ?? "");
  }
}
function fmtDate(iso) {
  if (!iso) return "-";
  try {
    return new Date(iso).toLocaleString("fa-IR", {
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
    });
  } catch {
    return iso;
  }
}
const getErrMsg = (e, fallback = "خطای ناشناخته") => {
  const d = e?.response?.data;
  if (!d) return e?.message || fallback;
  if (typeof d === "string") return d;
  if (d.detail) return d.detail;
  if (d.message) return d.message;
  try {
    return JSON.stringify(d);
  } catch {
    return fallback;
  }
};

// باینری (1024) مطابق نمونه‌های backend
const UNIT = {
  MB: 1024 ** 2,
  GB: 1024 ** 3,
  TB: 1024 ** 4,
};
const STORAGE_UNITS = [
  { value: "MB", label: "MB" },
  { value: "GB", label: "GB" },
  { value: "TB", label: "TB" },
];

const bytesToHuman = (bytes) => {
  const n = Number(bytes ?? 0);
  if (!Number.isFinite(n) || n <= 0) return "0 B";
  const units = ["B", "KB", "MB", "GB", "TB", "PB"];
  let v = n;
  let i = 0;
  while (v >= 1024 && i < units.length - 1) {
    v /= 1024;
    i++;
  }
  const fixed = v >= 10 || i === 0 ? v.toFixed(0) : v.toFixed(1);
  return `${fixed} ${units[i]}`;
};

// value+unit => bytes
const toBytes = (value, unit) => {
  const v = Number(String(value ?? "").replace(/[^\d.]/g, ""));
  if (!Number.isFinite(v) || v <= 0) return 0;
  const mul = UNIT[unit] ?? UNIT.GB;
  return Math.round(v * mul);
};

// bytes => بهترین unit (MB/GB/TB) + مقدار
const splitBytes = (bytes) => {
  const b = Number(bytes ?? 0);
  if (!Number.isFinite(b) || b <= 0) return { value: "", unit: "GB" };

  // بیشترین واحد تا TB
  if (b >= UNIT.TB) {
    const v = b / UNIT.TB;
    return { value: v >= 10 ? v.toFixed(0) : v.toFixed(1), unit: "TB" };
  }
  if (b >= UNIT.GB) {
    const v = b / UNIT.GB;
    return { value: v >= 10 ? v.toFixed(0) : v.toFixed(1), unit: "GB" };
  }
  // default MB
  const v = b / UNIT.MB;
  return { value: v >= 10 ? v.toFixed(0) : v.toFixed(1), unit: "MB" };
};

function useDebouncedValue(value, delay = 350) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const t = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(t);
  }, [value, delay]);
  return debounced;
}

/* ---------------- UI atoms ---------------- */
const CARD =
  "rounded-2xl shadow border border-black/10 dark:border-white/10 bg-white/70 dark:bg-white/5 backdrop-blur-sm";
const SOFT =
  "rounded-2xl shadow border border-black/10 dark:border-white/10 bg-[#A1E3F910] dark:bg-[#A1E3F919]";
const INPUT_BASE =
  "w-full dark:bg-[#A1E3F919] bg-[#A1E3F980] text-sm rounded-xl shadow grid relative items-center border border-black/10 dark:border-white/10";
const INPUT =
  "h-11 px-4 w-full outline-0 focus:outline-0 rounded-xl bg-transparent text-black dark:text-white placeholder:text-black/50 dark:placeholder:text-white/50";

function Badge({ tone = "default", children }) {
  const m = {
    default:
      "bg-black/5 border-black/10 text-black/70 dark:text-white/70 dark:bg-white/10 dark:border-white/10",
    success:
      "bg-emerald-500/10 border-emerald-500/25 text-emerald-700 dark:text-emerald-200",
    danger:
      "bg-red-500/10 border-red-500/25 text-red-700 dark:text-red-200",
    warn:
      "bg-amber-500/10 border-amber-500/25 text-amber-700 dark:text-amber-200",
    info:
      "bg-[#43BEFF14] border-[#43BEFF40] text-[#146E85] dark:text-[#A1E3F9]",
  };
  return (
    <span
      className={cn(
        "inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs border",
        m[tone] || m.default
      )}
    >
      {children}
    </span>
  );
}

/* ---------------- Modal ---------------- */
function useBodyScrollLock(locked) {
  useEffect(() => {
    if (!locked) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => (document.body.style.overflow = prev);
  }, [locked]);
}
function Modal({ open, title, onClose, children, widthClass = "max-w-2xl" }) {
  useBodyScrollLock(open);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && onClose?.();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);

  if (!open) return null;

  return createPortal(
    <div className="fixed inset-0 z-[9998]">
      <div className="absolute inset-0 bg-black/45" onClick={onClose} />
      <div className={cn("absolute inset-x-0 top-10 mx-auto px-3", widthClass)}>
        <div className="rounded-2xl shadow-xl border border-black/10 dark:border-white/10 bg-white dark:bg-[#0b1d39] overflow-hidden">
          <div className="px-4 py-3 border-b border-black/10 dark:border-white/10 flex items-center justify-between">
            <div className="font-extrabold text-black dark:text-white text-sm truncate">
              {title}
            </div>
            <button
              type="button"
              onClick={onClose}
              className="rounded-xl px-3 py-2 hover:bg-black/5 dark:hover:bg-white/10 transition"
            >
              <TbX className="w-5 h-5" />
            </button>
          </div>
          <div className="p-4">{children}</div>
        </div>
      </div>
    </div>,
    document.body
  );
}
function Field({ label, children, hint }) {
  return (
    <div>
      <div className="mb-1 text-xs text-black/60 dark:text-white/70 font-bold">
        {label}
      </div>
      {children}
      {hint ? (
        <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
          {hint}
        </div>
      ) : null}
    </div>
  );
}

function Toggle({ value, onToggle, labelOn = "فعال", labelOff = "غیرفعال" }) {
  return (
    <button
      type="button"
      onClick={onToggle}
      className={cn(
        "px-3 py-2 rounded-xl border transition text-sm inline-flex items-center gap-2",
        value
          ? "border-emerald-500/25 bg-emerald-500/10 text-emerald-700 dark:text-emerald-200"
          : "border-red-500/25 bg-red-500/10 text-red-700 dark:text-red-200"
      )}
    >
      {value ? <TbCheck className="w-4 h-4" /> : <TbX className="w-4 h-4" />}
      {value ? labelOn : labelOff}
    </button>
  );
}

function PlanTypePill({ v }) {
  const t = String(v || "").toLowerCase();
  if (t === "org") {
    return (
      <Badge tone="info">
        <TbBuilding className="w-4 h-4" />
        سازمانی
      </Badge>
    );
  }
  return (
    <Badge tone="info">
      <TbUserCircle className="w-4 h-4" />
      شخصی
    </Badge>
  );
}

/* ---------------- API ---------------- */
async function listPlans() {
  const res = await api.get("/api/admin/billing/plans/");
  return res.data;
}
async function createPlan(payload) {
  const res = await api.post("/api/admin/billing/plans/", payload);
  return res.data;
}
async function patchPlan({ plan_id, payload }) {
  const res = await api.patch(`/api/admin/billing/plans/${plan_id}/`, payload);
  return res.data;
}

async function getSub(sub_id) {
  const res = await api.get(`/api/admin/billing/subscriptions/${sub_id}/`);
  return res.data;
}
async function patchSub({ sub_id, payload }) {
  const res = await api.patch(`/api/admin/billing/subscriptions/${sub_id}/`, payload);
  return res.data;
}
async function deleteSub(sub_id) {
  const res = await api.delete(`/api/admin/billing/subscriptions/${sub_id}/`);
  return res.data;
}

async function listUsers(params) {
  const res = await api.get("/api/admin/users/", { params });
  return res.data;
}

/**
 * ✅ Fetch ALL subscriptions (paginate through backend)
 * Supports DRF-style: {count,next,previous,results} or array
 */
async function listAllSubs() {
  const pageSize = 200;
  const maxPages = 400;
  let page = 1;
  let all = [];
  let next = true;

  while (next && page <= maxPages) {
    const res = await api.get("/api/admin/billing/subscriptions/", {
      params: { page, page_size: pageSize },
    });

    const d = res.data;

    if (Array.isArray(d)) {
      all = d;
      break;
    }

    const items = Array.isArray(d?.results) ? d.results : [];
    all = all.concat(items);

    if (d?.next === null || items.length === 0) next = false;
    else next = true;

    page += 1;
  }

  return all;
}

/* ---------------- Page ---------------- */
export default function AdminPlans() {
  const qc = useQueryClient();
  const { success, error: toastError, info } = useToast();

  // shared dropdown/menu state
  const [menu, setMenu] = useState({ id: null, rect: null });

  // -------- Plans filters
  const [pq, setPq] = useState("");
  const [pActive, setPActive] = useState("all");
  const [pType, setPType] = useState("all"); // ✅ new: personal/org filter

  // -------- Subscriptions filters (CLIENT)
  const [sqRaw, setSqRaw] = useState("");
  const sq = useDebouncedValue(sqRaw, 350);
  const [sStatus, setSStatus] = useState("all");

  const [sPage, setSPage] = useState(1);
  const sPageSize = 50;

  // create plan modal
  const [createOpen, setCreateOpen] = useState(false);
  const [createDraft, setCreateDraft] = useState({
    name: "",
    price: "",
    duration_days: 30,

    // ✅ storage as value+unit (send bytes)
    storage_value: "10",
    storage_unit: "GB",

    is_active: true,
    plan_type: "personal", // personal | org

    monthly_enabled: true,
    yearly_enabled: true,
    yearly_discount_percent: 10,
    yearly_duration_days: 365,
  });

  // edit plan modal
  const [editOpen, setEditOpen] = useState(false);
  const [editPlan, setEditPlan] = useState(null);
  const [editDraft, setEditDraft] = useState({
    name: "",
    price: "",
    duration_days: "",

    storage_value: "",
    storage_unit: "GB",

    is_active: true,
    plan_type: "personal",

    monthly_enabled: true,
    yearly_enabled: true,
    yearly_discount_percent: 10,
    yearly_duration_days: 365,
  });

  // subs modals
  const [subEditOpen, setSubEditOpen] = useState(false);
  const [subDeleteOpen, setSubDeleteOpen] = useState(false);
  const [subCurrent, setSubCurrent] = useState(null);
  const [subDraft, setSubDraft] = useState({
    is_active: true,
    ended_at: "",
  });

  // user picker
  const [uOpen, setUOpen] = useState(false);
  const [uq, setUq] = useState("");
  const [uActive, setUActive] = useState("all");

  const activeOptions = useMemo(
    () => [
      { value: "all", label: "همه" },
      { value: "true", label: "فقط فعال" },
      { value: "false", label: "فقط غیرفعال" },
    ],
    []
  );

  const typeOptions = useMemo(
    () => [
      { value: "all", label: "همه" },
      { value: "personal", label: "شخصی" },
      { value: "org", label: "سازمانی" },
    ],
    []
  );

  const subStatusOptions = useMemo(
    () => [
      { value: "all", label: "همه" },
      { value: "active", label: "Active" },
      { value: "canceled", label: "Canceled" },
      { value: "expired", label: "Expired" },
      { value: "pending", label: "Pending" },
    ],
    []
  );

  const subStatusTone = (s) => {
    const v = String(s || "").toLowerCase();
    if (v === "active") return { tone: "success", label: "Active" };
    if (v === "pending") return { tone: "warn", label: "Pending" };
    if (v === "expired") return { tone: "default", label: "Expired" };
    if (v === "canceled") return { tone: "danger", label: "Canceled" };
    return { tone: "default", label: v || "-" };
  };

  // -------- Queries
  const qPlans = useQuery({
    queryKey: ["admin-plans"],
    queryFn: listPlans,
    staleTime: 5_000,
    refetchOnWindowFocus: false,
  });

  // ✅ fetch ALL subscriptions once (refetchable)
  const qSubsAll = useQuery({
    queryKey: ["admin-subs-all"],
    queryFn: listAllSubs,
    staleTime: 10_000,
    refetchOnWindowFocus: false,
  });

  const plans = useMemo(() => {
    const arr = Array.isArray(qPlans.data) ? qPlans.data : [];
    let out = arr;

    if (pActive !== "all") {
      const want = pActive === "true";
      out = out.filter((p) => !!p?.is_active === want);
    }

    if (pType !== "all") {
      const want = String(pType).toLowerCase();
      out = out.filter((p) => String(p?.plan_type || "").toLowerCase() === want);
    }

    const qq = String(pq || "").trim().toLowerCase();
    if (qq) out = out.filter((p) => String(p?.name || "").toLowerCase().includes(qq));

    return out
      .slice()
      .sort((a, b) => String(b?.created_at || "").localeCompare(String(a?.created_at || "")));
  }, [qPlans.data, pq, pActive, pType]);

  const subsAll = useMemo(() => (Array.isArray(qSubsAll.data) ? qSubsAll.data : []), [qSubsAll.data]);

  // ✅ CLIENT-side filter/search
  const subsFiltered = useMemo(() => {
    let out = subsAll;

    if (sStatus !== "all") {
      const want = String(sStatus).toLowerCase();
      out = out.filter((s) => String(s?.status || "").toLowerCase() === want);
    }

    const q = String(sq || "").trim().toLowerCase();
    if (q) {
      out = out.filter((s) => {
        const hay = [
          s?.user_email,
          s?.plan_name,
          s?.status,
          s?.id,
          s?.user,
          s?.plan,
        ]
          .map((x) => String(x ?? "").toLowerCase())
          .join(" | ");
        return hay.includes(q);
      });
    }

    return out.slice().sort((a, b) => String(b?.started_at || "").localeCompare(String(a?.started_at || "")));
  }, [subsAll, sStatus, sq]);

  const subsTotalCount = subsFiltered.length;

  const subsTotalPages = useMemo(
    () => Math.max(1, Math.ceil(subsTotalCount / sPageSize)),
    [subsTotalCount, sPageSize]
  );

  useEffect(() => {
    setSPage(1);
  }, [sq, sStatus]);

  useEffect(() => {
    if (sPage > subsTotalPages) setSPage(1);
  }, [sPage, subsTotalPages]);

  const subsPageItems = useMemo(() => {
    const start = (sPage - 1) * sPageSize;
    return subsFiltered.slice(start, start + sPageSize);
  }, [subsFiltered, sPage, sPageSize]);

  const qUsers = useQuery({
    enabled: uOpen,
    queryKey: ["admin-users-for-billing", { uq, uActive }],
    queryFn: () =>
      listUsers({
        q: uq || undefined,
        is_active: uActive === "all" ? undefined : uActive,
        page: 1,
        page_size: 200,
      }),
    staleTime: 10_000,
    refetchOnWindowFocus: false,
  });

  const users = useMemo(() => {
    const d = qUsers.data;
    return Array.isArray(d) ? d : d?.results || [];
  }, [qUsers.data]);

  // -------- Mutations
  const mutCreatePlan = useMutation({
    mutationFn: createPlan,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-plans"] });
      success("پلن ساخته شد ✅", { title: "Plans" });
      setCreateOpen(false);
      setCreateDraft({
        name: "",
        price: "",
        duration_days: 30,
        storage_value: "10",
        storage_unit: "GB",
        is_active: true,
        plan_type: "personal",
        monthly_enabled: true,
        yearly_enabled: true,
        yearly_discount_percent: 10,
        yearly_duration_days: 365,
      });
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در ساخت پلن"), { title: "Plans" }),
  });

  const mutPatchPlan = useMutation({
    mutationFn: patchPlan,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-plans"] });
      success("پلن بروزرسانی شد ✅", { title: "Plans" });
      setEditOpen(false);
      setEditPlan(null);
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در ویرایش پلن"), { title: "Plans" }),
  });

  const mutPatchSub = useMutation({
    mutationFn: patchSub,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-subs-all"] });
      success("اشتراک بروزرسانی شد ✅", { title: "Subscriptions" });
      setSubEditOpen(false);
      setSubCurrent(null);
    },
    onError: (e) =>
      toastError(getErrMsg(e, "خطا در بروزرسانی اشتراک"), { title: "Subscriptions" }),
  });

  const mutDeleteSub = useMutation({
    mutationFn: deleteSub,
    onSuccess: async () => {
      await qc.invalidateQueries({ queryKey: ["admin-subs-all"] });
      success("اشتراک حذف شد ✅", { title: "Subscriptions" });
      setSubDeleteOpen(false);
      setSubCurrent(null);
    },
    onError: (e) => toastError(getErrMsg(e, "خطا در حذف اشتراک"), { title: "Subscriptions" }),
  });

  // -------- Actions
  const refreshAll = async () => {
    info("در حال بروزرسانی...", { title: "Billing" });
    await Promise.allSettled([qPlans.refetch(), qSubsAll.refetch()]);
    success("بروزرسانی شد ✅", { title: "Billing" });
  };

  const validateStorage = (value, unit) => {
    const b = toBytes(value, unit);
    if (!b) return "حجم ذخیره‌سازی معتبر نیست.";
    return null;
  };

  const validateCreate = () => {
    const name = String(createDraft.name || "").trim();
    if (!name) return "name اجباری است.";
    const price = Number(createDraft.price);
    if (!Number.isFinite(price) || price < 0) return "price باید عدد معتبر باشد.";
    const d = Number(createDraft.duration_days);
    if (!Number.isFinite(d) || d <= 0) return "duration_days باید عدد مثبت باشد.";

    const se = validateStorage(createDraft.storage_value, createDraft.storage_unit);
    if (se) return se;

    const pt = String(createDraft.plan_type || "").toLowerCase();
    if (!["personal", "org"].includes(pt)) return "plan_type باید personal یا org باشد.";

    if (createDraft.yearly_enabled) {
      const yd = Number(createDraft.yearly_duration_days);
      if (!Number.isFinite(yd) || yd <= 0) return "yearly_duration_days باید عدد مثبت باشد.";
      const disc = Number(createDraft.yearly_discount_percent);
      if (!Number.isFinite(disc) || disc < 0 || disc > 100) return "yearly_discount_percent باید بین ۰ تا ۱۰۰ باشد.";
    }

    return null;
  };

  const submitCreate = () => {
    const err = validateCreate();
    if (err) return toastError(err, { title: "Plans" });

    const storage_limit_bytes = toBytes(createDraft.storage_value, createDraft.storage_unit);

    const payload = {
      name: String(createDraft.name).trim(),
      price: Number(createDraft.price),
      duration_days: Number(createDraft.duration_days),
      storage_limit_bytes,
      is_active: !!createDraft.is_active,
      plan_type: String(createDraft.plan_type).toLowerCase(),
      monthly_enabled: !!createDraft.monthly_enabled,
      yearly_enabled: !!createDraft.yearly_enabled,
      yearly_discount_percent: Number(createDraft.yearly_discount_percent ?? 0),
      yearly_duration_days: Number(createDraft.yearly_duration_days ?? 365),
    };

    // اگر yearly_enabled خاموشه، این فیلدا رو تمیز بفرست
    if (!payload.yearly_enabled) {
      payload.yearly_discount_percent = 0;
      payload.yearly_duration_days = 365;
    }

    info("در حال ساخت پلن...", { title: "Plans" });
    mutCreatePlan.mutate(payload);
  };

  const openEditPlan = (p) => {
    const sp = splitBytes(p?.storage_limit_bytes ?? 0);

    setEditPlan(p);
    setEditDraft({
      name: String(p?.name ?? ""),
      price: String(p?.price ?? ""),
      duration_days: String(p?.duration_days ?? ""),

      storage_value: sp.value,
      storage_unit: sp.unit,

      is_active: !!p?.is_active,
      plan_type: String(p?.plan_type || "personal").toLowerCase(),

      monthly_enabled: !!p?.monthly_enabled,
      yearly_enabled: !!p?.yearly_enabled,
      yearly_discount_percent: Number(p?.yearly_discount_percent ?? 0),
      yearly_duration_days: Number(p?.yearly_duration_days ?? 365),
    });
    setEditOpen(true);
  };

  const validateEdit = () => {
    if (!editPlan?.id) return "پلن نامعتبر است.";
    const name = String(editDraft.name || "").trim();
    if (!name) return "name اجباری است.";

    if (editDraft.price !== "") {
      const price = Number(editDraft.price);
      if (!Number.isFinite(price) || price < 0) return "price باید عدد معتبر باشد.";
    }

    if (editDraft.duration_days !== "") {
      const d = Number(editDraft.duration_days);
      if (!Number.isFinite(d) || d <= 0) return "duration_days باید عدد مثبت باشد.";
    }

    const se = validateStorage(editDraft.storage_value, editDraft.storage_unit);
    if (se) return se;

    const pt = String(editDraft.plan_type || "").toLowerCase();
    if (!["personal", "org"].includes(pt)) return "plan_type باید personal یا org باشد.";

    if (editDraft.yearly_enabled) {
      const yd = Number(editDraft.yearly_duration_days);
      if (!Number.isFinite(yd) || yd <= 0) return "yearly_duration_days باید عدد مثبت باشد.";
      const disc = Number(editDraft.yearly_discount_percent);
      if (!Number.isFinite(disc) || disc < 0 || disc > 100) return "yearly_discount_percent باید بین ۰ تا ۱۰۰ باشد.";
    }

    return null;
  };

  const submitEditPlan = () => {
    const err = validateEdit();
    if (err) return toastError(err, { title: "Plans" });

    const payload = {
      name: String(editDraft.name).trim(),
      price: editDraft.price === "" ? undefined : Number(editDraft.price),
      duration_days: editDraft.duration_days === "" ? undefined : Number(editDraft.duration_days),

      storage_limit_bytes: toBytes(editDraft.storage_value, editDraft.storage_unit),

      is_active: !!editDraft.is_active,
      plan_type: String(editDraft.plan_type).toLowerCase(),
      monthly_enabled: !!editDraft.monthly_enabled,
      yearly_enabled: !!editDraft.yearly_enabled,
      yearly_discount_percent: Number(editDraft.yearly_discount_percent ?? 0),
      yearly_duration_days: Number(editDraft.yearly_duration_days ?? 365),
    };

    if (!payload.yearly_enabled) {
      payload.yearly_discount_percent = 0;
      payload.yearly_duration_days = 365;
    }

    Object.keys(payload).forEach((k) => payload[k] === undefined && delete payload[k]);

    info("در حال ذخیره...", { title: "Plans" });
    mutPatchPlan.mutate({ plan_id: editPlan.id, payload });
  };

  const openEditSub = async (s) => {
    try {
      info("در حال دریافت اشتراک...", { title: "Subscriptions" });
      const d = await getSub(s.id);
      setSubCurrent(d);
      setSubDraft({
        is_active: String(d?.status || "").toLowerCase() === "active",
        ended_at: d?.ends_at || "",
      });
      setSubEditOpen(true);
      success("آماده شد ✅", { title: "Subscriptions" });
    } catch (e) {
      toastError(getErrMsg(e, "خطا در دریافت اشتراک"), { title: "Subscriptions" });
    }
  };

  const submitEditSub = () => {
    if (!subCurrent?.id) return;

    const payload = {
      is_active: !!subDraft.is_active,
      ended_at: subDraft.ended_at ? subDraft.ended_at : null,
    };

    info("در حال ذخیره...", { title: "Subscriptions" });
    mutPatchSub.mutate({ sub_id: subCurrent.id, payload });
  };

  const confirmDeleteSub = (s) => {
    setSubCurrent(s);
    setSubDeleteOpen(true);
  };

  const doDeleteSub = () => {
    if (!subCurrent?.id) return;
    info("در حال حذف اشتراک...", { title: "Subscriptions" });
    mutDeleteSub.mutate(subCurrent.id);
  };

  return (
    <PageShell title="پلن‌ها و اشتراک‌ها">
      <div className="w-full dark:text-white">
        {/* header */}
        <div className={cn(CARD, "p-3 sm:p-4 mb-4 !bg-[#A1E3F910] dark:!bg-[#A1E3F910]")}>
          <div className="flex flex-col lg:flex-row gap-3 lg:items-center lg:justify-between">
            <div className="min-w-0">
              <h1 className="text-lg sm:text-xl font-extrabold inline-flex items-center gap-2">
                <TbBox className="w-5 h-5 opacity-80" />
                مدیریت پلن‌ها + اشتراک‌ها
              </h1>
              <p className="text-xs sm:text-sm text-black/60 dark:text-white/70 truncate">
                ساخت/ویرایش پلن‌ها (شخصی و سازمانی) + مدیریت اشتراک کاربران
              </p>
            </div>

            <div className="flex items-center gap-2 w-full lg:w-auto flex-wrap">
              <button
                type="button"
                onClick={refreshAll}
                disabled={qPlans.isFetching || qSubsAll.isFetching}
                className="px-4 py-2 rounded-xl shadow bg-white dark:bg-[#16325b]
                  border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10
                  text-sm inline-flex items-center justify-center gap-2 transition disabled:opacity-60"
              >
                <TbRefresh
                  className={cn(
                    "w-4 h-4 text-[#43BEFF] dark:text-white",
                    qPlans.isFetching || qSubsAll.isFetching ? "animate-spin" : ""
                  )}
                />
                بروزرسانی
              </button>

              <button
                type="button"
                onClick={() => setCreateOpen(true)}
                className="px-4 py-2 rounded-xl shadow bg-white dark:bg-[#16325b]
                  border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10
                  text-sm inline-flex items-center justify-center gap-2 transition"
              >
                <TbPlus className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                ساخت پلن
              </button>

              <button
                type="button"
                onClick={() => setUOpen(true)}
                className="px-4 py-2 rounded-xl shadow bg-white dark:bg-[#16325b]
                  border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10
                  text-sm inline-flex items-center justify-center gap-2 transition"
              >
                <TbUsers className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                کاربران (نمایش)
              </button>

              <Badge tone="info">
                پلن‌ها: <b className="font-extrabold">{toFa(plans.length)}</b>
              </Badge>

              <Badge tone="info">
                اشتراک‌ها: <b className="font-extrabold">{toFa(subsAll.length)}</b>
              </Badge>

              {qSubsAll.isFetching ? (
                <Badge tone="warn">
                  <TbRefresh className="w-4 h-4 animate-spin" />
                  درحال دریافت همه اشتراک‌ها...
                </Badge>
              ) : null}
            </div>
          </div>

          {qPlans.error || qSubsAll.error ? (
            <div className={cn("mt-3 rounded-2xl border border-amber-500/25 bg-amber-500/10 p-3")}>
              <div className="flex items-start gap-2">
                <TbAlertTriangle className="w-5 h-5 mt-0.5" />
                <div className="text-sm">
                  <div className="font-extrabold">خطا در دریافت اطلاعات</div>
                  <div className="text-xs opacity-80 mt-1">
                    {getErrMsg(qPlans.error || qSubsAll.error)}
                  </div>
                </div>
              </div>
            </div>
          ) : null}
        </div>

        {/* ---------------- Plans section ---------------- */}
        <div className={cn(CARD, "p-3 sm:p-4 mb-4")}>
          <div className="flex items-center justify-between gap-2 flex-wrap">
            <div className="font-extrabold inline-flex items-center gap-2">
              <TbShieldCheck className="w-5 h-5 opacity-80" />
              پلن‌ها
            </div>

            <div className="flex items-center gap-2 w-full lg:w-auto flex-wrap">
              <div className={cn(INPUT_BASE, "w-full sm:w-[260px]")}>
                <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
                  <TbSearch className="w-5 h-5" />
                </div>
                <input
                  className={cn(INPUT, "pr-11")}
                  placeholder="جستجو بر اساس name..."
                  value={pq}
                  onChange={(e) => setPq(e.target.value)}
                />
              </div>

              <DropdownPortal
                id="plans-type-filter"
                menu={menu}
                setMenu={setMenu}
                label="نوع"
                value={pType}
                options={typeOptions}
                onChange={(v) => setPType(v)}
                width={220}
              />

              <DropdownPortal
                id="plans-active-filter"
                menu={menu}
                setMenu={setMenu}
                label="فعال"
                value={pActive}
                options={activeOptions}
                onChange={(v) => setPActive(v)}
                width={220}
              />
            </div>
          </div>

          {qPlans.isLoading ? (
            <div className="mt-3 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
              {[...Array(6)].map((_, i) => (
                <div key={i} className={cn(SOFT, "p-4 animate-pulse")}>
                  <div className="h-5 w-40 rounded bg-black/5 dark:bg-white/10" />
                  <div className="mt-3 h-4 w-56 rounded bg-black/5 dark:bg-white/10" />
                  <div className="mt-3 h-10 w-full rounded bg-black/5 dark:bg-white/10" />
                </div>
              ))}
            </div>
          ) : plans.length === 0 ? (
            <div className="mt-3 py-10 text-center text-black/50 dark:text-white/60">
              پلنی برای نمایش وجود ندارد.
            </div>
          ) : (
            <div className="mt-3 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
              {plans.map((p) => {
                const active = !!p?.is_active;
                const pt = String(p?.plan_type || "personal").toLowerCase();
                return (
                  <div
                    key={String(p.id)}
                    className={cn(
                      "rounded-3xl border border-black/10 dark:border-white/10 p-4",
                      "bg-white/70 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/10 transition",
                      "min-w-0"
                    )}
                  >
                    <div className="flex items-start justify-between gap-2">
                      <div className="min-w-0">
                        <div className="font-extrabold text-black dark:text-white truncate">
                          {p?.name || "-"}
                        </div>
                        <div className="mt-1 text-[11px] text-black/55 dark:text-white/60 truncate">
                          slug: <span className="font-mono">{String(p?.slug || "-")}</span>
                        </div>
                        <div className="mt-1 text-[11px] text-black/55 dark:text-white/60 truncate">
                          id: <span className="font-mono">{String(p.id)}</span>
                        </div>
                      </div>

                      <div className="flex flex-col items-end gap-2">
                        <PlanTypePill v={pt} />
                        <Badge tone={active ? "success" : "danger"}>
                          {active ? <TbCheck className="w-4 h-4" /> : <TbX className="w-4 h-4" />}
                          {active ? "Active" : "Inactive"}
                        </Badge>
                      </div>
                    </div>

                    <div className="mt-3 grid grid-cols-2 gap-2">
                      <div className={cn(SOFT, "p-2 rounded-2xl")}>
                        <div className="text-[10px] text-black/50 dark:text-white/60 inline-flex items-center gap-1">
                          <TbBolt className="w-4 h-4" /> price
                        </div>
                        <div className="mt-1 font-extrabold text-black/80 dark:text-white/80">
                          {toFa(p?.price ?? 0)}
                        </div>
                      </div>

                      <div className={cn(SOFT, "p-2 rounded-2xl")}>
                        <div className="text-[10px] text-black/50 dark:text-white/60 inline-flex items-center gap-1">
                          <TbDatabase className="w-4 h-4" /> storage
                        </div>
                        <div className="mt-1 font-extrabold text-black/80 dark:text-white/80">
                          {bytesToHuman(p?.storage_limit_bytes ?? 0)}
                        </div>
                      </div>
                    </div>

                    <div className="mt-2 grid grid-cols-2 gap-2">
                      <div className={cn(SOFT, "p-2 rounded-2xl")}>
                        <div className="text-[10px] text-black/50 dark:text-white/60 inline-flex items-center gap-1">
                          <TbClock className="w-4 h-4" /> duration
                        </div>
                        <div className="mt-1 font-extrabold text-black/80 dark:text-white/80">
                          {toFa(p?.duration_days ?? 0)} روز
                        </div>
                      </div>

                      <div className={cn(SOFT, "p-2 rounded-2xl")}>
                        <div className="text-[10px] text-black/50 dark:text-white/60 inline-flex items-center gap-1">
                          <TbPercentage className="w-4 h-4" /> yearly
                        </div>
                        <div className="mt-1 text-[11px] font-bold text-black/80 dark:text-white/80">
                          {p?.yearly_enabled
                            ? `✅ ${toFa(p?.yearly_discount_percent ?? 0)}% • ${toFa(p?.yearly_duration_days ?? 365)}d`
                            : "❌ disabled"}
                        </div>
                        {p?.yearly_enabled && p?.yearly_price != null ? (
                          <div className="mt-1 text-[11px] text-black/60 dark:text-white/60">
                            yearly_price: <b className="font-extrabold">{toFa(p.yearly_price)}</b>
                          </div>
                        ) : null}
                      </div>
                    </div>

                    <div className="mt-2 text-[11px] text-black/50 dark:text-white/60">
                      created: <span className="font-mono">{fmtDate(p?.created_at)}</span>
                    </div>

                    <div className="mt-4 flex items-center justify-end gap-2">
                      <button
                        type="button"
                        onClick={() => openEditPlan(p)}
                        className="px-4 py-2 rounded-2xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                          hover:bg-black/5 dark:hover:bg-white/10 transition text-xs inline-flex items-center gap-2"
                      >
                        <TbPencil className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                        ویرایش
                      </button>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>

        {/* ---------------- Subscriptions section (CLIENT FILTER) ---------------- */}
        <div className={cn(CARD, "p-3 sm:p-4")}>
          <div className="flex items-center justify-between gap-2 flex-wrap">
            <div className="font-extrabold inline-flex items-center gap-2">
              <TbUsers className="w-5 h-5 opacity-80" />
              اشتراک‌ها
            </div>

            <div className="flex items-center gap-2 flex-wrap">
              <Badge tone="info">
                فیلترشده‌ها: <b className="font-extrabold">{toFa(subsTotalCount)}</b>
              </Badge>
            </div>
          </div>

          <div className="mt-3 grid lg:grid-cols-[1fr_260px_260px] gap-2">
            <div className={cn(INPUT_BASE)}>
              <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
                <TbSearch className="w-5 h-5" />
              </div>
              <input
                className={cn(INPUT, "pr-11")}
                placeholder="جستجو (email / plan / status / id / user ...)"
                value={sqRaw}
                onChange={(e) => setSqRaw(e.target.value)}
              />
            </div>

            <DropdownPortal
              id="subs-status-filter"
              menu={menu}
              setMenu={setMenu}
              label="وضعیت"
              value={sStatus}
              options={subStatusOptions}
              onChange={(v) => setSStatus(v)}
              width={240}
            />

            <div className={cn(SOFT, "p-1 h-11 flex items-center justify-between")}>
              <span className="text-xs text-black/55 dark:text-white/60">
                صفحه: <b>{toFa(sPage)}</b> / <b>{toFa(subsTotalPages)}</b>
              </span>
              <div className="flex items-center gap-2">
                <button
                  type="button"
                  disabled={sPage <= 1}
                  onClick={() => setSPage((p) => Math.max(1, p - 1))}
                  className="px-3 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition text-xs disabled:opacity-50"
                >
                  قبلی
                </button>
                <button
                  type="button"
                  disabled={sPage >= subsTotalPages}
                  onClick={() => setSPage((p) => Math.min(subsTotalPages, p + 1))}
                  className="px-3 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition text-xs disabled:opacity-50"
                >
                  بعدی
                </button>
              </div>
            </div>
          </div>

          {qSubsAll.isLoading ? (
            <div className="mt-3 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
              {[...Array(6)].map((_, i) => (
                <div key={i} className={cn(SOFT, "p-4 animate-pulse")}>
                  <div className="h-5 w-44 rounded bg-black/5 dark:bg-white/10" />
                  <div className="mt-2 h-4 w-56 rounded bg-black/5 dark:bg-white/10" />
                  <div className="mt-3 h-10 w-full rounded bg-black/5 dark:bg-white/10" />
                </div>
              ))}
            </div>
          ) : subsPageItems.length === 0 ? (
            <div className="mt-3 py-10 text-center text-black/50 dark:text-white/60">
              اشتراکی برای نمایش وجود ندارد.
            </div>
          ) : (
            <div className="mt-3 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
              {subsPageItems.map((s) => {
                const st = subStatusTone(s?.status);
                return (
                  <div
                    key={String(s.id)}
                    className={cn(
                      "rounded-3xl border border-black/10 dark:border-white/10 p-4",
                      "bg-white/70 dark:bg-white/5 hover:bg-black/5 dark:hover:bg-white/10 transition",
                      "min-w-0"
                    )}
                  >
                    <div className="flex items-start justify-between gap-2">
                      <div className="min-w-0">
                        <div className="font-extrabold truncate">
                          {s?.user_email || `User #${toFa(s?.user)}`}
                        </div>
                        <div className="mt-1 text-[11px] text-black/55 dark:text-white/60 truncate">
                          plan: <b>{s?.plan_name || "-"}</b>
                        </div>
                      </div>

                      <Badge tone={st.tone}>{st.label}</Badge>
                    </div>

                    <div className="mt-3 grid grid-cols-2 gap-2">
                      <div className={cn(SOFT, "p-2 rounded-2xl")}>
                        <div className="text-[10px] text-black/50 dark:text-white/60 inline-flex items-center gap-1">
                          <TbClock className="w-4 h-4" /> started
                        </div>
                        <div className="mt-1 text-[11px] font-mono text-black/70 dark:text-white/70 truncate">
                          {fmtDate(s?.started_at)}
                        </div>
                      </div>

                      <div className={cn(SOFT, "p-2 rounded-2xl")}>
                        <div className="text-[10px] text-black/50 dark:text-white/60 inline-flex items-center gap-1">
                          <TbClock className="w-4 h-4" /> ends
                        </div>
                        <div className="mt-1 text-[11px] font-mono text-black/70 dark:text-white/70 truncate">
                          {s?.ends_at ? fmtDate(s.ends_at) : "—"}
                        </div>
                      </div>
                    </div>

                    <div className="mt-3 text-[11px] text-black/50 dark:text-white/60 truncate">
                      sub_id: <span className="font-mono">{String(s?.id)}</span>
                    </div>

                    <div className="mt-4 flex items-center justify-end gap-2">
                      <button
                        type="button"
                        onClick={() => openEditSub(s)}
                        className="px-4 py-2 rounded-2xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                          hover:bg-black/5 dark:hover:bg-white/10 transition text-xs inline-flex items-center gap-2"
                      >
                        <TbPencil className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                        ویرایش
                      </button>

                      <button
                        type="button"
                        onClick={() => confirmDeleteSub(s)}
                        className="px-4 py-2 rounded-2xl shadow border border-red-500/25 bg-red-500/10 hover:bg-red-500/15
                          transition text-red-700 dark:text-red-200 text-xs inline-flex items-center gap-2"
                      >
                        <TbTrash className="w-4 h-4" />
                        حذف
                      </button>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>

        {/* ---------------- Create Plan Modal ---------------- */}
        <Modal
          open={createOpen}
          title="ساخت پلن"
          onClose={() => !mutCreatePlan.isPending && setCreateOpen(false)}
          widthClass="max-w-3xl"
        >
          <div className="space-y-4">
            <div className="grid md:grid-cols-2 gap-3">
              <Field label="name" hint="اسم نمایشی پلن (مثلاً: 100 گیگابایت فضا)">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={createDraft.name}
                    onChange={(e) => setCreateDraft((p) => ({ ...p, name: e.target.value }))}
                    placeholder="Pro"
                  />
                </div>
              </Field>

              <Field label="plan_type" hint="شخصی یا سازمانی">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">نوع پلن</div>
                  <div className="flex items-center gap-2">
                    <button
                      type="button"
                      onClick={() => setCreateDraft((p) => ({ ...p, plan_type: "personal" }))}
                      className={cn(
                        "px-3 py-2 rounded-xl border text-sm inline-flex items-center gap-2 transition",
                        createDraft.plan_type === "personal"
                          ? "border-[#43BEFF66] bg-[#43BEFF14]"
                          : "border-black/10 dark:border-white/10 bg-white/60 dark:bg-white/10"
                      )}
                    >
                      <TbUserCircle className="w-4 h-4" />
                      شخصی
                    </button>
                    <button
                      type="button"
                      onClick={() => setCreateDraft((p) => ({ ...p, plan_type: "org" }))}
                      className={cn(
                        "px-3 py-2 rounded-xl border text-sm inline-flex items-center gap-2 transition",
                        createDraft.plan_type === "org"
                          ? "border-[#43BEFF66] bg-[#43BEFF14]"
                          : "border-black/10 dark:border-white/10 bg-white/60 dark:bg-white/10"
                      )}
                    >
                      <TbBuilding className="w-4 h-4" />
                      سازمانی
                    </button>
                  </div>
                </div>
              </Field>

              <Field label="price">
                <div className={INPUT_BASE}>
                  <input
                    type="number"
                    className={INPUT}
                    value={createDraft.price}
                    onChange={(e) => setCreateDraft((p) => ({ ...p, price: e.target.value }))}
                    placeholder="99000"
                  />
                </div>
              </Field>

              <Field label="duration_days" hint="مدت پلن (برای ماهانه معمولاً 30)">
                <div className={INPUT_BASE}>
                  <input
                    type="number"
                    className={INPUT}
                    value={createDraft.duration_days}
                    onChange={(e) =>
                      setCreateDraft((p) => ({ ...p, duration_days: e.target.value }))
                    }
                    placeholder="30"
                  />
                </div>
              </Field>

              <Field
                label="storage_limit"
                hint="حجم را وارد کن (MB/GB/TB) — برای backend به bytes تبدیل می‌شود"
              >
                <div className="grid grid-cols-[1fr_120px] gap-2">
                  <div className={INPUT_BASE}>
                    <input
                      type="number"
                      className={INPUT}
                      value={createDraft.storage_value}
                      onChange={(e) =>
                        setCreateDraft((p) => ({ ...p, storage_value: e.target.value }))
                      }
                      placeholder="100"
                      min="0"
                      step="0.1"
                    />
                  </div>
                  <div className={INPUT_BASE}>
                    <select
                      className={cn(INPUT, "px-3")}
                      value={createDraft.storage_unit}
                      onChange={(e) =>
                        setCreateDraft((p) => ({ ...p, storage_unit: e.target.value }))
                      }
                    >
                      {STORAGE_UNITS.map((u) => (
                        <option key={u.value} value={u.value}>
                          {u.label}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>

                <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
                  bytes:{" "}
                  <span className="font-mono">
                    {toFa(toBytes(createDraft.storage_value, createDraft.storage_unit))}
                  </span>{" "}
                  • نمایش:{" "}
                  <b className="font-extrabold">
                    {bytesToHuman(toBytes(createDraft.storage_value, createDraft.storage_unit))}
                  </b>
                </div>
              </Field>

              <Field label="فعال/غیرفعال">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">is_active</div>
                  <Toggle
                    value={createDraft.is_active}
                    onToggle={() => setCreateDraft((p) => ({ ...p, is_active: !p.is_active }))}
                  />
                </div>
              </Field>

              <Field label="monthly_enabled">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">monthly</div>
                  <Toggle
                    value={createDraft.monthly_enabled}
                    onToggle={() =>
                      setCreateDraft((p) => ({ ...p, monthly_enabled: !p.monthly_enabled }))
                    }
                    labelOn="روشن"
                    labelOff="خاموش"
                  />
                </div>
              </Field>

              <Field label="yearly_enabled">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">yearly</div>
                  <Toggle
                    value={createDraft.yearly_enabled}
                    onToggle={() =>
                      setCreateDraft((p) => ({ ...p, yearly_enabled: !p.yearly_enabled }))
                    }
                    labelOn="روشن"
                    labelOff="خاموش"
                  />
                </div>
              </Field>

              {createDraft.yearly_enabled ? (
                <>
                  <Field label="yearly_discount_percent" hint="۰ تا ۱۰۰">
                    <div className={INPUT_BASE}>
                      <input
                        type="number"
                        className={INPUT}
                        value={createDraft.yearly_discount_percent}
                        onChange={(e) =>
                          setCreateDraft((p) => ({ ...p, yearly_discount_percent: e.target.value }))
                        }
                        min="0"
                        max="100"
                      />
                    </div>
                  </Field>

                  <Field label="yearly_duration_days" hint="مثلاً 365">
                    <div className={INPUT_BASE}>
                      <input
                        type="number"
                        className={INPUT}
                        value={createDraft.yearly_duration_days}
                        onChange={(e) =>
                          setCreateDraft((p) => ({ ...p, yearly_duration_days: e.target.value }))
                        }
                        min="1"
                      />
                    </div>
                  </Field>
                </>
              ) : null}
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                disabled={mutCreatePlan.isPending}
                onClick={() => setCreateOpen(false)}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition disabled:opacity-60"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutCreatePlan.isPending}
                onClick={submitCreate}
                className="px-4 py-2 rounded-xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                  hover:bg-black/5 dark:hover:bg-white/10 transition inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                {mutCreatePlan.isPending ? (
                  <>
                    <TbRefresh className="w-4 h-4 animate-spin text-[#43BEFF] dark:text-white" />
                    درحال ساخت...
                  </>
                ) : (
                  <>
                    <TbCheck className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                    ساخت
                  </>
                )}
              </button>
            </div>
          </div>
        </Modal>

        {/* ---------------- Edit Plan Modal ---------------- */}
        <Modal
          open={editOpen}
          title={`ویرایش پلن: ${editPlan?.name || "-"}`}
          onClose={() => !mutPatchPlan.isPending && setEditOpen(false)}
          widthClass="max-w-3xl"
        >
          <div className="space-y-4">
            <div className="grid md:grid-cols-2 gap-3">
              <Field label="name">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={editDraft.name}
                    onChange={(e) => setEditDraft((p) => ({ ...p, name: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="plan_type">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">نوع پلن</div>
                  <div className="flex items-center gap-2">
                    <button
                      type="button"
                      onClick={() => setEditDraft((p) => ({ ...p, plan_type: "personal" }))}
                      className={cn(
                        "px-3 py-2 rounded-xl border text-sm inline-flex items-center gap-2 transition",
                        editDraft.plan_type === "personal"
                          ? "border-[#43BEFF66] bg-[#43BEFF14]"
                          : "border-black/10 dark:border-white/10 bg-white/60 dark:bg-white/10"
                      )}
                    >
                      <TbUserCircle className="w-4 h-4" />
                      شخصی
                    </button>
                    <button
                      type="button"
                      onClick={() => setEditDraft((p) => ({ ...p, plan_type: "org" }))}
                      className={cn(
                        "px-3 py-2 rounded-xl border text-sm inline-flex items-center gap-2 transition",
                        editDraft.plan_type === "org"
                          ? "border-[#43BEFF66] bg-[#43BEFF14]"
                          : "border-black/10 dark:border-white/10 bg-white/60 dark:bg-white/10"
                      )}
                    >
                      <TbBuilding className="w-4 h-4" />
                      سازمانی
                    </button>
                  </div>
                </div>
              </Field>

              <Field label="price">
                <div className={INPUT_BASE}>
                  <input
                    type="number"
                    className={INPUT}
                    value={editDraft.price}
                    onChange={(e) => setEditDraft((p) => ({ ...p, price: e.target.value }))}
                  />
                </div>
              </Field>

              <Field label="duration_days">
                <div className={INPUT_BASE}>
                  <input
                    type="number"
                    className={INPUT}
                    value={editDraft.duration_days}
                    onChange={(e) =>
                      setEditDraft((p) => ({ ...p, duration_days: e.target.value }))
                    }
                  />
                </div>
              </Field>

              <Field label="storage_limit" hint="به bytes ارسال می‌شود">
                <div className="grid grid-cols-[1fr_120px] gap-2">
                  <div className={INPUT_BASE}>
                    <input
                      type="number"
                      className={INPUT}
                      value={editDraft.storage_value}
                      onChange={(e) =>
                        setEditDraft((p) => ({ ...p, storage_value: e.target.value }))
                      }
                      min="0"
                      step="0.1"
                    />
                  </div>
                  <div className={INPUT_BASE}>
                    <select
                      className={cn(INPUT, "px-3")}
                      value={editDraft.storage_unit}
                      onChange={(e) =>
                        setEditDraft((p) => ({ ...p, storage_unit: e.target.value }))
                      }
                    >
                      {STORAGE_UNITS.map((u) => (
                        <option key={u.value} value={u.value}>
                          {u.label}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>
                <div className="mt-1 text-[11px] text-black/50 dark:text-white/60">
                  bytes:{" "}
                  <span className="font-mono">
                    {toFa(toBytes(editDraft.storage_value, editDraft.storage_unit))}
                  </span>{" "}
                  • نمایش:{" "}
                  <b className="font-extrabold">
                    {bytesToHuman(toBytes(editDraft.storage_value, editDraft.storage_unit))}
                  </b>
                </div>
              </Field>

              <Field label="فعال/غیرفعال">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">is_active</div>
                  <Toggle
                    value={editDraft.is_active}
                    onToggle={() => setEditDraft((p) => ({ ...p, is_active: !p.is_active }))}
                  />
                </div>
              </Field>

              <Field label="monthly_enabled">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">monthly</div>
                  <Toggle
                    value={editDraft.monthly_enabled}
                    onToggle={() =>
                      setEditDraft((p) => ({ ...p, monthly_enabled: !p.monthly_enabled }))
                    }
                    labelOn="روشن"
                    labelOff="خاموش"
                  />
                </div>
              </Field>

              <Field label="yearly_enabled">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">yearly</div>
                  <Toggle
                    value={editDraft.yearly_enabled}
                    onToggle={() =>
                      setEditDraft((p) => ({ ...p, yearly_enabled: !p.yearly_enabled }))
                    }
                    labelOn="روشن"
                    labelOff="خاموش"
                  />
                </div>
              </Field>

              {editDraft.yearly_enabled ? (
                <>
                  <Field label="yearly_discount_percent" hint="۰ تا ۱۰۰">
                    <div className={INPUT_BASE}>
                      <input
                        type="number"
                        className={INPUT}
                        value={editDraft.yearly_discount_percent}
                        onChange={(e) =>
                          setEditDraft((p) => ({ ...p, yearly_discount_percent: e.target.value }))
                        }
                        min="0"
                        max="100"
                      />
                    </div>
                  </Field>

                  <Field label="yearly_duration_days" hint="مثلاً 365">
                    <div className={INPUT_BASE}>
                      <input
                        type="number"
                        className={INPUT}
                        value={editDraft.yearly_duration_days}
                        onChange={(e) =>
                          setEditDraft((p) => ({ ...p, yearly_duration_days: e.target.value }))
                        }
                        min="1"
                      />
                    </div>
                  </Field>
                </>
              ) : null}
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                disabled={mutPatchPlan.isPending}
                onClick={() => setEditOpen(false)}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition disabled:opacity-60"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutPatchPlan.isPending || !editPlan?.id}
                onClick={submitEditPlan}
                className="px-4 py-2 rounded-xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                  hover:bg-black/5 dark:hover:bg-white/10 transition inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                {mutPatchPlan.isPending ? (
                  <>
                    <TbRefresh className="w-4 h-4 animate-spin text-[#43BEFF] dark:text-white" />
                    درحال ذخیره...
                  </>
                ) : (
                  <>
                    <TbCheck className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                    ذخیره
                  </>
                )}
              </button>
            </div>
          </div>
        </Modal>

        {/* ---------------- Edit Subscription Modal ---------------- */}
        <Modal
          open={subEditOpen}
          title={`ویرایش اشتراک: ${
            subCurrent?.user_email || `User #${toFa(subCurrent?.user)}`
          }`}
          onClose={() => !mutPatchSub.isPending && setSubEditOpen(false)}
          widthClass="max-w-2xl"
        >
          <div className="space-y-4">
            <div className={cn(SOFT, "p-3")}>
              <div className="text-sm font-extrabold">{subCurrent?.plan_name || "-"}</div>
              <div className="mt-1 text-[11px] text-black/55 dark:text-white/60">
                sub_id: <span className="font-mono">{String(subCurrent?.id || "-")}</span>
              </div>
              <div className="mt-1 text-[11px] text-black/55 dark:text-white/60">
                started: <span className="font-mono">{fmtDate(subCurrent?.started_at)}</span>
              </div>
              <div className="mt-1 text-[11px] text-black/55 dark:text-white/60">
                ends:{" "}
                <span className="font-mono">
                  {subCurrent?.ends_at ? fmtDate(subCurrent.ends_at) : "—"}
                </span>
              </div>
            </div>

            <div className="grid md:grid-cols-2 gap-3">
              <Field label="is_active">
                <div className={cn(SOFT, "p-3 flex items-center justify-between")}>
                  <div className="text-sm font-bold">active</div>
                  <Toggle
                    value={subDraft.is_active}
                    onToggle={() => setSubDraft((p) => ({ ...p, is_active: !p.is_active }))}
                  />
                </div>
              </Field>

              <Field label="ended_at" hint="خالی = null">
                <div className={INPUT_BASE}>
                  <input
                    className={INPUT}
                    value={subDraft.ended_at || ""}
                    onChange={(e) => setSubDraft((p) => ({ ...p, ended_at: e.target.value }))}
                    placeholder="2025-12-28T02:40:27.422Z یا خالی"
                  />
                </div>
              </Field>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                disabled={mutPatchSub.isPending}
                onClick={() => setSubEditOpen(false)}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition disabled:opacity-60"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutPatchSub.isPending || !subCurrent?.id}
                onClick={submitEditSub}
                className="px-4 py-2 rounded-xl shadow border border-black/10 dark:border-white/10 bg-white dark:bg-[#16325b]
                  hover:bg-black/5 dark:hover:bg-white/10 transition inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                {mutPatchSub.isPending ? (
                  <>
                    <TbRefresh className="w-4 h-4 animate-spin text-[#43BEFF] dark:text-white" />
                    درحال ذخیره...
                  </>
                ) : (
                  <>
                    <TbCheck className="w-4 h-4 text-[#43BEFF] dark:text-white" />
                    ذخیره
                  </>
                )}
              </button>
            </div>
          </div>
        </Modal>

        {/* ---------------- Delete Subscription Modal ---------------- */}
        <Modal
          open={subDeleteOpen}
          title="حذف اشتراک"
          onClose={() => !mutDeleteSub.isPending && setSubDeleteOpen(false)}
          widthClass="max-w-xl"
        >
          <div className="space-y-3">
            <div className={cn(SOFT, "p-4")}>
              <div className="text-sm font-extrabold text-black dark:text-white">
                مطمئنی می‌خوای این اشتراک حذف بشه؟
              </div>
              <div className="mt-2 text-xs text-black/55 dark:text-white/60 space-y-1">
                <div>
                  user: <b>{subCurrent?.user_email || `#${toFa(subCurrent?.user)}`}</b>
                </div>
                <div>
                  plan: <b>{subCurrent?.plan_name || "-"}</b>
                </div>
                <div>
                  sub_id: <span className="font-mono">{String(subCurrent?.id || "-")}</span>
                </div>
              </div>
            </div>

            <div className="flex flex-col sm:flex-row gap-2 sm:justify-end">
              <button
                type="button"
                disabled={mutDeleteSub.isPending}
                onClick={() => setSubDeleteOpen(false)}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition disabled:opacity-60"
              >
                انصراف
              </button>

              <button
                type="button"
                disabled={mutDeleteSub.isPending || !subCurrent?.id}
                onClick={doDeleteSub}
                className="px-4 py-2 rounded-xl shadow border border-red-500/25 bg-red-500/10 hover:bg-red-500/15
                  transition text-red-700 dark:text-red-200 inline-flex items-center justify-center gap-2 disabled:opacity-60"
              >
                <TbTrash className="w-4 h-4" />
                {mutDeleteSub.isPending ? "درحال حذف..." : "حذف"}
              </button>
            </div>
          </div>
        </Modal>

        {/* ---------------- Users modal ---------------- */}
        <Modal
          open={uOpen}
          title="کاربران (فقط نمایش)"
          onClose={() => setUOpen(false)}
          widthClass="max-w-3xl"
        >
          <div className="space-y-3">
            <div className="grid md:grid-cols-[1fr_240px] gap-2">
              <div className={cn(INPUT_BASE)}>
                <div className="absolute right-3 top-1/2 -translate-y-1/2 opacity-70">
                  <TbSearch className="w-5 h-5" />
                </div>
                <input
                  className={cn(INPUT, "pr-11")}
                  placeholder="جستجوی کاربر..."
                  value={uq}
                  onChange={(e) => setUq(e.target.value)}
                />
              </div>

              <DropdownPortal
                id="users-active-filter"
                menu={menu}
                setMenu={setMenu}
                label="وضعیت"
                value={uActive}
                options={activeOptions}
                onChange={(v) => setUActive(v)}
                width={220}
              />
            </div>

            {qUsers.error ? (
              <div className={cn("rounded-2xl border border-amber-500/25 bg-amber-500/10 p-3")}>
                <div className="flex items-start gap-2">
                  <TbAlertTriangle className="w-5 h-5 mt-0.5" />
                  <div className="text-sm">
                    <div className="font-extrabold">خطا در دریافت کاربران</div>
                    <div className="text-xs opacity-80 mt-1">{getErrMsg(qUsers.error)}</div>
                  </div>
                </div>
              </div>
            ) : null}

            <div className="max-h-[60vh] overflow-auto space-y-2 pr-1">
              {qUsers.isLoading ? (
                [...Array(8)].map((_, i) => (
                  <div key={i} className={cn(SOFT, "p-3 animate-pulse")}>
                    <div className="h-5 w-44 rounded bg-black/5 dark:bg-white/10" />
                    <div className="mt-2 h-4 w-64 rounded bg-black/5 dark:bg-white/10" />
                  </div>
                ))
              ) : users.length === 0 ? (
                <div className="py-10 text-center text-black/50 dark:text-white/60">
                  کاربری یافت نشد.
                </div>
              ) : (
                users.map((u) => (
                  <div
                    key={u?.id}
                    className={cn(
                      "rounded-2xl border border-black/10 dark:border-white/10 p-3",
                      "bg-white/70 dark:bg-white/5"
                    )}
                  >
                    <div className="flex items-start justify-between gap-2">
                      <div className="min-w-0">
                        <div className="font-extrabold truncate inline-flex items-center gap-2">
                          <TbUser className="w-4 h-4 opacity-70" />
                          {u?.username || `User #${toFa(u?.id)}`}
                        </div>
                        <div className="mt-1 text-[11px] text-black/55 dark:text-white/60 truncate">
                          {u?.email || "—"} • {u?.phone || "—"}
                        </div>
                      </div>
                      <Badge tone={u?.is_active ? "success" : "danger"}>
                        {u?.is_active ? "Active" : "Inactive"}
                      </Badge>
                    </div>
                  </div>
                ))
              )}
            </div>

            <div className="flex justify-end">
              <button
                type="button"
                onClick={() => setUOpen(false)}
                className="px-4 py-2 rounded-xl border border-black/10 dark:border-white/10 hover:bg-black/5 dark:hover:bg-white/10 transition"
              >
                بستن
              </button>
            </div>
          </div>
        </Modal>
      </div>
    </PageShell>
  );
}
