import { useMemo, useState, type ReactNode } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { PlusIcon, PencilIcon, MagnifyingGlassIcon, ChevronDownIcon } from '@heroicons/react/24/outline';
import { toast } from 'sonner';
import { api } from '../lib/api';
import type { ApiResponse } from '../lib/api';
import { formatRial, formatNumber, formatDate } from '../lib/utils';
import { useAuthStore } from '../stores/authStore';
import { usePermissions } from '../hooks/usePermissions';
import { useServiceCategories, type ServiceCategoryOption } from '../hooks/useServiceCategories';
import SearchableSelect from './ui/SearchableSelect';
import type { ClinicDoctorItem } from './ClinicDoctorsManager';
import InsuranceModal, { Contract, InsuranceOption, KIND_LABEL, SOURCE_ADMIN_DEFAULT, buildInsurancePayload } from './InsuranceModal';

type Kind = 'basic' | 'supplementary';

const KINDS: { key: Kind; label: string; addLabel: string; emptyLabel: string }[] = [
  { key: 'basic', label: 'بیمه پایه', addLabel: 'افزودن بیمه پایه', emptyLabel: 'هنوز بیمه‌ی پایه‌ای اضافه نکرده‌اید.' },
  { key: 'supplementary', label: 'بیمه تکمیلی', addLabel: 'افزودن بیمه تکمیلی', emptyLabel: 'هنوز بیمه‌ی تکمیلی‌ای اضافه نکرده‌اید.' },
];

/** Contract's effective kind, falling back to 'basic' for legacy rows with no kind/type. */
const contractKind = (c: Contract): Kind =>
  (c.insurance_kind === 'supplementary' ? 'supplementary' : 'basic');

/** Case-insensitive filter over insurance name (and code) — the "جستجو در بیمه ها..." box. */
export function filterInsurances(list: Contract[], query: string): Contract[] {
  const q = query.trim().toLowerCase();
  if (!q) return list;
  return list.filter((c) =>
    (c.insurance_name ?? '').toLowerCase().includes(q) ||
    String(c.insurance_id).includes(q),
  );
}

/**
 * One-line readable summary shown on the collapsed row:
 * سرپایی ۷۰٪ · بستری ۳۰٪ · سقف پوشش … — فرانشیز فقط در قراردادهای تکمیلی.
 */
export function contractSummary(c: Contract, categories: ServiceCategoryOption[] = []): string {
  const percents = c.category_coverages ?? {};
  // برچسب‌ها فقط از سرور می‌آیند؛ تا نیامده‌اند خطِ قدیمیِ «پوشش X٪» نشان داده می‌شود
  // (کلید انگلیسیِ نوع خدمت هرگز به UI نمی‌رسد).
  const labelled = categories
    .filter((cat) => cat.key in percents)
    .map((cat) => `${cat.label} ${formatNumber(percents[cat.key])}٪`);

  const parts = labelled.length > 0 ? labelled : [`پوشش ${formatNumber(c.coverage_percent)}٪`];
  if (c.insurance_kind === 'supplementary' && c.franchise_percent > 0) {
    parts.push(`فرانشیز ${formatNumber(c.franchise_percent)}٪`);
  }
  parts.push(c.annual_ceiling_rials != null ? `سقف پوشش ${formatRial(c.annual_ceiling_rials)}` : 'سقف پوشش نامحدود');

  return parts.join(' · ');
}

export default function TenantInsuranceContracts() {
  const qc = useQueryClient();
  const { dbUuid, context, availableContexts } = useAuthStore();
  // مجوزهای منشی؛ برای owner/پزشک همیشه true (usePermissions بدون context آزاد است).
  const { can } = usePermissions();
  const canCreate = can('insurances', 'create');
  const canUpdate = can('insurances', 'update');
  const [tab, setTab] = useState<Kind>('basic');
  const [modalOpen, setModalOpen] = useState(false);
  const [editContract, setEditContract] = useState<Contract | null>(null);
  const [search, setSearch] = useState('');
  const [expanded, setExpanded] = useState<string | null>(null);
  const [pickedDoctorUuid, setPickedDoctorUuid] = useState<string | null>(null);

  // A user who is both a doctor and a clinic owner may have a doctor db_uuid active;
  // fall back to the clinic context so the roster query targets the clinic. Same
  // resolution as ClinicAppointmentSettingsPage.
  const clinicUuid = useMemo(() => {
    if (context?.type === 'clinic') return dbUuid;
    return availableContexts.find((c) => c.type === 'clinic')?.db_uuid ?? null;
  }, [context, dbUuid, availableContexts]);

  const doctorsQuery = useQuery({
    queryKey: ['clinic-doctors', clinicUuid],
    queryFn: () => api.get<ApiResponse<{ data: ClinicDoctorItem[] }>>(`/api/v1/clinic/doctor-list/${clinicUuid}`),
    enabled: !!clinicUuid,
  });

  const doctorList: ClinicDoctorItem[] = useMemo(() => {
    const raw = doctorsQuery.data?.data;
    return (raw as any)?.data ?? raw ?? [];
  }, [doctorsQuery.data]);

  // In a clinic, insurance is per-doctor: default to the first doctor. Solo doctors /
  // personal offices have no clinic context → doctorUuid stays null → backend keeps the
  // legacy tenant-scoped behavior.
  const isClinic = !!clinicUuid;
  const doctorUuid = useMemo(
    () => (isClinic ? pickedDoctorUuid ?? doctorList[0]?.uuid ?? null : null),
    [isClinic, pickedDoctorUuid, doctorList],
  );
  const showDoctorPicker = isClinic && doctorList.length > 1;
  const dq = doctorUuid ? `?doctor_uuid=${encodeURIComponent(doctorUuid)}` : '';

  const contractsQuery = useQuery({
    queryKey: ['tenant-insurances', doctorUuid],
    queryFn: () => api.get(`/api/v1/billing/tenant-insurances${dq}`),
  });

  const { categories } = useServiceCategories();

  const pricingQuery = useQuery({
    queryKey: ['insurance-pricing', doctorUuid],
    queryFn: () => api.get(`/api/v1/insurance-pricing${dq}`),
  });

  const contracts: Contract[] = (contractsQuery.data as any)?.data?.data ?? [];
  const allInsurances: InsuranceOption[] = (pricingQuery.data as any)?.data?.insurances ?? [];

  // فرم قرارداد فقط نوع خدمت‌هایی را می‌گیرد که همین tenant بیمه‌ای‌شان می‌کند؛
  // لیست سراسری service-categories اینجا اشتباه است چون نوع خاموش را هم می‌آورد.
  const enabledCategories: ServiceCategoryOption[] = useMemo(
    () => ((pricingQuery.data as any)?.data?.service_categories ?? [])
      .filter((c: { enabled: boolean }) => c.enabled)
      .map((c: { key: string; label: string }) => ({ key: c.key, label: c.label })),
    [pricingQuery.data],
  );
  const activeIds = new Set(contracts.map((c) => c.insurance_id));
  // Add-mode options: only the active tab's kind, excluding already-contracted insurances.
  const available = allInsurances.filter((i) => i.type === tab).filter((i) => !activeIds.has(i.insurance_id));

  // The insurance's real type comes from the catalog, not the contract's stored kind
  // (legacy contracts carry a stale manually-picked kind). Catalog type is authoritative.
  const catalogTypeById = useMemo(() => {
    const m: Record<number, Kind> = {};
    for (const i of allInsurances) m[i.insurance_id] = i.type === 'supplementary' ? 'supplementary' : 'basic';
    return m;
  }, [allInsurances]);
  const kindOf = (c: Contract): Kind =>
    catalogTypeById[c.insurance_id] ?? contractKind(c);

  const byKind = useMemo(() => contracts.filter((c) => kindOf(c) === tab), [contracts, tab, catalogTypeById]);
  const rows = useMemo(() => filterInsurances(byKind, search), [byKind, search]);
  const counts = useMemo(() => ({
    basic: contracts.filter((c) => kindOf(c) === 'basic').length,
    supplementary: contracts.filter((c) => kindOf(c) === 'supplementary').length,
  }), [contracts, catalogTypeById]);

  const invalidate = () => qc.invalidateQueries({ queryKey: ['tenant-insurances', doctorUuid] });
  const toggleRow = (uuid: string) => setExpanded((p) => (p === uuid ? null : uuid));

  const saveMut = useMutation({
    mutationFn: (payload: ReturnType<typeof buildInsurancePayload>) =>
      editContract
        ? api.patch(`/api/v1/billing/tenant-insurances/${editContract.uuid}`, payload)
        : api.post('/api/v1/billing/tenant-insurances', payload),
    onSuccess: () => {
      toast.success(editContract ? 'قرارداد بیمه ویرایش شد' : 'قرارداد بیمه فعال شد');
      closeModal();
      invalidate();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const toggleMut = useMutation({
    mutationFn: (c: Contract) =>
      api.patch(`/api/v1/billing/tenant-insurances/${c.uuid}`, {
        is_active: !c.is_active,
        ...(doctorUuid ? { doctor_uuid: doctorUuid } : {}),
      }),
    onSuccess: () => invalidate(),
    onError: (e: Error) => toast.error(e.message),
  });

  const openAdd = () => { setEditContract(null); setModalOpen(true); };
  const openEdit = (c: Contract) => { setEditContract(c); setModalOpen(true); };
  const closeModal = () => { setModalOpen(false); setEditContract(null); };

  const activeKind = KINDS.find((k) => k.key === tab)!;

  return (
    <div className="card" style={{ padding: 20 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, marginBottom: 16, flexWrap: 'wrap' }}>
        <h2 style={{ fontSize: 15, fontWeight: 700, margin: 0 }}>مدیریت بیمه</h2>
        {canCreate && (
          <button className="btn primary sm" onClick={openAdd}>
            <PlusIcon style={{ width: 15 }} /> {activeKind.addLabel}
          </button>
        )}
      </div>

      {showDoctorPicker && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 16, maxWidth: 320 }}>
          <label style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-2)' }}>پزشک</label>
          <SearchableSelect
            options={doctorList.map((d) => ({ value: d.uuid, label: d.name }))}
            value={doctorUuid ?? ''}
            onChange={(v) => { setPickedDoctorUuid(v ? String(v) : null); setExpanded(null); }}
            placeholder="انتخاب پزشک..."
          />
          <span style={{ fontSize: 11, color: 'var(--text-3)' }}>
            تنظیمات بیمه برای هر پزشک جداگانه ذخیره می‌شود.
          </span>
        </div>
      )}

      <div role="tablist" style={{ display: 'flex', gap: 4, borderBottom: '1px solid var(--border)', marginBottom: 16 }}>
        {KINDS.map((k) => {
          const active = k.key === tab;
          return (
            <button
              key={k.key}
              role="tab"
              aria-selected={active}
              onClick={() => { setTab(k.key); setExpanded(null); }}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 6, padding: '8px 14px',
                background: 'none', border: 'none', cursor: 'pointer', fontSize: 13, fontWeight: 600,
                color: active ? 'var(--primary)' : 'var(--text-3)',
                borderBottom: `2px solid ${active ? 'var(--primary)' : 'transparent'}`,
                marginBottom: -1, transition: 'color .2s, border-color .2s',
              }}
            >
              {k.label}
              <span style={{
                fontSize: 11, fontWeight: 700, minWidth: 18, padding: '0 6px', borderRadius: 'var(--r-pill)',
                background: active ? 'var(--primary-soft)' : 'var(--surface-2)', color: active ? 'var(--primary)' : 'var(--text-3)',
              }}>
                {formatNumber(counts[k.key])}
              </span>
            </button>
          );
        })}
      </div>

      <div style={{ position: 'relative', marginBottom: 16 }}>
        <MagnifyingGlassIcon style={{ width: 16, position: 'absolute', insetInlineStart: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-3)' }} />
        <input
          className="input"
          style={{ paddingInlineStart: 36 }}
          placeholder="جستجو در بیمه ها..."
          value={search}
          onChange={(e) => setSearch(e.target.value)}
        />
      </div>

      {contractsQuery.isLoading ? (
        <div className="muted" style={{ fontSize: 13 }}>در حال بارگذاری...</div>
      ) : rows.length === 0 ? (
        <div style={{ fontSize: 12.5, color: 'var(--text-3)', padding: '16px 0', textAlign: 'center' }}>
          {search ? 'بیمه‌ای یافت نشد.' : activeKind.emptyLabel}
        </div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          {rows.map((c) => (
            <ContractCard
              key={c.uuid}
              contract={c}
              categories={categories}
              open={expanded === c.uuid}
              onToggleRow={() => toggleRow(c.uuid)}
              onEdit={() => openEdit(c)}
              onToggleStatus={() => toggleMut.mutate(c)}
              statusPending={toggleMut.isPending}
              canUpdate={canUpdate}
            />
          ))}
        </div>
      )}

      <InsuranceModal
        open={modalOpen}
        editContract={editContract}
        options={editContract ? allInsurances : available}
        categories={enabledCategories}
        kind={editContract ? kindOf(editContract) : tab}
        doctorUuid={doctorUuid}
        canUpdate={canUpdate}
        onClose={closeModal}
        onSubmit={(payload) => saveMut.mutate(payload)}
        isPending={saveMut.isPending}
      />
    </div>
  );
}

interface RowProps {
  contract: Contract;
  categories: ServiceCategoryOption[];
  open: boolean;
  onToggleRow: () => void;
  onEdit: () => void;
  onToggleStatus: () => void;
  statusPending?: boolean;
  canUpdate?: boolean;
}

function ContractCard({ contract: c, categories, open, onToggleRow, onEdit, onToggleStatus, statusPending, canUpdate }: RowProps) {
  const stop = (fn: () => void) => (e: React.MouseEvent) => { e.stopPropagation(); fn(); };
  return (
    <div style={{ border: '1px solid var(--border)', borderRadius: 12, padding: 14, cursor: 'pointer' }} onClick={onToggleRow}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <ChevronDownIcon style={{ width: 15, color: 'var(--text-3)', transition: 'transform .2s var(--ease)', transform: open ? 'rotate(180deg)' : 'none' }} />
          <div style={{ fontWeight: 700, fontSize: 14 }}>{c.insurance_name ?? `#${c.insurance_id}`}</div>
        </div>
        {canUpdate && (
          <button className="mini-btn" title="ویرایش" onClick={stop(onEdit)}>
            <PencilIcon style={{ width: 15 }} />
          </button>
        )}
      </div>
      <div style={{ fontSize: 12, color: 'var(--text-2)', marginBottom: 8 }}>{contractSummary(c, categories)}</div>
      {canUpdate && (
        <div style={{ display: 'flex', justifyContent: 'flex-end' }} onClick={stop(() => {})}>
          <StatusToggle contract={c} onToggle={stop(onToggleStatus)} disabled={statusPending} />
        </div>
      )}
      {open && <div style={{ marginTop: 10 }}><ContractDetails contract={c} categories={categories} /></div>}
    </div>
  );
}

/** Expanded full detail of a contract (all fields), shown when its card is open. */
function ContractDetails({ contract: c, categories }: { contract: Contract; categories: ServiceCategoryOption[] }) {
  const percents = c.category_coverages ?? {};
  const isSupplementary = c.insurance_kind === 'supplementary';
  const perCategory = categories.filter((cat) => cat.key in percents);

  return (
    <div style={{
      background: 'var(--surface-2)', border: '1px solid var(--border-2)', borderRadius: 'var(--r-sm)',
      padding: 14,
      display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: 14,
    }}>
      {perCategory.length === 0 && (
        <DetailCell label="درصد پوشش" value={`${formatNumber(c.coverage_percent)}٪`} />
      )}
      {perCategory.map((cat) => (
        <DetailCell
          key={cat.key}
          label={`درصد پوشش — ${cat.label}`}
          value={
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              {formatNumber(percents[cat.key])}٪
              {c.category_coverage_source?.[cat.key] === SOURCE_ADMIN_DEFAULT && (
                <span style={{ fontSize: 10.5, fontWeight: 600, color: 'var(--text-3)' }}>پیش‌فرض ادمین</span>
              )}
            </span>
          }
        />
      ))}
      {isSupplementary && (
        <DetailCell label="فرانشیز" value={c.franchise_percent > 0 ? `${formatNumber(c.franchise_percent)}٪` : '—'} />
      )}
      <DetailCell label="سقف تعهد سالانه" value={c.annual_ceiling_rials != null ? formatRial(c.annual_ceiling_rials) : 'نامحدود'} />
      <DetailCell label="تاریخ شروع قرارداد" value={formatDate(c.effective_from)} />
      <DetailCell label="تاریخ پایان قرارداد" value={c.effective_to != null ? formatDate(c.effective_to) : 'بدون تاریخ پایان'} />
      <DetailCell label="نسخه قرارداد" value={<span dir="ltr">{formatNumber(c.version)}</span>} />
      <DetailCell label="کد بیمه" value={<span dir="ltr">{c.insurance_id}</span>} />
      <DetailCell
        label="وضعیت"
        value={
          <span style={{ color: c.is_active ? 'var(--success)' : 'var(--text-3)', fontWeight: 700 }}>
            {c.is_active ? 'فعال' : 'غیرفعال'}
          </span>
        }
      />
    </div>
  );
}

function DetailCell({ label, value }: { label: string; value: ReactNode }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <span style={{ fontSize: 11, color: 'var(--text-3)' }}>{label}</span>
      <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--text)' }}>{value}</span>
    </div>
  );
}

function StatusToggle({ contract, onToggle, disabled }: { contract: Contract; onToggle: (e: React.MouseEvent) => void; disabled?: boolean }) {
  return (
    <button
      type="button"
      role="switch"
      aria-checked={contract.is_active}
      aria-label={contract.is_active ? 'غیرفعال کردن' : 'فعال کردن'}
      onClick={onToggle}
      disabled={disabled}
      style={{ display: 'inline-flex', alignItems: 'center', gap: 8, background: 'none', border: 'none', cursor: disabled ? 'default' : 'pointer', padding: 0 }}
    >
      <span style={{
        width: 36, height: 20, borderRadius: 999, position: 'relative', transition: 'background .2s',
        background: contract.is_active ? 'var(--primary)' : 'var(--border)',
      }}>
        <span style={{
          position: 'absolute', top: 2, width: 16, height: 16, borderRadius: 999, background: 'var(--surface)', transition: 'inset-inline .2s',
          insetInlineStart: contract.is_active ? 18 : 2,
        }} />
      </span>
      <span style={{ fontSize: 12, color: contract.is_active ? 'var(--success)' : 'var(--text-3)' }}>
        {contract.is_active ? 'فعال' : 'غیرفعال'}
      </span>
    </button>
  );
}
