import React, { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
  TrashIcon, PlusIcon, PencilIcon, TagIcon, MapPinIcon,
  BuildingOffice2Icon, HeartIcon, ShieldCheckIcon, WrenchScrewdriverIcon,
  CheckCircleIcon, XCircleIcon, PhotoIcon, XMarkIcon,
} from '@heroicons/react/24/outline';
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { toast } from 'sonner';
import { api } from '../lib/api';
import type { PaginatedResponse } from '../lib/api';
import type { Province, City, SpecialtyFull, DoctorService, Insurance, Tag, Representation } from '../types';
import { useAuthStore } from '../stores/authStore';
import PageHeader from '../components/ui/PageHeader';
import DataTable, { Column } from '../components/ui/DataTable';
import ConfirmDialog from '../components/ui/ConfirmDialog';
import Modal from '../components/ui/Modal';
import Pagination from '../components/ui/Pagination';
import SearchableSelect from '../components/ui/SearchableSelect';

// ── Tab types ────────────────────────────────────────────────────────────────

type TabKey = 'provinces' | 'cities' | 'specialties' | 'doctor_services' | 'insurances' | 'tags';

interface TabConfig {
  key: TabKey;
  label: string;
  icon: React.ElementType;
  color: string;
  description: string;
}

const TABS: TabConfig[] = [
  {
    key: 'provinces',
    label: 'استان‌ها',
    icon: MapPinIcon,
    color: 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-400/10',
    description: 'مدیریت استان‌ها',
  },
  {
    key: 'cities',
    label: 'شهرها',
    icon: BuildingOffice2Icon,
    color: 'text-indigo-600 dark:text-indigo-400 bg-indigo-50 dark:bg-indigo-400/10',
    description: 'مدیریت شهرها و اطلاعات تفصیلی هر شهر',
  },
  {
    key: 'specialties',
    label: 'تخصص‌ها',
    icon: HeartIcon,
    color: 'text-rose-600 dark:text-rose-400 bg-rose-50 dark:bg-rose-400/10',
    description: 'تخصص‌های پزشکی',
  },
  {
    key: 'doctor_services',
    label: 'خدمات پزشک',
    icon: WrenchScrewdriverIcon,
    color: 'text-orange-600 dark:text-orange-400 bg-orange-50 dark:bg-orange-400/10',
    description: 'خدمات قابل ارائه توسط پزشکان',
  },
  {
    key: 'insurances',
    label: 'بیمه‌ها',
    icon: ShieldCheckIcon,
    color: 'text-teal-600 dark:text-teal-400 bg-teal-50 dark:bg-teal-400/10',
    description: 'بیمه‌های پایه و تکمیلی',
  },
  {
    key: 'tags',
    label: 'تگ‌ها',
    icon: TagIcon,
    color: 'text-violet-600 dark:text-violet-400 bg-violet-50 dark:bg-violet-400/10',
    description: 'تگ‌های مورد استفاده در مطالب بلاگ',
  },
];

// ── Logo uploader ─────────────────────────────────────────────────────────────

function LogoUploadField({
  value,
  onChange,
  uploadUrl,
}: {
  value: string | null;
  onChange: (url: string | null) => void;
  uploadUrl: string;
}) {
  const [uploading, setUploading] = useState(false);
  const token = useAuthStore((s) => s.token);

  const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setUploading(true);
    try {
      const res = await fetch(uploadUrl, {
        method: 'POST',
        headers: {
          'Content-Disposition': `attachment; filename="${file.name}"`,
          'Content-Type': 'application/octet-stream',
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        body: file,
      });
      const json = await res.json();
      if (json.success) {
        onChange(json.data.url);
        toast.success('لگو آپلود شد');
      } else {
        toast.error(json.errors?.[0]?.message ?? 'خطا در آپلود');
      }
    } catch {
      toast.error('خطا در آپلود تصویر');
    } finally {
      setUploading(false);
      e.target.value = '';
    }
  };

  return (
    <div className="flex items-center gap-3">
      {value ? (
        <div className="relative group">
          <img src={value} alt="logo" className="w-16 h-16 object-contain rounded-xl border border-slate-200 dark:border-gray-600 bg-white dark:bg-gray-800 p-1" />
          <button
            type="button"
            onClick={() => onChange(null)}
            className="absolute -top-1.5 -right-1.5 w-5 h-5 bg-red-500 hover:bg-red-600 rounded-full text-white flex items-center justify-center shadow transition-colors"
          >
            <XMarkIcon className="w-3 h-3" />
          </button>
        </div>
      ) : (
        <div className="w-16 h-16 rounded-xl border-2 border-dashed border-slate-300 dark:border-gray-600 flex items-center justify-center bg-slate-50 dark:bg-gray-800">
          <PhotoIcon className="w-6 h-6 text-slate-300 dark:text-gray-600" />
        </div>
      )}
      <label className={`cursor-pointer cp-btn-secondary text-sm ${uploading ? 'opacity-60 pointer-events-none' : ''}`}>
        {uploading ? (
          <span className="flex items-center gap-2">
            <svg className="w-4 h-4 animate-spin" viewBox="0 0 24 24" fill="none">
              <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
              <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z" />
            </svg>
            در حال آپلود...
          </span>
        ) : (
          <span className="flex items-center gap-2">
            <PhotoIcon className="w-4 h-4" />
            {value ? 'تغییر لگو' : 'انتخاب لگو'}
          </span>
        )}
        <input type="file" accept="image/jpeg,image/png,image/webp" className="hidden" onChange={handleFile} disabled={uploading} />
      </label>
      <p className="text-xs text-slate-400 dark:text-slate-500">JPG، PNG یا WebP</p>
    </div>
  );
}

// ── StatusBadge helper ────────────────────────────────────────────────────────

function StatusBadge({ status }: { status: number }) {
  return status === 1 ? (
    <span className="inline-flex items-center gap-1 text-xs font-medium text-green-700 dark:text-green-400 bg-green-50 dark:bg-green-400/10 px-2 py-0.5 rounded-full">
      <CheckCircleIcon className="w-3 h-3" /> فعال
    </span>
  ) : (
    <span className="inline-flex items-center gap-1 text-xs font-medium text-slate-500 dark:text-slate-400 bg-slate-100 dark:bg-slate-400/10 px-2 py-0.5 rounded-full">
      <XCircleIcon className="w-3 h-3" /> غیرفعال
    </span>
  );
}

// ── Provinces Tab ─────────────────────────────────────────────────────────────

const provinceSchema = z.object({
  name:   z.string().min(1, 'نام الزامی است'),
  weight: z.string().optional(),
  status: z.string().optional(),
});
type ProvinceForm = z.infer<typeof provinceSchema>;

function ProvincesTab() {
  const qc = useQueryClient();
  const [page, setPage]               = useState(1);
  const [search, setSearch]           = useState('');
  const [addOpen, setAddOpen]         = useState(false);
  const [editTarget, setEditTarget]   = useState<Province | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<Province | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['admin-provinces', page, search],
    queryFn: () => api.get<PaginatedResponse<Province>>(`/api/v1/admin/provinces?page=${page}&limit=20&search=${encodeURIComponent(search)}`),
  });

  const items = data?.data ?? [];
  const total = data?.meta?.totalRecords ?? 0;

  const { register, handleSubmit, reset, control, formState: { errors } } = useForm<ProvinceForm>({
    resolver: zodResolver(provinceSchema),
    defaultValues: { status: '1', weight: '0' },
  });

  const closeModal = () => { setAddOpen(false); setEditTarget(null); reset({ status: '1', weight: '0' }); };

  const createMutation = useMutation({
    mutationFn: (d: ProvinceForm) => api.post('/api/v1/admin/province', { name: d.name.trim(), weight: parseInt(d.weight ?? '0'), status: parseInt(d.status ?? '1') }),
    onSuccess: () => { toast.success('استان اضافه شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-provinces'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, d }: { id: number; d: ProvinceForm }) => api.patch(`/api/v1/admin/province/${id}`, { name: d.name.trim(), weight: parseInt(d.weight ?? '0'), status: parseInt(d.status ?? '1') }),
    onSuccess: () => { toast.success('استان بروزرسانی شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-provinces'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const deleteMutation = useMutation({
    mutationFn: (p: Province) => api.delete(`/api/v1/admin/province/${p.id}`),
    onSuccess: () => { toast.success('استان حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-provinces'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const openEdit = (p: Province) => {
    setEditTarget(p);
    reset({ name: p.name, weight: String(p.weight), status: String(p.status) });
  };

  const columns: Column<Province>[] = [
    { key: 'id', header: 'شناسه', className: 'w-16', render: (p) => <span className="text-xs text-slate-400 font-mono">{p.id}</span> },
    { key: 'name', header: 'نام', render: (p) => <span className="font-medium text-slate-800 dark:text-slate-100">{p.name}</span> },
    { key: 'weight', header: 'ترتیب', className: 'w-20', render: (p) => <span className="text-xs text-slate-400">{p.weight}</span> },
    { key: 'status', header: 'وضعیت', className: 'w-24', render: (p) => <StatusBadge status={p.status} /> },
  ];

  const formBody = (
    <div className="space-y-4">
      <div>
        <label className="cp-label">نام <span className="text-red-500">*</span></label>
        <input {...register('name')} className="cp-input h-11" placeholder="نام استان" />
        {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
      </div>
      <div>
        <label className="cp-label">ترتیب نمایش</label>
        <input {...register('weight')} type="number" dir="ltr" className="cp-input h-11 w-32" placeholder="0" />
      </div>
      <div>
        <label className="cp-label">وضعیت</label>
        <Controller name="status" control={control} render={({ field }) => (
          <SearchableSelect options={[{ value: '1', label: 'فعال' }, { value: '0', label: 'غیرفعال' }]} value={field.value ?? '1'} onChange={(v) => field.onChange(v ?? '1')} isClearable={false} />
        )} />
      </div>
    </div>
  );

  return (
    <>
      <div className="flex justify-end px-5 pt-4">
        <button onClick={() => { reset({ status: '1', weight: '0' }); setAddOpen(true); }} className="cp-btn-primary">
          <PlusIcon className="w-4 h-4" /> افزودن استان
        </button>
      </div>
      <div className="p-5">
        <DataTable<Province> columns={columns} data={items} loading={isLoading} searchValue={search} onSearchChange={(v) => { setSearch(v); setPage(1); }} searchPlaceholder="جستجو در استان‌ها..." emptyMessage="هیچ استانی یافت نشد"
          actions={(p) => (
            <>
              <button onClick={() => openEdit(p)} className="cp-action-edit" title="ویرایش"><PencilIcon className="w-4 h-4" /></button>
              <button onClick={() => setDeleteTarget(p)} className="cp-action-delete" title="حذف"><TrashIcon className="w-4 h-4" /></button>
            </>
          )}
        />
        {total > 20 && <div className="mt-4"><Pagination page={page} total={total} limit={20} onPageChange={setPage} /></div>}
      </div>

      <Modal open={addOpen || !!editTarget} title={editTarget ? `ویرایش — ${editTarget.name}` : 'افزودن استان'} size="sm" onClose={closeModal}
        footer={<><button onClick={closeModal} className="cp-btn-secondary">لغو</button><button form="province-form" type="submit" disabled={createMutation.isPending || updateMutation.isPending} className="cp-btn-primary">{(createMutation.isPending || updateMutation.isPending) ? 'در حال ذخیره...' : (editTarget ? 'ذخیره' : 'افزودن')}</button></>}
      >
        <form id="province-form" onSubmit={handleSubmit((d) => editTarget ? updateMutation.mutate({ id: editTarget.id, d }) : createMutation.mutate(d))}>
          {formBody}
        </form>
      </Modal>

      <ConfirmDialog open={!!deleteTarget} title="حذف استان" message={`آیا از حذف "${deleteTarget?.name}" اطمینان دارید؟`} confirmLabel="حذف" danger loading={deleteMutation.isPending}
        onConfirm={() => deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
    </>
  );
}

// ── Cities Tab ────────────────────────────────────────────────────────────────

const citySchema = z.object({
  name:               z.string().min(1, 'نام الزامی است'),
  province_id:        z.number().nullable().optional(),
  weight:             z.string().optional(),
  status:             z.string().optional(),
  representation_id:  z.number().nullable().optional(),
  contact_phone:      z.string().optional(),
  email:              z.string().optional(),
  description:        z.string().optional(),
  slogan:             z.string().optional(),
  domain:             z.string().optional(),
  keywords:           z.string().optional(),
  footer_description: z.string().optional(),
});
type CityForm = z.infer<typeof citySchema>;

function CitiesTab() {
  const qc = useQueryClient();
  const [page, setPage]               = useState(1);
  const [search, setSearch]           = useState('');
  const [addOpen, setAddOpen]         = useState(false);
  const [editTarget, setEditTarget]   = useState<City | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<City | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['admin-cities', page, search],
    queryFn: () => api.get<PaginatedResponse<City>>(`/api/v1/admin/cities?page=${page}&limit=20&search=${encodeURIComponent(search)}`),
  });

  const provincesQuery = useQuery({
    queryKey: ['admin-provinces-select'],
    queryFn: () => api.get<PaginatedResponse<Province>>('/api/v1/admin/provinces?limit=100'),
    staleTime: 60_000,
  });
  const provinceOptions = (provincesQuery.data?.data ?? []).map((p) => ({ value: p.id, label: p.name }));
  const provinceMap = Object.fromEntries((provincesQuery.data?.data ?? []).map((p) => [p.id, p.name]));

  const representationsQuery = useQuery({
    queryKey: ['representations-select'],
    queryFn: () => api.get<PaginatedResponse<Representation>>('/api/v1/admin/representations?limit=200'),
    staleTime: 2 * 60_000,
  });
  const representationOptions = (representationsQuery.data?.data ?? []).map((r) => ({
    value: r.id,
    label: r.full_name + (r.mobile_number ? ` — ${r.mobile_number}` : ''),
  }));
  const representationMap = Object.fromEntries((representationsQuery.data?.data ?? []).map((r) => [r.id, r.full_name]));

  const items = data?.data ?? [];
  const total = data?.meta?.totalRecords ?? 0;

  const { register, handleSubmit, reset, control, formState: { errors } } = useForm<CityForm>({
    resolver: zodResolver(citySchema),
    defaultValues: { status: '1', weight: '0' },
  });

  const closeModal = () => { setAddOpen(false); setEditTarget(null); reset({ status: '1', weight: '0' }); };

  const buildPayload = (d: CityForm) => ({
    name: d.name.trim(),
    weight: parseInt(d.weight ?? '0'),
    status: parseInt(d.status ?? '1'),
    province_id: d.province_id ?? null,
    representation_id: d.representation_id ?? null,
    ...(d.contact_phone?.trim() && { contact_phone: d.contact_phone.trim() }),
    ...(d.email?.trim() && { email: d.email.trim() }),
    ...(d.description?.trim() && { description: d.description.trim() }),
    ...(d.slogan?.trim() && { slogan: d.slogan.trim() }),
    ...(d.domain?.trim() && { domain: d.domain.trim() }),
    ...(d.keywords?.trim() && { keywords: d.keywords.trim() }),
    ...(d.footer_description?.trim() && { footer_description: d.footer_description.trim() }),
  });

  const createMutation = useMutation({
    mutationFn: (d: CityForm) => api.post('/api/v1/admin/city', buildPayload(d)),
    onSuccess: () => { toast.success('شهر اضافه شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-cities'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, d }: { id: number; d: CityForm }) => api.patch(`/api/v1/admin/city/${id}`, buildPayload(d)),
    onSuccess: () => { toast.success('شهر بروزرسانی شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-cities'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const deleteMutation = useMutation({
    mutationFn: (c: City) => api.delete(`/api/v1/admin/city/${c.id}`),
    onSuccess: () => { toast.success('شهر حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-cities'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const openEdit = (c: City) => {
    setEditTarget(c);
    reset({
      name: c.name, weight: String(c.weight), status: String(c.status),
      province_id: c.province_id ?? null,
      representation_id: c.representation_id ?? null,
      contact_phone: c.contact_phone ?? '',
      email: c.email ?? '',
      description: c.description ?? '',
      slogan: c.slogan ?? '',
      domain: c.domain ?? '',
      keywords: c.keywords ?? '',
      footer_description: c.footer_description ?? '',
    });
  };

  const columns: Column<City>[] = [
    { key: 'id', header: 'شناسه', className: 'w-16', render: (c) => <span className="text-xs text-slate-400 font-mono">{c.id}</span> },
    { key: 'name', header: 'نام', render: (c) => <span className="font-medium text-slate-800 dark:text-slate-100">{c.name}</span> },
    { key: 'province_id', header: 'استان', render: (c) => c.province_id ? <span className="text-xs bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300 px-2 py-0.5 rounded-full">{provinceMap[c.province_id] ?? `#${c.province_id}`}</span> : <span className="text-slate-300">—</span> },
    { key: 'representation_id', header: 'نماینده', render: (c) => c.representation_id ? <span className="text-xs text-slate-500 dark:text-slate-400">{representationMap[c.representation_id] ?? `#${c.representation_id}`}</span> : <span className="text-slate-300">—</span> },
    { key: 'domain', header: 'دامنه', render: (c) => c.domain ? <span className="text-xs font-mono text-slate-500">{c.domain}</span> : <span className="text-slate-300">—</span> },
    { key: 'weight', header: 'ترتیب', className: 'w-20', render: (c) => <span className="text-xs text-slate-400">{c.weight}</span> },
    { key: 'status', header: 'وضعیت', className: 'w-24', render: (c) => <StatusBadge status={c.status} /> },
  ];

  return (
    <>
      <div className="flex justify-end px-5 pt-4">
        <button onClick={() => { reset({ status: '1', weight: '0' }); setAddOpen(true); }} className="cp-btn-primary">
          <PlusIcon className="w-4 h-4" /> افزودن شهر
        </button>
      </div>
      <div className="p-5">
        <DataTable<City> columns={columns} data={items} loading={isLoading} searchValue={search} onSearchChange={(v) => { setSearch(v); setPage(1); }} searchPlaceholder="جستجو در شهرها..." emptyMessage="هیچ شهری یافت نشد"
          actions={(c) => (
            <>
              <button onClick={() => openEdit(c)} className="cp-action-edit" title="ویرایش"><PencilIcon className="w-4 h-4" /></button>
              <button onClick={() => setDeleteTarget(c)} className="cp-action-delete" title="حذف"><TrashIcon className="w-4 h-4" /></button>
            </>
          )}
        />
        {total > 20 && <div className="mt-4"><Pagination page={page} total={total} limit={20} onPageChange={setPage} /></div>}
      </div>

      <Modal open={addOpen || !!editTarget} title={editTarget ? `ویرایش — ${editTarget.name}` : 'افزودن شهر'} size="lg" onClose={closeModal}
        footer={<><button onClick={closeModal} className="cp-btn-secondary">لغو</button><button form="city-form" type="submit" disabled={createMutation.isPending || updateMutation.isPending} className="cp-btn-primary">{(createMutation.isPending || updateMutation.isPending) ? 'در حال ذخیره...' : (editTarget ? 'ذخیره' : 'افزودن')}</button></>}
      >
        <form id="city-form" onSubmit={handleSubmit((d) => editTarget ? updateMutation.mutate({ id: editTarget.id, d }) : createMutation.mutate(d))}>
          <div className="space-y-4">
            <div>
              <label className="cp-label">نام <span className="text-red-500">*</span></label>
              <input {...register('name')} className="cp-input h-11" placeholder="نام شهر" />
              {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
            </div>
            <div>
              <label className="cp-label">استان</label>
              <Controller name="province_id" control={control} render={({ field }) => (
                <SearchableSelect options={provinceOptions} value={field.value ?? null} onChange={(v) => field.onChange(v as number | null)} placeholder="-- انتخاب استان --" isClearable isLoading={provincesQuery.isLoading} noOptionsMessage="استانی یافت نشد" />
              )} />
            </div>
            <div>
              <label className="cp-label">نماینده</label>
              <Controller name="representation_id" control={control} render={({ field }) => (
                <SearchableSelect options={representationOptions} value={field.value ?? null} onChange={(v) => field.onChange(v as number | null)} placeholder="انتخاب نماینده..." isClearable isLoading={representationsQuery.isLoading} noOptionsMessage="هیچ نماینده‌ای یافت نشد" />
              )} />
            </div>
            <div className="grid grid-cols-2 gap-3">
              <div>
                <label className="cp-label">تلفن تماس</label>
                <input {...register('contact_phone')} className="cp-input h-10" dir="ltr" placeholder="021xxxxxxxx" />
              </div>
              <div>
                <label className="cp-label">ایمیل</label>
                <input {...register('email')} type="email" className="cp-input h-10" dir="ltr" />
              </div>
            </div>
            <div>
              <label className="cp-label">دامنه</label>
              <input {...register('domain')} className="cp-input h-10" dir="ltr" />
            </div>
            <div>
              <label className="cp-label">شعار</label>
              <input {...register('slogan')} className="cp-input h-10" />
            </div>
            <div>
              <label className="cp-label">کلیدواژه‌ها</label>
              <input {...register('keywords')} className="cp-input h-10" />
            </div>
            <div>
              <label className="cp-label">توضیحات</label>
              <textarea {...register('description')} rows={3} className="cp-textarea" />
            </div>
            <div>
              <label className="cp-label">توضیحات فوتر</label>
              <textarea {...register('footer_description')} rows={2} className="cp-textarea" />
            </div>
            <div>
              <label className="cp-label">ترتیب نمایش</label>
              <input {...register('weight')} type="number" dir="ltr" className="cp-input h-11 w-32" placeholder="0" />
            </div>
            <div>
              <label className="cp-label">وضعیت</label>
              <Controller name="status" control={control} render={({ field }) => (
                <SearchableSelect options={[{ value: '1', label: 'فعال' }, { value: '0', label: 'غیرفعال' }]} value={field.value ?? '1'} onChange={(v) => field.onChange(v ?? '1')} isClearable={false} />
              )} />
            </div>
          </div>
        </form>
      </Modal>

      <ConfirmDialog open={!!deleteTarget} title="حذف شهر" message={`آیا از حذف "${deleteTarget?.name}" اطمینان دارید؟`} confirmLabel="حذف" danger loading={deleteMutation.isPending}
        onConfirm={() => deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
    </>
  );
}

// ── Specialties Tab ───────────────────────────────────────────────────────────

const specialtySchema = z.object({
  name:      z.string().min(1, 'نام الزامی است'),
  parent_id: z.number().nullable().optional(),
  weight:    z.string().optional(),
  status:    z.string().optional(),
});
type SpecialtyForm = z.infer<typeof specialtySchema>;

function SpecialtiesTab() {
  const qc = useQueryClient();
  const [page, setPage]               = useState(1);
  const [search, setSearch]           = useState('');
  const [addOpen, setAddOpen]         = useState(false);
  const [editTarget, setEditTarget]   = useState<SpecialtyFull | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<SpecialtyFull | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['admin-specialties', page, search],
    queryFn: () => api.get<PaginatedResponse<SpecialtyFull>>(`/api/v1/admin/specialties?page=${page}&limit=20&search=${encodeURIComponent(search)}`),
  });

  const items = data?.data ?? [];
  const total = data?.meta?.totalRecords ?? 0;
  const parentMap = Object.fromEntries(items.map((s) => [s.id, s.name]));

  const { register, handleSubmit, reset, control, formState: { errors } } = useForm<SpecialtyForm>({
    resolver: zodResolver(specialtySchema),
    defaultValues: { status: '1', weight: '0' },
  });

  const closeModal = () => { setAddOpen(false); setEditTarget(null); reset({ status: '1', weight: '0' }); };

  const createMutation = useMutation({
    mutationFn: (d: SpecialtyForm) => api.post('/api/v1/admin/specialty', { name: d.name.trim(), weight: parseInt(d.weight ?? '0'), status: parseInt(d.status ?? '1'), parent_id: d.parent_id ?? null }),
    onSuccess: () => { toast.success('تخصص اضافه شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-specialties'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, d }: { id: number; d: SpecialtyForm }) => api.patch(`/api/v1/admin/specialty/${id}`, { name: d.name.trim(), weight: parseInt(d.weight ?? '0'), status: parseInt(d.status ?? '1'), parent_id: d.parent_id ?? null }),
    onSuccess: () => { toast.success('تخصص بروزرسانی شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-specialties'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const deleteMutation = useMutation({
    mutationFn: (s: SpecialtyFull) => api.delete(`/api/v1/admin/specialty/${s.id}`),
    onSuccess: () => { toast.success('تخصص حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-specialties'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const openEdit = (s: SpecialtyFull) => {
    setEditTarget(s);
    reset({ name: s.name, weight: String(s.weight), status: String(s.status), parent_id: s.parent_id ?? null });
  };

  const parentOptions = items.filter((s) => s.parent_id === null).map((s) => ({ value: s.id, label: s.name }));

  const columns: Column<SpecialtyFull>[] = [
    { key: 'id', header: 'شناسه', className: 'w-16', render: (s) => <span className="text-xs text-slate-400 font-mono">{s.id}</span> },
    { key: 'name', header: 'نام', render: (s) => <span className="font-medium text-slate-800 dark:text-slate-100">{s.name}</span> },
    { key: 'slug', header: 'slug', render: (s) => <span className="text-xs font-mono text-slate-400">{s.slug}</span> },
    { key: 'parent_id', header: 'والد', render: (s) => s.parent_id ? <span className="text-xs bg-slate-100 dark:bg-slate-700 px-2 py-0.5 rounded-full">{parentMap[s.parent_id] ?? `#${s.parent_id}`}</span> : <span className="text-slate-300">—</span> },
    { key: 'weight', header: 'ترتیب', className: 'w-20', render: (s) => <span className="text-xs text-slate-400">{s.weight}</span> },
    { key: 'status', header: 'وضعیت', className: 'w-24', render: (s) => <StatusBadge status={s.status} /> },
  ];

  return (
    <>
      <div className="flex justify-end px-5 pt-4">
        <button onClick={() => { reset({ status: '1', weight: '0' }); setAddOpen(true); }} className="cp-btn-primary">
          <PlusIcon className="w-4 h-4" /> افزودن تخصص
        </button>
      </div>
      <div className="p-5">
        <DataTable<SpecialtyFull> columns={columns} data={items} loading={isLoading} searchValue={search} onSearchChange={(v) => { setSearch(v); setPage(1); }} searchPlaceholder="جستجو در تخصص‌ها..." emptyMessage="هیچ تخصصی یافت نشد"
          actions={(s) => (
            <>
              <button onClick={() => openEdit(s)} className="cp-action-edit" title="ویرایش"><PencilIcon className="w-4 h-4" /></button>
              <button onClick={() => setDeleteTarget(s)} className="cp-action-delete" title="حذف"><TrashIcon className="w-4 h-4" /></button>
            </>
          )}
        />
        {total > 20 && <div className="mt-4"><Pagination page={page} total={total} limit={20} onPageChange={setPage} /></div>}
      </div>

      <Modal open={addOpen || !!editTarget} title={editTarget ? `ویرایش — ${editTarget.name}` : 'افزودن تخصص'} size="sm" onClose={closeModal}
        footer={<><button onClick={closeModal} className="cp-btn-secondary">لغو</button><button form="specialty-form" type="submit" disabled={createMutation.isPending || updateMutation.isPending} className="cp-btn-primary">{(createMutation.isPending || updateMutation.isPending) ? 'در حال ذخیره...' : (editTarget ? 'ذخیره' : 'افزودن')}</button></>}
      >
        <form id="specialty-form" onSubmit={handleSubmit((d) => editTarget ? updateMutation.mutate({ id: editTarget.id, d }) : createMutation.mutate(d))}>
          <div className="space-y-4">
            <div>
              <label className="cp-label">نام <span className="text-red-500">*</span></label>
              <input {...register('name')} className="cp-input h-11" placeholder="نام تخصص" />
              {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
            </div>
            <div>
              <label className="cp-label">تخصص والد</label>
              <Controller name="parent_id" control={control} render={({ field }) => (
                <SearchableSelect options={parentOptions} value={field.value ?? null} onChange={(v) => field.onChange(v as number | null)} placeholder="-- بدون والد --" isClearable noOptionsMessage="موردی یافت نشد" />
              )} />
            </div>
            <div>
              <label className="cp-label">ترتیب نمایش</label>
              <input {...register('weight')} type="number" dir="ltr" className="cp-input h-11 w-32" placeholder="0" />
            </div>
            <div>
              <label className="cp-label">وضعیت</label>
              <Controller name="status" control={control} render={({ field }) => (
                <SearchableSelect options={[{ value: '1', label: 'فعال' }, { value: '0', label: 'غیرفعال' }]} value={field.value ?? '1'} onChange={(v) => field.onChange(v ?? '1')} isClearable={false} />
              )} />
            </div>
          </div>
        </form>
      </Modal>

      <ConfirmDialog open={!!deleteTarget} title="حذف تخصص" message={`آیا از حذف "${deleteTarget?.name}" اطمینان دارید؟`} confirmLabel="حذف" danger loading={deleteMutation.isPending}
        onConfirm={() => deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
    </>
  );
}

// ── DoctorServices Tab ────────────────────────────────────────────────────────

const serviceSchema = z.object({
  name:         z.string().min(1, 'نام الزامی است'),
  specialty_id: z.number().nullable().optional(),
  weight:       z.string().optional(),
  status:       z.string().optional(),
});
type ServiceForm = z.infer<typeof serviceSchema>;

function DoctorServicesTab() {
  const qc = useQueryClient();
  const [page, setPage]               = useState(1);
  const [search, setSearch]           = useState('');
  const [addOpen, setAddOpen]         = useState(false);
  const [editTarget, setEditTarget]   = useState<DoctorService | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<DoctorService | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['admin-doctor-services', page, search],
    queryFn: () => api.get<PaginatedResponse<DoctorService>>(`/api/v1/admin/doctor-services?page=${page}&limit=20&search=${encodeURIComponent(search)}`),
  });

  const specialtiesQuery = useQuery({
    queryKey: ['admin-specialties-select'],
    queryFn: () => api.get<PaginatedResponse<SpecialtyFull>>('/api/v1/admin/specialties?limit=100'),
    staleTime: 60_000,
  });
  const specialtyOptions = (specialtiesQuery.data?.data ?? []).map((s) => ({ value: s.id, label: s.name }));
  const specialtyMap = Object.fromEntries((specialtiesQuery.data?.data ?? []).map((s) => [s.id, s.name]));

  const items = data?.data ?? [];
  const total = data?.meta?.totalRecords ?? 0;

  const { register, handleSubmit, reset, control, formState: { errors } } = useForm<ServiceForm>({
    resolver: zodResolver(serviceSchema),
    defaultValues: { status: '1', weight: '0' },
  });

  const closeModal = () => { setAddOpen(false); setEditTarget(null); reset({ status: '1', weight: '0' }); };

  const createMutation = useMutation({
    mutationFn: (d: ServiceForm) => api.post('/api/v1/admin/doctor-service', { name: d.name.trim(), weight: parseInt(d.weight ?? '0'), status: parseInt(d.status ?? '1'), specialty_id: d.specialty_id ?? null }),
    onSuccess: () => { toast.success('خدمت اضافه شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-doctor-services'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, d }: { id: number; d: ServiceForm }) => api.patch(`/api/v1/admin/doctor-service/${id}`, { name: d.name.trim(), weight: parseInt(d.weight ?? '0'), status: parseInt(d.status ?? '1'), specialty_id: d.specialty_id ?? null }),
    onSuccess: () => { toast.success('خدمت بروزرسانی شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-doctor-services'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const deleteMutation = useMutation({
    mutationFn: (s: DoctorService) => api.delete(`/api/v1/admin/doctor-service/${s.id}`),
    onSuccess: () => { toast.success('خدمت حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-doctor-services'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const openEdit = (s: DoctorService) => {
    setEditTarget(s);
    reset({ name: s.name, weight: String(s.weight), status: String(s.status), specialty_id: s.specialty_id ?? null });
  };

  const columns: Column<DoctorService>[] = [
    { key: 'id', header: 'شناسه', className: 'w-16', render: (s) => <span className="text-xs text-slate-400 font-mono">{s.id}</span> },
    { key: 'name', header: 'نام', render: (s) => <span className="font-medium text-slate-800 dark:text-slate-100">{s.name}</span> },
    { key: 'specialty_id', header: 'تخصص', render: (s) => s.specialty_id ? <span className="text-xs bg-rose-50 dark:bg-rose-400/10 text-rose-600 dark:text-rose-400 px-2 py-0.5 rounded-full">{specialtyMap[s.specialty_id] ?? `#${s.specialty_id}`}</span> : <span className="text-slate-300">—</span> },
    { key: 'weight', header: 'ترتیب', className: 'w-20', render: (s) => <span className="text-xs text-slate-400">{s.weight}</span> },
    { key: 'status', header: 'وضعیت', className: 'w-24', render: (s) => <StatusBadge status={s.status} /> },
  ];

  return (
    <>
      <div className="flex justify-end px-5 pt-4">
        <button onClick={() => { reset({ status: '1', weight: '0' }); setAddOpen(true); }} className="cp-btn-primary">
          <PlusIcon className="w-4 h-4" /> افزودن خدمت
        </button>
      </div>
      <div className="p-5">
        <DataTable<DoctorService> columns={columns} data={items} loading={isLoading} searchValue={search} onSearchChange={(v) => { setSearch(v); setPage(1); }} searchPlaceholder="جستجو در خدمات..." emptyMessage="هیچ خدمتی یافت نشد"
          actions={(s) => (
            <>
              <button onClick={() => openEdit(s)} className="cp-action-edit" title="ویرایش"><PencilIcon className="w-4 h-4" /></button>
              <button onClick={() => setDeleteTarget(s)} className="cp-action-delete" title="حذف"><TrashIcon className="w-4 h-4" /></button>
            </>
          )}
        />
        {total > 20 && <div className="mt-4"><Pagination page={page} total={total} limit={20} onPageChange={setPage} /></div>}
      </div>

      <Modal open={addOpen || !!editTarget} title={editTarget ? `ویرایش — ${editTarget.name}` : 'افزودن خدمت'} size="sm" onClose={closeModal}
        footer={<><button onClick={closeModal} className="cp-btn-secondary">لغو</button><button form="service-form" type="submit" disabled={createMutation.isPending || updateMutation.isPending} className="cp-btn-primary">{(createMutation.isPending || updateMutation.isPending) ? 'در حال ذخیره...' : (editTarget ? 'ذخیره' : 'افزودن')}</button></>}
      >
        <form id="service-form" onSubmit={handleSubmit((d) => editTarget ? updateMutation.mutate({ id: editTarget.id, d }) : createMutation.mutate(d))}>
          <div className="space-y-4">
            <div>
              <label className="cp-label">نام <span className="text-red-500">*</span></label>
              <input {...register('name')} className="cp-input h-11" placeholder="نام خدمت" />
              {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
            </div>
            <div>
              <label className="cp-label">تخصص مرتبط</label>
              <Controller name="specialty_id" control={control} render={({ field }) => (
                <SearchableSelect options={specialtyOptions} value={field.value ?? null} onChange={(v) => field.onChange(v as number | null)} placeholder="-- انتخاب تخصص --" isClearable isLoading={specialtiesQuery.isLoading} noOptionsMessage="تخصصی یافت نشد" />
              )} />
            </div>
            <div>
              <label className="cp-label">ترتیب نمایش</label>
              <input {...register('weight')} type="number" dir="ltr" className="cp-input h-11 w-32" placeholder="0" />
            </div>
            <div>
              <label className="cp-label">وضعیت</label>
              <Controller name="status" control={control} render={({ field }) => (
                <SearchableSelect options={[{ value: '1', label: 'فعال' }, { value: '0', label: 'غیرفعال' }]} value={field.value ?? '1'} onChange={(v) => field.onChange(v ?? '1')} isClearable={false} />
              )} />
            </div>
          </div>
        </form>
      </Modal>

      <ConfirmDialog open={!!deleteTarget} title="حذف خدمت" message={`آیا از حذف "${deleteTarget?.name}" اطمینان دارید؟`} confirmLabel="حذف" danger loading={deleteMutation.isPending}
        onConfirm={() => deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
    </>
  );
}

// ── Insurances Tab ────────────────────────────────────────────────────────────

const insuranceSchema = z.object({
  name:   z.string().min(1, 'نام الزامی است'),
  type:   z.enum(['basic', 'supplementary']),
  status: z.string().optional(),
});
type InsuranceForm = z.infer<typeof insuranceSchema>;

function InsurancesTab() {
  const qc = useQueryClient();
  const [page, setPage]               = useState(1);
  const [search, setSearch]           = useState('');
  const [addOpen, setAddOpen]         = useState(false);
  const [editTarget, setEditTarget]   = useState<Insurance | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<Insurance | null>(null);
  const [logoUrl, setLogoUrl]         = useState<string | null>(null);
  const [uploadTarget, setUploadTarget] = useState<number | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['admin-insurances', page, search],
    queryFn: () => api.get<PaginatedResponse<Insurance>>(`/api/v1/admin/insurances?page=${page}&limit=20&search=${encodeURIComponent(search)}`),
  });

  const items = data?.data ?? [];
  const total = data?.meta?.totalRecords ?? 0;

  const { register, handleSubmit, reset, control, formState: { errors } } = useForm<InsuranceForm>({
    resolver: zodResolver(insuranceSchema),
    defaultValues: { status: '1', type: 'basic' },
  });

  const closeModal = () => { setAddOpen(false); setEditTarget(null); setLogoUrl(null); reset({ status: '1', type: 'basic' }); };

  const createMutation = useMutation({
    mutationFn: (d: InsuranceForm) => api.post('/api/v1/admin/insurance', { name: d.name.trim(), type: d.type, status: parseInt(d.status ?? '1'), logo_url: logoUrl }),
    onSuccess: () => { toast.success('بیمه اضافه شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-insurances'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, d }: { id: number; d: InsuranceForm }) => api.patch(`/api/v1/admin/insurance/${id}`, { name: d.name.trim(), type: d.type, status: parseInt(d.status ?? '1'), logo_url: logoUrl }),
    onSuccess: () => { toast.success('بیمه بروزرسانی شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-insurances'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const deleteMutation = useMutation({
    mutationFn: (i: Insurance) => api.delete(`/api/v1/admin/insurance/${i.id}`),
    onSuccess: () => { toast.success('بیمه حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-insurances'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const openEdit = (i: Insurance) => {
    setEditTarget(i);
    setLogoUrl(i.logo_url ?? null);
    setUploadTarget(i.id);
    reset({ name: i.name, type: i.type, status: String(i.status) });
  };

  const columns: Column<Insurance>[] = [
    { key: 'id', header: 'شناسه', className: 'w-16', render: (i) => <span className="text-xs text-slate-400 font-mono">{i.id}</span> },
    { key: 'name', header: 'نام', render: (i) => (
      <div className="flex items-center gap-2.5">
        {i.logo_url ? (
          <img src={i.logo_url} alt={i.name} className="w-8 h-8 object-contain rounded-lg border border-slate-200 dark:border-gray-600 bg-white p-0.5 shrink-0" />
        ) : (
          <div className="w-8 h-8 rounded-lg border border-dashed border-slate-200 dark:border-gray-600 flex items-center justify-center shrink-0">
            <PhotoIcon className="w-4 h-4 text-slate-300" />
          </div>
        )}
        <span className="font-medium text-slate-800 dark:text-slate-100">{i.name}</span>
      </div>
    )},
    { key: 'type', header: 'نوع', render: (i) => (
      <span className={`text-xs font-medium px-2 py-0.5 rounded-full ${i.type === 'basic' ? 'bg-teal-50 dark:bg-teal-400/10 text-teal-700 dark:text-teal-400' : 'bg-cyan-50 dark:bg-cyan-400/10 text-cyan-700 dark:text-cyan-400'}`}>
        {i.type === 'basic' ? 'پایه' : 'تکمیلی'}
      </span>
    )},
    { key: 'status', header: 'وضعیت', className: 'w-24', render: (i) => <StatusBadge status={i.status} /> },
  ];

  return (
    <>
      <div className="flex justify-end px-5 pt-4">
        <button onClick={() => { reset({ status: '1', type: 'basic' }); setLogoUrl(null); setUploadTarget(null); setAddOpen(true); }} className="cp-btn-primary">
          <PlusIcon className="w-4 h-4" /> افزودن بیمه
        </button>
      </div>
      <div className="p-5">
        <DataTable<Insurance> columns={columns} data={items} loading={isLoading} searchValue={search} onSearchChange={(v) => { setSearch(v); setPage(1); }} searchPlaceholder="جستجو در بیمه‌ها..." emptyMessage="هیچ بیمه‌ای یافت نشد"
          actions={(i) => (
            <>
              <button onClick={() => openEdit(i)} className="cp-action-edit" title="ویرایش"><PencilIcon className="w-4 h-4" /></button>
              <button onClick={() => setDeleteTarget(i)} className="cp-action-delete" title="حذف"><TrashIcon className="w-4 h-4" /></button>
            </>
          )}
        />
        {total > 20 && <div className="mt-4"><Pagination page={page} total={total} limit={20} onPageChange={setPage} /></div>}
      </div>

      <Modal open={addOpen || !!editTarget} title={editTarget ? `ویرایش — ${editTarget.name}` : 'افزودن بیمه'} size="sm" onClose={closeModal}
        footer={<><button onClick={closeModal} className="cp-btn-secondary">لغو</button><button form="insurance-form" type="submit" disabled={createMutation.isPending || updateMutation.isPending} className="cp-btn-primary">{(createMutation.isPending || updateMutation.isPending) ? 'در حال ذخیره...' : (editTarget ? 'ذخیره' : 'افزودن')}</button></>}
      >
        <form id="insurance-form" onSubmit={handleSubmit((d) => editTarget ? updateMutation.mutate({ id: editTarget.id, d }) : createMutation.mutate(d))}>
          <div className="space-y-4">
            <div>
              <label className="cp-label">لگو</label>
              <LogoUploadField
                value={logoUrl}
                onChange={setLogoUrl}
                uploadUrl={uploadTarget ? `/api/v1/admin/insurance/${uploadTarget}/upload-logo` : '/api/v1/admin/insurance/0/upload-logo'}
              />
            </div>
            <div>
              <label className="cp-label">نام <span className="text-red-500">*</span></label>
              <input {...register('name')} className="cp-input h-11" placeholder="نام بیمه" />
              {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
            </div>
            <div>
              <label className="cp-label">نوع <span className="text-red-500">*</span></label>
              <Controller name="type" control={control} render={({ field }) => (
                <SearchableSelect options={[{ value: 'basic', label: 'بیمه پایه' }, { value: 'supplementary', label: 'بیمه تکمیلی' }]} value={field.value} onChange={(v) => field.onChange(v ?? 'basic')} isClearable={false} />
              )} />
            </div>
            <div>
              <label className="cp-label">وضعیت</label>
              <Controller name="status" control={control} render={({ field }) => (
                <SearchableSelect options={[{ value: '1', label: 'فعال' }, { value: '0', label: 'غیرفعال' }]} value={field.value ?? '1'} onChange={(v) => field.onChange(v ?? '1')} isClearable={false} />
              )} />
            </div>
          </div>
        </form>
      </Modal>

      <ConfirmDialog open={!!deleteTarget} title="حذف بیمه" message={`آیا از حذف "${deleteTarget?.name}" اطمینان دارید؟`} confirmLabel="حذف" danger loading={deleteMutation.isPending}
        onConfirm={() => deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
    </>
  );
}

// ── Tags Tab ──────────────────────────────────────────────────────────────────

const tagSchema = z.object({
  name:   z.string().min(1, 'نام الزامی است'),
  status: z.string().optional(),
});
type TagForm = z.infer<typeof tagSchema>;

function TagsTab() {
  const qc = useQueryClient();
  const [page, setPage]               = useState(1);
  const [search, setSearch]           = useState('');
  const [addOpen, setAddOpen]         = useState(false);
  const [editTarget, setEditTarget]   = useState<Tag | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<Tag | null>(null);

  const { data, isLoading } = useQuery({
    queryKey: ['admin-tags', page, search],
    queryFn: () => api.get<PaginatedResponse<Tag>>(`/api/v1/admin/tags?page=${page}&limit=20&search=${encodeURIComponent(search)}`),
  });

  const items = data?.data ?? [];
  const total = data?.meta?.totalRecords ?? 0;

  const { register, handleSubmit, reset, formState: { errors } } = useForm<TagForm>({
    resolver: zodResolver(tagSchema),
    defaultValues: { status: '1' },
  });

  const closeModal = () => { setAddOpen(false); setEditTarget(null); reset({ status: '1' }); };

  const createMutation = useMutation({
    mutationFn: (d: TagForm) => api.post('/api/v1/admin/tag', { name: d.name.trim(), status: parseInt(d.status ?? '1') }),
    onSuccess: () => { toast.success('تگ اضافه شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-tags'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, d }: { id: number; d: TagForm }) => api.patch(`/api/v1/admin/tag/${id}`, { name: d.name.trim(), status: parseInt(d.status ?? '1') }),
    onSuccess: () => { toast.success('تگ بروزرسانی شد'); closeModal(); qc.invalidateQueries({ queryKey: ['admin-tags'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const deleteMutation = useMutation({
    mutationFn: (t: Tag) => api.delete(`/api/v1/admin/tag/${t.id}`),
    onSuccess: () => { toast.success('تگ حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-tags'] }); },
    onError: (err: Error) => toast.error(err.message),
  });

  const openEdit = (t: Tag) => {
    setEditTarget(t);
    reset({ name: t.name, status: String(t.status) });
  };

  const columns: Column<Tag>[] = [
    { key: 'id', header: 'شناسه', className: 'w-16', render: (t) => <span className="text-xs text-slate-400 font-mono">{t.id}</span> },
    { key: 'name', header: 'نام', render: (t) => <span className="font-medium text-slate-800 dark:text-slate-100">{t.name}</span> },
    { key: 'slug', header: 'slug', render: (t) => <span className="text-xs font-mono text-slate-400">{t.slug}</span> },
    { key: 'status', header: 'وضعیت', className: 'w-24', render: (t) => <StatusBadge status={t.status} /> },
  ];

  return (
    <>
      <div className="flex justify-end px-5 pt-4">
        <button onClick={() => { reset({ status: '1' }); setAddOpen(true); }} className="cp-btn-primary">
          <PlusIcon className="w-4 h-4" /> افزودن تگ
        </button>
      </div>
      <div className="p-5">
        <DataTable<Tag> columns={columns} data={items} loading={isLoading} searchValue={search} onSearchChange={(v) => { setSearch(v); setPage(1); }} searchPlaceholder="جستجو در تگ‌ها..." emptyMessage="هیچ تگی یافت نشد"
          actions={(t) => (
            <>
              <button onClick={() => openEdit(t)} className="cp-action-edit" title="ویرایش"><PencilIcon className="w-4 h-4" /></button>
              <button onClick={() => setDeleteTarget(t)} className="cp-action-delete" title="حذف"><TrashIcon className="w-4 h-4" /></button>
            </>
          )}
        />
        {total > 20 && <div className="mt-4"><Pagination page={page} total={total} limit={20} onPageChange={setPage} /></div>}
      </div>

      <Modal open={addOpen || !!editTarget} title={editTarget ? `ویرایش — ${editTarget.name}` : 'افزودن تگ'} size="sm" onClose={closeModal}
        footer={<><button onClick={closeModal} className="cp-btn-secondary">لغو</button><button form="tag-form" type="submit" disabled={createMutation.isPending || updateMutation.isPending} className="cp-btn-primary">{(createMutation.isPending || updateMutation.isPending) ? 'در حال ذخیره...' : (editTarget ? 'ذخیره' : 'افزودن')}</button></>}
      >
        <form id="tag-form" onSubmit={handleSubmit((d) => editTarget ? updateMutation.mutate({ id: editTarget.id, d }) : createMutation.mutate(d))}>
          <div className="space-y-4">
            <div>
              <label className="cp-label">نام <span className="text-red-500">*</span></label>
              <input {...register('name')} className="cp-input h-11" placeholder="نام تگ" />
              {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
            </div>
            <div>
              <label className="cp-label">وضعیت</label>
              <input {...register('status')} className="hidden" />
            </div>
          </div>
        </form>
      </Modal>

      <ConfirmDialog open={!!deleteTarget} title="حذف تگ" message={`آیا از حذف "${deleteTarget?.name}" اطمینان دارید؟`} confirmLabel="حذف" danger loading={deleteMutation.isPending}
        onConfirm={() => deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
    </>
  );
}

// ── Main Page ─────────────────────────────────────────────────────────────────

export default function CategoriesPage() {
  const [activeTab, setActiveTab] = useState<TabKey>('provinces');

  const tab = TABS.find((t) => t.key === activeTab)!;

  return (
    <div>
      <PageHeader
        title="دسته‌بندی‌ها"
        description={tab.description}
        breadcrumbs={[{ label: 'داشبورد', to: '/admin/dashboard' }, { label: 'دسته‌بندی‌ها' }]}
      />

      <div className="cp-card overflow-hidden">
        {/* ── Tab bar ── */}
        <div className="flex overflow-x-auto border-b border-slate-200 dark:border-gray-700 px-2 pt-2 gap-1 scrollbar-none">
          {TABS.map((t) => {
            const Icon = t.icon;
            const isActive = t.key === activeTab;
            return (
              <button
                key={t.key}
                onClick={() => setActiveTab(t.key)}
                className={`flex items-center gap-2 px-3.5 py-2.5 text-sm font-medium rounded-t-xl whitespace-nowrap border-b-2 -mb-px transition-all ${
                  isActive
                    ? 'border-primary-600 text-primary-600 dark:text-primary-400 bg-primary-50/50 dark:bg-primary-400/5'
                    : 'border-transparent text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 hover:bg-slate-50 dark:hover:bg-gray-800/50'
                }`}
              >
                <Icon className="w-4 h-4 shrink-0" />
                {t.label}
              </button>
            );
          })}
        </div>

        {/* ── Bundle info bar ── */}
        <div className="flex items-center gap-3 px-6 py-3 border-b border-slate-100 dark:border-gray-700/50 bg-slate-50/50 dark:bg-gray-800/30">
          <div className={`w-7 h-7 rounded-lg flex items-center justify-center ${tab.color}`}>
            <tab.icon className="w-4 h-4" />
          </div>
          <div>
            <p className="text-xs font-medium text-slate-700 dark:text-slate-300">{tab.label}</p>
            <p className="text-[11px] text-slate-400 dark:text-slate-500">{tab.description}</p>
          </div>
        </div>

        {/* ── Tab content ── */}
        {activeTab === 'provinces'      && <ProvincesTab />}
        {activeTab === 'cities'         && <CitiesTab />}
        {activeTab === 'specialties'    && <SpecialtiesTab />}
        {activeTab === 'doctor_services' && <DoctorServicesTab />}
        {activeTab === 'insurances'     && <InsurancesTab />}
        {activeTab === 'tags'           && <TagsTab />}
      </div>
    </div>
  );
}
