"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { AppShell } from "@/components/app/AppShell";
import { PageHeader } from "@/components/layout/PageHeader";
import { DataTable, DataTableEmpty } from "@/components/layout/DataTable";
import { Alert } from "@/components/ui/Alert";
import { Button } from "@/components/ui/Button";
import { Field, Input, Select } from "@/components/ui/Field";
import { PageContentSkeleton } from "@/components/ui/Skeleton";
import {
  CannedTopicEditor,
  padCannedMessages,
  type CannedTopicRow,
} from "@/components/messaging/CannedTopicEditor";
import { TemplateEditorCard, type CatalogChannel, type MessageTemplateRow, type TemplateMediaItem } from "@/components/messaging/TemplateEditorCard";
import {
  AdminUser,
  ApiError,
  BranchItem,
  Paginated,
  apiGet,
  apiPost,
  apiPostFormData,
  apiPut,
  getStoredUser,
} from "@/lib/api";
import { getActiveBranchId, getActiveRole } from "@/lib/session-context";

type TabId = "providers" | "templates" | "canned" | "dispatches" | "failed" | "policies";

const GROUP_ORDER = ["سیستم", "حضور و غیاب", "پیش‌ثبت‌نام", "انضباط"];

const MAIN_TABS: Array<{ id: TabId; label: string; icon: string; superAdminOnly?: boolean }> = [
  { id: "providers", label: "اتصال به CRM", icon: "M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h10v2H4v-2z", superAdminOnly: true },
  {
    id: "templates",
    label: "قالب پیام‌ها",
    icon: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zm1 7V3.5L18.5 9H15zM8 13h8v2H8v-2zm0 4h5v2H8v-2z",
  },
  {
    id: "canned",
    label: "پیام‌های پیش‌فرض",
    icon: "M4 6h16v2H4V6zm0 5h10v2H4v-2zm0 5h16v2H4v-2z",
  },
  {
    id: "dispatches",
    label: "سابقه ارسال",
    icon: "M13 3a9 9 0 1 0 8.94 10h-2.02A7 7 0 1 1 13 5v3l4-3.5L13 1v2z",
  },
  {
    id: "failed",
    label: "ناموفق",
    icon: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z",
  },
  {
    id: "policies",
    label: "سیاست‌ها",
    icon: "M12 1 3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
  },
];

function NavTabs<T extends string>({
  items,
  value,
  onChange,
  size = "md",
}: {
  items: Array<{ id: T; label: string; icon?: string }>;
  value: T;
  onChange: (id: T) => void;
  size?: "md" | "sm";
}) {
  return (
    <div className="flex flex-wrap gap-x-1 border-b border-[var(--border)]">
      {items.map((item) => {
        const active = value === item.id;
        return (
          <button
            key={item.id}
            type="button"
            onClick={() => onChange(item.id)}
            className={`-mb-px inline-flex items-center gap-2 border-b-2 px-3 ${
              size === "sm" ? "py-2 text-[13px]" : "py-3 text-sm"
            } font-semibold transition ${
              active
                ? "border-primary text-primary"
                : "border-transparent text-slate-500 hover:text-slate-800"
            }`}
          >
            {item.icon ? (
              <svg viewBox="0 0 24 24" className="h-4 w-4 shrink-0" fill="currentColor" aria-hidden>
                <path d={item.icon} />
              </svg>
            ) : null}
            {item.label}
          </button>
        );
      })}
    </div>
  );
}

type CrmSchoolRow = {
  branch_id: number;
  name: string;
  code?: string | null;
  token_set: boolean;
  is_active: boolean;
};

type CrmConnection = {
  send_url: string;
  enabled_channels: string[];
  platforms: Array<{ key: string; label: string; via: string; enabled: boolean }>;
  schools: CrmSchoolRow[];
  org_token_set: boolean;
  driver: string;
};

type DispatchRow = {
  id: number;
  event_key: string;
  channel: string;
  recipient: string;
  message: string;
  status: string;
  driver: string;
  created_at?: string | null;
};

function secretHint(set: boolean): string {
  return set ? "ثبت شده — برای تغییر، مقدار جدید وارد کنید" : "هنوز ثبت نشده";
}

const CRM_TEST_TEXT = "این یک پیام تست است";

export default function MessagingPage() {
  const user = useMemo(() => getStoredUser<AdminUser>(), []);
  const role = getActiveRole();
  const isSuperAdmin = role === "super_admin" || role === "developer" || Boolean(user?.roles?.includes("super_admin") || user?.roles?.includes("developer"));
  const activeBranchId = getActiveBranchId();

  const [tab, setTab] = useState<TabId>("templates");
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);

  const [channels, setChannels] = useState<CatalogChannel[]>([]);
  const [branches, setBranches] = useState<BranchItem[]>([]);
  const [crm, setCrm] = useState<CrmConnection | null>(null);
  const [sendUrl, setSendUrl] = useState("");
  const [enabledChannels, setEnabledChannels] = useState<string[]>([]);
  const [orgToken, setOrgToken] = useState("");
  const [schoolTokens, setSchoolTokens] = useState<Record<number, string>>({});
  const [crmTest, setCrmTest] = useState<{ branchId: number; name: string } | null>(null);
  const [crmTestChannel, setCrmTestChannel] = useState("sms");
  const [crmTestMobile, setCrmTestMobile] = useState("");
  const [crmTestBusy, setCrmTestBusy] = useState(false);
  const [crmTestFeedback, setCrmTestFeedback] = useState<{ tone: "success" | "error"; text: string } | null>(null);
  const [templates, setTemplates] = useState<MessageTemplateRow[]>([]);
  const [dispatches, setDispatches] = useState<DispatchRow[]>([]);
  const [failedRows, setFailedRows] = useState<Array<{ id: number; error_code?: string; error_message?: string; delivery_id: number }>>([]);
  const [policyRows, setPolicyRows] = useState<Array<{ id: number; name: string; scope: string; limit_count: number; window_seconds: number; action: string; enabled: boolean }>>([]);
  const [retryingId, setRetryingId] = useState<number | null>(null);

  const [scopeId, setScopeId] = useState<number>(0);
  const [templateDrafts, setTemplateDrafts] = useState<Record<string, MessageTemplateRow>>({});
  const [templateGroup, setTemplateGroup] = useState<string>("all");
  const [cannedTopics, setCannedTopics] = useState<CannedTopicRow[]>([]);
  const [cannedDrafts, setCannedDrafts] = useState<Record<string, CannedTopicRow["messages"]>>({});
  const [cannedApplyAll, setCannedApplyAll] = useState<Record<string, boolean>>({});
  const [uploadingKey, setUploadingKey] = useState<string | null>(null);
  const [testMobile, setTestMobile] = useState("");
  const [testEvent, setTestEvent] = useState("pre_registration.submitted");

  const schoolScopeId = isSuperAdmin ? (scopeId > 0 ? scopeId : null) : activeBranchId;
  const editingOrg = isSuperAdmin && scopeId === 0;

  const loadCatalogAndBranches = useCallback(async () => {
    const [catalog, branchList] = await Promise.all([
      apiGet<{
        channels: CatalogChannel[];
        events: Array<{ key: string }>;
      }>("/messaging/catalog"),
      apiGet<BranchItem[]>("/branches"),
    ]);
    setChannels(catalog.channels.filter((channel) => channel.platform !== false && channel.key !== "inbox" && channel.key !== "bale"));
    setBranches(branchList);
    if (catalog.events[0]) {
      setTestEvent((current) =>
        catalog.events.some((event) => event.key === current) ? current : catalog.events[0].key,
      );
    }
    if (!isSuperAdmin && activeBranchId) {
      setScopeId(activeBranchId);
    }
  }, [activeBranchId, isSuperAdmin]);

  const loadProviders = useCallback(async () => {
    if (!isSuperAdmin) return;
    const data = await apiGet<CrmConnection>("/messaging/providers");
    setCrm(data);
    setSendUrl(data.send_url ?? "");
    setEnabledChannels(data.enabled_channels ?? []);
    setOrgToken("");
    setSchoolTokens({});
  }, [isSuperAdmin]);

  const loadTemplates = useCallback(async () => {
    const query = schoolScopeId ? `?branch_id=${schoolScopeId}` : "";
    const rows = await apiGet<MessageTemplateRow[]>(`/messaging/templates${query}`);
    setTemplates(rows);
    setTemplateDrafts(
      Object.fromEntries(
        rows.map((row) => [
          row.key,
          {
            ...row,
            sms_body: row.sms_body || row.body,
            messenger_body: row.messenger_body || row.body,
            media: row.media ?? [],
            apply_to_all_schools: false,
          },
        ]),
      ),
    );
  }, [schoolScopeId]);

  const loadCanned = useCallback(async () => {
    const query = schoolScopeId ? `?branch_id=${schoolScopeId}` : "";
    const rows = await apiGet<CannedTopicRow[]>(`/messaging/canned${query}`);
    setCannedTopics(rows);
    setCannedDrafts(
      Object.fromEntries(
        rows.map((row) => [
          row.key,
          row.messages
            .filter((item) => item.title.trim() || item.body.trim())
            .map((item) => ({ ...item })),
        ]),
      ),
    );
    setCannedApplyAll({});
  }, [schoolScopeId]);

  const loadFailed = useCallback(async () => {
    const page = await apiGet<Paginated<{ id: number; error_code?: string; error_message?: string; delivery_id: number }>>(
      "/messaging/failed",
    );
    setFailedRows(page.data ?? []);
  }, []);

  const loadPolicies = useCallback(async () => {
    const rows = await apiGet<Array<{ id: number; name: string; scope: string; limit_count: number; window_seconds: number; action: string; enabled: boolean }>>(
      "/messaging/policies",
    );
    setPolicyRows(rows);
  }, []);

  const loadDispatches = useCallback(async () => {
    const query = schoolScopeId ? `?branch_id=${schoolScopeId}` : "";
    const page = await apiGet<Paginated<DispatchRow>>(`/messaging/dispatches${query}`);
    setDispatches(page.data ?? []);
  }, [schoolScopeId]);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);
    loadCatalogAndBranches()
      .catch((err) => {
        if (!cancelled) {
          setError(err instanceof ApiError ? err.message : "خطا در بارگذاری کاتالوگ پیام‌رسانی");
        }
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [loadCatalogAndBranches]);

  useEffect(() => {
    if (loading || !isSuperAdmin) return;
    void loadProviders().catch((err) => {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری اتصال CRM");
    });
  }, [isSuperAdmin, loadProviders, loading]);

  useEffect(() => {
    if (loading) return;
    void loadTemplates().catch((err) => {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری قالب‌ها");
    });
  }, [loadTemplates, loading]);

  useEffect(() => {
    if (loading || tab !== "canned") return;
    void loadCanned().catch((err) => {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری پیام‌های پیش‌فرض");
    });
  }, [loadCanned, loading, tab]);

  useEffect(() => {
    if (loading || tab !== "dispatches") return;
    void loadDispatches().catch((err) => {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری سابقه ارسال");
    });
  }, [loadDispatches, loading, tab]);

  useEffect(() => {
    if (loading || tab !== "failed") return;
    void loadFailed().catch((err) => {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری پیام‌های ناموفق");
    });
  }, [loadFailed, loading, tab]);

  useEffect(() => {
    if (loading || tab !== "policies") return;
    void loadPolicies().catch((err) => {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری سیاست‌ها");
    });
  }, [loadPolicies, loading, tab]);

  const visibleTabs = useMemo(
    () => MAIN_TABS.filter((item) => !item.superAdminOnly || isSuperAdmin),
    [isSuperAdmin],
  );

  const groupedTemplates = useMemo(() => {
    const groups = new Map<string, MessageTemplateRow[]>();
    for (const row of templates) {
      if (templateGroup !== "all" && row.group !== templateGroup) continue;
      const list = groups.get(row.group) ?? [];
      list.push(row);
      groups.set(row.group, list);
    }
    return Array.from(groups.entries());
  }, [templateGroup, templates]);

  const templateGroups = useMemo(() => {
    const names = Array.from(new Set(templates.map((row) => row.group).filter(Boolean)));
    return names.sort((a, b) => {
      const ai = GROUP_ORDER.indexOf(a);
      const bi = GROUP_ORDER.indexOf(b);
      return (ai === -1 ? 99 : ai) - (bi === -1 ? 99 : bi);
    });
  }, [templates]);

  const platformChannels = channels.filter((channel) => channel.platform !== false && channel.key !== "inbox" && channel.key !== "bale");
  const smsChannels = platformChannels.filter((channel) => (channel.family ?? "sms") === "sms");
  const messengerChannels = platformChannels.filter((channel) => channel.family === "messenger" || channel.family === "email");
  const internalChannels = platformChannels.filter((channel) => channel.family === "internal");

  const saveProvider = async () => {
    setSaving(true);
    setError(null);
    setMessage(null);
    try {
      const saved = await apiPut<CrmConnection>("/messaging/providers", {
        send_url: sendUrl.trim(),
        enabled_channels: enabledChannels,
        ...(orgToken ? { org_token: orgToken } : {}),
        schools: (crm?.schools ?? []).map((school) => ({
          branch_id: school.branch_id,
          is_active: school.is_active,
          ...(schoolTokens[school.branch_id] ? { token: schoolTokens[school.branch_id] } : {}),
        })),
      });
      setCrm(saved);
      setSendUrl(saved.send_url ?? "");
      setEnabledChannels(saved.enabled_channels ?? []);
      setOrgToken("");
      setSchoolTokens({});
      setMessage("اتصال CRM ذخیره شد. پیامک، سفیر بله، تلگرام، واتساپ و ایمیل از همین مسیر ارسال می‌شوند.");
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "ذخیره اتصال CRM ناموفق بود.");
    } finally {
      setSaving(false);
    }
  };

  const crmTestPlatforms = useMemo(() => {
    const platforms = (crm?.platforms ?? []).filter(
      (platform) => platform.via === "crm" || platform.via === "internal_social",
    );
    const enabled = platforms.filter((platform) => enabledChannels.includes(platform.key));
    return enabled.length ? enabled : platforms;
  }, [crm?.platforms, enabledChannels]);

  const isInternalSocialTest = crmTestChannel === "internal_social";

  const openCrmTest = (branchId: number, name: string) => {
    setCrmTest({ branchId, name });
    setCrmTestChannel(crmTestPlatforms[0]?.key ?? "sms");
    setCrmTestMobile("");
    setCrmTestFeedback(null);
  };

  const sendCrmConnectionTest = async () => {
    if (!crmTest) return;
    if (!isInternalSocialTest && !/^09\d{9}$/.test(crmTestMobile)) return;
    setCrmTestBusy(true);
    setCrmTestFeedback(null);
    try {
      const token =
        crmTest.branchId === 0 ? orgToken.trim() : (schoolTokens[crmTest.branchId] ?? "").trim();
      const result = await apiPost<{ sent: boolean; message: string; crm_message_id: string | null }>(
        "/messaging/providers/test",
        {
          branch_id: crmTest.branchId,
          channel: crmTestChannel,
          ...(isInternalSocialTest ? {} : { mobile: crmTestMobile }),
          send_url: sendUrl.trim() || undefined,
          ...(!isInternalSocialTest && token ? { token } : {}),
        },
      );
      setCrmTestFeedback({
        tone: result.sent ? "success" : "error",
        text: result.message,
      });
    } catch (err) {
      setCrmTestFeedback({
        tone: "error",
        text: err instanceof ApiError ? err.message : "ارسال پیام تست ناموفق بود.",
      });
    } finally {
      setCrmTestBusy(false);
    }
  };

  const saveTemplate = async (key: string) => {
    const row = templateDrafts[key];
    if (!row) return;
    if (!editingOrg && row.account !== "school") {
      setError("رویدادهای سیستمی فقط در سطح هلدینگ قابل ویرایش هستند.");
      return;
    }
    setSaving(true);
    setError(null);
    setMessage(null);
    try {
      const result = await apiPut<{ applied_branch_count?: number }>("/messaging/templates", {
        event_key: key,
        branch_id: editingOrg ? 0 : schoolScopeId,
        enabled: row.enabled,
        body: row.sms_body || row.body,
        sms_body: row.sms_body || row.body,
        messenger_body: row.messenger_body || row.sms_body || row.body,
        channels: row.channels.length ? row.channels : ["sms"],
        media: row.media ?? [],
        apply_to_all_schools: Boolean(editingOrg && row.apply_to_all_schools),
      });
      await loadTemplates();
      const applied = result.applied_branch_count ?? 1;
      setMessage(
        applied > 1
          ? `قالب ذخیره شد و روی ${applied} محدوده (هلدینگ و مدارس) اعمال شد.`
          : "قالب پیام ذخیره شد.",
      );
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "ذخیره قالب ناموفق بود.");
    } finally {
      setSaving(false);
    }
  };

  const saveCanned = async (key: string) => {
    const messages = cannedDrafts[key];
    if (!messages) return;
    setSaving(true);
    setError(null);
    setMessage(null);
    try {
      const result = await apiPut<{ applied_branch_count?: number }>("/messaging/canned", {
        topic_key: key,
        branch_id: editingOrg ? 0 : schoolScopeId,
        messages: padCannedMessages(messages),
        apply_to_all_schools: Boolean(editingOrg && cannedApplyAll[key]),
      });
      await loadCanned();
      const applied = result.applied_branch_count ?? 1;
      const topicLabel = cannedTopics.find((row) => row.key === key)?.label ?? key;
      setMessage(
        applied > 1
          ? `پیام‌های پیش‌فرض ذخیره شد و روی ${applied} محدوده (هلدینگ و مدارس) اعمال شد.`
          : `پیام‌های پیش‌فرض «${topicLabel}» ذخیره شد.`,
      );
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "ذخیره پیام‌های پیش‌فرض ناموفق بود.");
    } finally {
      setSaving(false);
    }
  };

  const sendTest = async () => {
    setSaving(true);
    setError(null);
    setMessage(null);
    try {
      const result = await apiPost<{ sent: number }>("/messaging/test-send", {
        event_key: testEvent,
        mobile: testMobile,
        ...(schoolScopeId ? { branch_id: schoolScopeId } : {}),
      });
      setMessage(`ارسال آزمایشی ثبت شد (${result.sent} کانال). متن در لاگ سامانه آزمایشی ذخیره شده است.`);
      if (tab === "dispatches") {
        await loadDispatches();
      }
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "ارسال آزمایشی ناموفق بود.");
    } finally {
      setSaving(false);
    }
  };

  const insertPlaceholder = (key: string, placeholder: string, field: "sms_body" | "messenger_body") => {
    setTemplateDrafts((prev) => {
      const row = prev[key];
      if (!row) return prev;
      return { ...prev, [key]: { ...row, [field]: `${row[field] ?? ""}{${placeholder}}` } };
    });
  };

  const toggleChannel = (key: string, channel: string) => {
    setTemplateDrafts((prev) => {
      const row = prev[key];
      if (!row) return prev;
      const has = row.channels.includes(channel);
      const next = has ? row.channels.filter((c) => c !== channel) : [...row.channels, channel];
      return { ...prev, [key]: { ...row, channels: next.length ? next : [channel] } };
    });
  };

  const uploadTemplateImage = async (key: string, file: File) => {
    setUploadingKey(key);
    setError(null);
    try {
      const uploaded = await apiPostFormData<TemplateMediaItem>("/messaging/templates/media", (() => {
        const form = new FormData();
        form.append("image", file);
        return form;
      })());
      setTemplateDrafts((prev) => {
        const row = prev[key];
        if (!row) return prev;
        return { ...prev, [key]: { ...row, media: [{ type: "image", url: uploaded.url, name: uploaded.name }] } };
      });
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "آپلود تصویر ناموفق بود.");
    } finally {
      setUploadingKey(null);
    }
  };

  if (loading) {
    return (
      <AppShell title="پیامک و اطلاع‌رسانی" subtitle="سامانه‌ها، قالب‌ها و کانال‌های ارسال">
        <PageContentSkeleton />
      </AppShell>
    );
  }

  return (
    <AppShell title="پیامک و اطلاع‌رسانی" subtitle="سامانه‌ها، قالب‌ها و کانال‌های ارسال">
      <PageHeader
        title="پیامک و اطلاع‌رسانی"
        subtitle="ارسال پیامک، سفیر بله، تلگرام، واتساپ و ایمیل از CRM خارجی است. شبکه اجتماعی سامانه داخلی است."
      />

      {error ? <Alert tone="error">{error}</Alert> : null}
      {message ? <Alert tone="success">{message}</Alert> : null}

      {isSuperAdmin ? (
        <div className="mb-4 max-w-sm">
          <Field label="محدوده تنظیم">
            <Select value={String(scopeId)} onChange={(e) => setScopeId(Number(e.target.value))}>
              <option value="0">هلدینگ (سامانه سیستم)</option>
              {branches.map((branch) => (
                <option key={branch.id} value={branch.id}>
                  {branch.name}
                </option>
              ))}
            </Select>
          </Field>
        </div>
      ) : null}

      <NavTabs items={visibleTabs} value={tab} onChange={setTab} />

      {tab === "providers" && isSuperAdmin ? (
        <div className="mt-4 space-y-4 rounded-2xl border border-[var(--border)] bg-white p-4">
          <Alert tone="info">
            همه پلتفرم‌های خارجی (پیامک، تلگرام، واتساپ، سفیر بله، ایمیل) به همین آدرس CRM می‌روند. شبکه اجتماعی
            سامانه برای هر گیرنده یک کانال یک‌طرفه «اطلاعیه‌های سامانه» می‌سازد؛ فقط همان کاربر می‌بیند و به CRM
            نمی‌رود.
          </Alert>
          <Field label="آدرس ارسال پیام در CRM">
            <Input
              value={sendUrl}
              onChange={(e) => setSendUrl(e.target.value)}
              placeholder="http://example.com/api/v1/messages/send"
              dir="ltr"
            />
          </Field>
          <div>
            <div className="mb-2 text-sm font-medium">پلتفرم‌های فعال سامانه</div>
            <div className="flex flex-wrap gap-x-5 gap-y-2 text-sm">
              {(crm?.platforms ?? []).map((platform) => (
                <label key={platform.key} className="inline-flex items-center gap-2">
                  <input
                    type="checkbox"
                    className="h-4 w-4 rounded border-slate-300 text-primary focus:ring-primary"
                    checked={enabledChannels.includes(platform.key)}
                    onChange={() => {
                      setEnabledChannels((current) =>
                        current.includes(platform.key)
                          ? current.filter((key) => key !== platform.key)
                          : [...current, platform.key],
                      );
                    }}
                  />
                  {platform.label}
                  {platform.via === "internal_social" ? (
                    <span className="text-xs text-[var(--muted)]">(کانال شخصی کاربر)</span>
                  ) : null}
                </label>
              ))}
            </div>
          </div>
          <div className="flex flex-wrap items-end gap-2">
            <div className="min-w-0 flex-1">
              <Field label="توکن پیش‌فرض هلدینگ (اختیاری)">
                <Input
                  value={orgToken}
                  onChange={(e) => setOrgToken(e.target.value)}
                  placeholder={secretHint(Boolean(crm?.org_token_set))}
                  dir="ltr"
                  type="password"
                  autoComplete="off"
                />
              </Field>
            </div>
            <Button
              variant="secondary"
              type="button"
              disabled={
                !enabledChannels.includes("internal_social") && !orgToken.trim() && !crm?.org_token_set
              }
              onClick={() => openCrmTest(0, "هلدینگ")}
            >
              تست
            </Button>
          </div>
          <div>
            <h3 className="mb-2 text-sm font-bold">توکن هر مدرسه</h3>
            <p className="mb-3 text-xs text-[var(--muted)]">
              برای ارسال واقعی، توکن همان مدرسه‌ای که پیام از آن می‌رود در هدر Authorization به‌صورت Bearer فرستاده می‌شود.
            </p>
            <DataTable
              columns={[
                { key: "school", label: "مدرسه" },
                { key: "token", label: "توکن" },
                { key: "status", label: "وضعیت" },
                { key: "test", label: "تست" },
              ]}
            >
              {(crm?.schools ?? []).length === 0 ? (
                <DataTableEmpty colSpan={4} message="مدرسه‌ای ثبت نشده است." />
              ) : (
                (crm?.schools ?? []).map((school) => (
                  <tr key={school.branch_id}>
                    <td className="px-3 py-2 text-sm">{school.name}</td>
                    <td className="px-3 py-2">
                      <Input
                        value={schoolTokens[school.branch_id] ?? ""}
                        onChange={(e) =>
                          setSchoolTokens((current) => ({ ...current, [school.branch_id]: e.target.value }))
                        }
                        placeholder={secretHint(school.token_set)}
                        dir="ltr"
                        type="password"
                        autoComplete="off"
                      />
                    </td>
                    <td className="px-3 py-2 text-xs text-[var(--muted)]">
                      {school.token_set ? "توکن دارد" : "بدون توکن"}
                    </td>
                    <td className="px-3 py-2">
                      <Button
                        variant="secondary"
                        type="button"
                        disabled={
                          !enabledChannels.includes("internal_social") &&
                          !school.token_set &&
                          !(schoolTokens[school.branch_id] ?? "").trim()
                        }
                        onClick={() => openCrmTest(school.branch_id, school.name)}
                      >
                        تست
                      </Button>
                    </td>
                  </tr>
                ))
              )}
            </DataTable>
          </div>
          <Button onClick={() => void saveProvider()} disabled={saving || !sendUrl.trim() || enabledChannels.length === 0}>
            ذخیره اتصال CRM
          </Button>
        </div>
      ) : null}

      {tab === "templates" ? (
        <div className="mt-4 space-y-4">
          <div className="rounded-xl border border-primary/20 bg-primary/5 px-4 py-3 text-sm leading-6 text-slate-700">
            برای پیامک یک متن جدا بنویسید. برای بله، تلگرام و واتساپ متن مشترک (با امکان عکس) تنظیم می‌شود. کانال
            کانال «شبکه اجتماعی سامانه» برای هر گیرنده یک کانال یک‌طرفه «اطلاعیه‌های سامانه» می‌سازد؛ پیام فقط برای
            همان کاربر دیده می‌شود و به CRM نمی‌رود.
          </div>
          <NavTabs
            size="sm"
            value={templateGroup}
            onChange={setTemplateGroup}
            items={[
              { id: "all", label: "همه دسته‌ها" },
              ...templateGroups.map((group) => ({ id: group, label: group })),
            ]}
          />
          {groupedTemplates.map(([group, rows]) => (
            <section key={group} className="space-y-4">
              {templateGroup === "all" ? (
                <h3 className="text-sm font-bold text-foreground">{group || "سایر"}</h3>
              ) : null}
              {rows.map((row) => {
                const draftRow = templateDrafts[row.key] ?? row;
                const readOnly = !editingOrg && row.account !== "school";
                return (
                  <TemplateEditorCard
                    key={row.key}
                    row={row}
                    draft={draftRow}
                    channels={[...smsChannels, ...messengerChannels, ...internalChannels]}
                    readOnly={readOnly}
                    saving={saving}
                    uploading={uploadingKey === row.key}
                    canApplyAll={Boolean(editingOrg && isSuperAdmin && row.account === "school")}
                    onChange={(patch) =>
                      setTemplateDrafts((prev) => ({
                        ...prev,
                        [row.key]: { ...draftRow, ...patch },
                      }))
                    }
                    onToggleChannel={(channel) => toggleChannel(row.key, channel)}
                    onInsertPlaceholder={(placeholder, field) => insertPlaceholder(row.key, placeholder, field)}
                    onUpload={(file) => void uploadTemplateImage(row.key, file)}
                    onSave={() => void saveTemplate(row.key)}
                  />
                );
              })}
            </section>
          ))}
        </div>
      ) : null}

      {tab === "canned" ? (
        <div className="mt-4 space-y-4">
          <div className="rounded-xl border border-primary/20 bg-primary/5 px-4 py-3 text-sm leading-6 text-slate-700">
            این پیام‌ها قالب سیستمی نیستند؛ عنوان و متن کامل‌اند تا در باکس ارسال ماژول‌ها (مثلاً ثبت تأخیر یا غیبت)
            از فهرست انتخاب شوند. هر موضوع تا ۶ پیام دارد. مدیر مدرسه برای مدرسه خودش ذخیره می‌کند؛ مدیر کل می‌تواند
            برای هلدینگ تعریف کند یا روی همه مدارس اعمال کند.
          </div>
          {cannedTopics.map((topic) => (
            <CannedTopicEditor
              key={topic.key}
              topic={topic}
              draft={cannedDrafts[topic.key] ?? topic.messages}
              saving={saving}
              canApplyAll={Boolean(editingOrg && isSuperAdmin)}
              applyToAll={Boolean(cannedApplyAll[topic.key])}
              onApplyToAllChange={(value) =>
                setCannedApplyAll((prev) => ({ ...prev, [topic.key]: value }))
              }
              onDraftChange={(messages) =>
                setCannedDrafts((prev) => ({ ...prev, [topic.key]: messages }))
              }
              onSave={() => void saveCanned(topic.key)}
            />
          ))}
        </div>
      ) : null}

      {tab === "dispatches" ? (
        <div className="mt-4 space-y-4">
          <div className="space-y-3 rounded-2xl border border-[var(--border)] bg-white p-4">
            <h3 className="text-sm font-bold">ارسال آزمایشی</h3>
            <div className="grid gap-3 md:grid-cols-2">
              <Field label="رویداد">
                <Select value={testEvent} onChange={(e) => setTestEvent(e.target.value)}>
                  {templates.map((row) => (
                    <option key={row.key} value={row.key}>
                      {row.label}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="شماره موبایل">
                <Input
                  value={testMobile}
                  onChange={(e) => setTestMobile(e.target.value)}
                  placeholder="09123456789"
                  dir="ltr"
                />
              </Field>
            </div>
            <Button onClick={() => void sendTest()} disabled={saving || !testMobile}>
              ثبت ارسال آزمایشی
            </Button>
          </div>

          <DataTable
            columns={[
              { key: "created", label: "زمان" },
              { key: "event", label: "رویداد" },
              { key: "channel", label: "کانال" },
              { key: "recipient", label: "گیرنده" },
              { key: "status", label: "وضعیت" },
              { key: "message", label: "متن" },
            ]}
          >
            {dispatches.length === 0 ? (
              <DataTableEmpty colSpan={6} message="هنوز ارسالی ثبت نشده است." />
            ) : (
              dispatches.map((row) => (
                <tr key={row.id}>
                  <td className="whitespace-nowrap px-3 py-2 text-xs text-[var(--muted)]">
                    {row.created_at ? new Date(row.created_at).toLocaleString("fa-IR") : "—"}
                  </td>
                  <td className="px-3 py-2 text-xs">{row.event_key}</td>
                  <td className="px-3 py-2 text-xs">{row.channel}</td>
                  <td className="px-3 py-2 text-xs" dir="ltr">
                    {row.recipient}
                  </td>
                  <td className="px-3 py-2 text-xs">{row.status}</td>
                  <td className="max-w-xs truncate px-3 py-2 text-xs">{row.message}</td>
                </tr>
              ))
            )}
          </DataTable>
        </div>
      ) : null}

      {tab === "failed" ? (
        <div className="mt-4">
        <DataTable
          columns={[
            { key: "id", label: "شناسه" },
            { key: "code", label: "کد خطا" },
            { key: "message", label: "پیام" },
            { key: "retry", label: "عملیات" },
          ]}
        >
          {failedRows.length === 0 ? (
            <DataTableEmpty colSpan={4} message="پیام ناموفقی نیست." />
          ) : (
            failedRows.map((row) => (
              <tr key={row.id}>
                <td className="px-3 py-2 text-xs">{row.id}</td>
                <td className="px-3 py-2 text-xs">{row.error_code}</td>
                <td className="px-3 py-2 text-xs">{row.error_message}</td>
                <td className="px-3 py-2 text-xs">
                  <Button
                    disabled={retryingId === row.delivery_id}
                    onClick={() => {
                      setRetryingId(row.delivery_id);
                      void apiPost(`/messaging/deliveries/${row.delivery_id}/retry`, {})
                        .then(() => loadFailed())
                        .catch((err) => setError(err instanceof ApiError ? err.message : "Retry ناموفق بود"))
                        .finally(() => setRetryingId(null));
                    }}
                  >
                    تلاش مجدد
                  </Button>
                </td>
              </tr>
            ))
          )}
        </DataTable>
        </div>
      ) : null}

      {tab === "policies" ? (
        <div className="mt-4">
        <DataTable
          columns={[
            { key: "name", label: "نام" },
            { key: "scope", label: "محدوده" },
            { key: "limit", label: "سقف" },
            { key: "window", label: "پنجره (ثانیه)" },
            { key: "action", label: "رفتار" },
          ]}
        >
          {policyRows.length === 0 ? (
            <DataTableEmpty colSpan={5} message="سیاستی ثبت نشده است." />
          ) : (
            policyRows.map((row) => (
              <tr key={row.id}>
                <td className="px-3 py-2 text-xs">{row.name}</td>
                <td className="px-3 py-2 text-xs">{row.scope}</td>
                <td className="px-3 py-2 text-xs">{row.limit_count}</td>
                <td className="px-3 py-2 text-xs">{row.window_seconds}</td>
                <td className="px-3 py-2 text-xs">{row.action}{row.enabled ? "" : " (خاموش)"}</td>
              </tr>
            ))
          )}
        </DataTable>
        </div>
      ) : null}

      {crmTest ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
          <div
            role="dialog"
            aria-modal="true"
            className="w-full max-w-md rounded-2xl border border-[var(--border)] bg-white p-5 shadow-xl"
          >
            <h3 className="text-base font-bold">تست ارسال — {crmTest.name}</h3>
            <p className="mt-1 text-sm text-[var(--muted)]">
              متن ارسالی: «{CRM_TEST_TEXT}»
              {isInternalSocialTest
                ? " — در کانال شخصی «اطلاعیه‌های سامانه» ثبت می‌شود و به CRM نمی‌رود."
                : null}
            </p>
            <div className="mt-4 space-y-3">
              <Field label="پلتفرم">
                <Select value={crmTestChannel} onChange={(e) => setCrmTestChannel(e.target.value)}>
                  {crmTestPlatforms.map((platform) => (
                    <option key={platform.key} value={platform.key}>
                      {platform.label}
                      {platform.via === "internal_social" ? " (داخلی)" : ""}
                    </option>
                  ))}
                </Select>
              </Field>
              {isInternalSocialTest ? (
                <Alert tone="info">
                  پیام تست در کانال یک‌طرفه «اطلاعیه‌های سامانه» همین کاربر (حساب شما) ثبت می‌شود؛ شماره تماس لازم
                  نیست. هر کاربر فقط پیام‌های خودش را می‌بیند.
                </Alert>
              ) : (
                <Field label="شماره تماس">
                  <Input
                    value={crmTestMobile}
                    onChange={(e) => setCrmTestMobile(e.target.value)}
                    placeholder="09123456789"
                    dir="ltr"
                  />
                </Field>
              )}
              {crmTestFeedback ? <Alert tone={crmTestFeedback.tone}>{crmTestFeedback.text}</Alert> : null}
            </div>
            <div className="mt-5 flex justify-end gap-2">
              <Button
                variant="secondary"
                type="button"
                disabled={crmTestBusy}
                onClick={() => setCrmTest(null)}
              >
                بستن
              </Button>
              <Button
                type="button"
                disabled={
                  crmTestBusy ||
                  !crmTestChannel ||
                  (!isInternalSocialTest && !/^09\d{9}$/.test(crmTestMobile))
                }
                onClick={() => void sendCrmConnectionTest()}
              >
                {crmTestBusy ? "در حال ارسال…" : "ارسال تست"}
              </Button>
            </div>
          </div>
        </div>
      ) : null}
    </AppShell>
  );
}
