import React, { useEffect, useMemo, useState } from 'react';
import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
import SearchableSelect from './ui/SearchableSelect';
import ConfirmDialog from './ui/ConfirmDialog';
import { formatRial } from '../lib/utils';
import {
  useAllServiceItems,
  useSelectionPreview,
  useServiceGroups,
  useServiceRelations,
  type ItemRelation,
} from '../hooks/useServiceCatalog';

interface Props {
  serviceUuid: string;
  canEdit: boolean;
  /** روابط فعلیِ سرویس از پاسخ جزئیات — `PUT` جایگزینی کامل است. */
  initialRelations?: ItemRelation[];
}

const RELATION_LABELS: Record<ItemRelation['type'], string> = {
  incompatible_with: 'با هم انجام نمی‌شوند',
  requires: 'پیش‌نیاز دارد',
};

/**
 * گروه‌های انتخاب و روابط آیتم‌ها — بخش UI تسک ۰۴.
 *
 * پیش‌نمایش مدت و قیمت از **همان** اندپوینتی می‌آید که سایت عمومی می‌زند
 * (`service-selection/validate`)، نه از یک جمع‌زدن جداگانه در فرانت: دو محاسبه یعنی
 * بالاخره روزی دو عدد متفاوت به اپراتور و بیمار نشان داده شود.
 */
export default function ServiceGroupsTab({ serviceUuid, canEdit, initialRelations = [] }: Props) {
  const { groups, loading, create, update, remove, setItems } = useServiceGroups(serviceUuid);
  const { save: saveRelations } = useServiceRelations(serviceUuid);
  const { items } = useAllServiceItems();

  const [newGroupName, setNewGroupName] = useState('');
  const [deleting, setDeleting] = useState<string | null>(null);
  const [relations, setRelations] = useState<ItemRelation[]>(initialRelations);

  // ── پیش‌نمایش زنده با debounce ───────────────────────────────────────────
  // بدون تأخیر، هر کلیک روی چیپ یک درخواست می‌سازد و اپراتورِ سریع، ده درخواست.
  const [selected, setSelected] = useState<string[]>([]);
  const [debounced, setDebounced] = useState<string[]>([]);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(selected), 400);
    return () => clearTimeout(timer);
  }, [selected]);

  const { preview, loading: previewing } = useSelectionPreview(debounced, serviceUuid);

  const itemOptions = useMemo(
    () => items.map((i) => ({ value: i.uuid, label: i.name })),
    [items],
  );

  const nameOf = (uuid: string) => items.find((i) => i.uuid === uuid)?.name ?? uuid;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      {/* ── گروه‌ها ───────────────────────────────────────────────────────── */}
      <section className="card card-pad" style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <h3 style={{ fontSize: 15, margin: 0 }}>گروه‌های انتخاب</h3>
          <span style={{ fontSize: 12, color: 'var(--text-3)' }}>
            «حتماً یک سطح انرژی، فقط یکی» یعنی حداقل ۱ و حداکثر ۱. حداکثرِ خالی یعنی نامحدود.
          </span>
        </div>

        {canEdit && (
          <div style={{ display: 'flex', alignItems: 'flex-end', gap: 8, flexWrap: 'wrap' }}>
            <div className="field-block" style={{ minWidth: 240, margin: 0 }}>
              <label htmlFor="new-group">گروه تازه</label>
              <input
                id="new-group"
                className="input"
                value={newGroupName}
                onChange={(e) => setNewGroupName(e.target.value)}
                placeholder="مثلاً: نواحی بدن"
              />
            </div>
            <button
              type="button"
              className="btn primary sm"
              disabled={newGroupName.trim() === '' || create.isPending}
              onClick={async () => {
                await create.mutateAsync({ name: newGroupName.trim(), min_select: 0, max_select: null });
                setNewGroupName('');
              }}
            >
              <PlusIcon style={{ width: 15 }} /> افزودن گروه
            </button>
          </div>
        )}

        {loading ? (
          <span style={{ fontSize: 13, color: 'var(--text-3)' }}>در حال بارگذاری…</span>
        ) : groups.length === 0 ? (
          <span style={{ fontSize: 13, color: 'var(--text-3)' }}>
            این سرویس گروه انتخابی ندارد؛ بیمار هر ترکیبی را می‌تواند انتخاب کند.
          </span>
        ) : (
          groups.map((group) => (
            <div
              key={group.uuid}
              style={{
                border: '1px solid var(--border)',
                borderRadius: 'var(--r)',
                padding: 14,
                display: 'flex',
                flexDirection: 'column',
                gap: 10,
              }}
            >
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
                <input
                  className="input"
                  style={{ maxWidth: 220 }}
                  defaultValue={group.name}
                  disabled={!canEdit}
                  onBlur={(e) => {
                    if (e.target.value.trim() !== '' && e.target.value !== group.name) {
                      update.mutate({ uuid: group.uuid, body: { name: e.target.value.trim() } });
                    }
                  }}
                />

                <label style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 4 }}>
                  حداقل
                  <input
                    className="input"
                    style={{ width: 70 }}
                    type="number"
                    min={0}
                    defaultValue={group.min_select}
                    disabled={!canEdit}
                    onBlur={(e) =>
                      update.mutate({ uuid: group.uuid, body: { min_select: Number(e.target.value) } })
                    }
                  />
                </label>

                <label style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 4 }}>
                  حداکثر
                  <input
                    className="input"
                    style={{ width: 70 }}
                    type="number"
                    min={0}
                    placeholder="نامحدود"
                    defaultValue={group.max_select ?? ''}
                    disabled={!canEdit}
                    onBlur={(e) =>
                      update.mutate({
                        uuid: group.uuid,
                        // خالی یعنی نامحدود؛ صفر یعنی «هیچ‌کدام» و معنای متفاوتی دارد.
                        body: { max_select: e.target.value === '' ? null : Number(e.target.value) },
                      })
                    }
                  />
                </label>

                {canEdit && (
                  <button
                    type="button"
                    className="btn secondary sm"
                    style={{ marginRight: 'auto' }}
                    onClick={() => setDeleting(group.uuid)}
                    aria-label="حذف گروه"
                  >
                    <TrashIcon style={{ width: 15 }} />
                  </button>
                )}
              </div>

              <div className="field-block" style={{ margin: 0 }}>
                <label>آیتم‌های این گروه</label>
                <SearchableSelect
                  value={null}
                  onChange={(v) => {
                    const uuid = String(v ?? '');
                    if (uuid && !group.items.some((i) => i.uuid === uuid)) {
                      setItems.mutate({
                        uuid: group.uuid,
                        itemUuids: [...group.items.map((i) => i.uuid), uuid],
                      });
                    }
                  }}
                  options={itemOptions.filter((o) => !group.items.some((i) => i.uuid === o.value))}
                  placeholder="افزودن آیتم"
                  isDisabled={!canEdit}
                />
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
                  {group.items.map((item) => (
                    <button
                      key={item.uuid}
                      type="button"
                      className="badge"
                      disabled={!canEdit}
                      onClick={() =>
                        setItems.mutate({
                          uuid: group.uuid,
                          itemUuids: group.items.filter((i) => i.uuid !== item.uuid).map((i) => i.uuid),
                        })
                      }
                    >
                      {item.name} ✕
                    </button>
                  ))}
                  {group.items.length === 0 && (
                    <span style={{ fontSize: 12, color: 'var(--danger)' }}>
                      گروه بدون آیتم، حداقلِ انتخابش هرگز برآورده نمی‌شود.
                    </span>
                  )}
                </div>
              </div>
            </div>
          ))
        )}
      </section>

      {/* ── روابط ─────────────────────────────────────────────────────────── */}
      <section className="card card-pad" style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <h3 style={{ fontSize: 15, margin: 0 }}>ناسازگاری و پیش‌نیاز</h3>
          <span style={{ fontSize: 12, color: 'var(--text-3)' }}>
            ناسازگاری متقارن است؛ پیش‌نیاز جهت‌دار. حلقهٔ پیش‌نیاز هنگام ذخیره رد می‌شود.
          </span>
        </div>

        {relations.map((relation, index) => (
          <div key={index} style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <div style={{ minWidth: 200 }}>
              <SearchableSelect
                value={relation.related_item_uuid}
                onChange={(v) =>
                  setRelations(
                    relations.map((r, i) =>
                      i === index ? { ...r, related_item_uuid: String(v ?? '') } : r,
                    ),
                  )
                }
                options={itemOptions}
                isDisabled={!canEdit}
              />
            </div>

            <div style={{ minWidth: 190 }}>
              <SearchableSelect
                value={relation.type}
                onChange={(v) =>
                  setRelations(
                    relations.map((r, i) =>
                      i === index ? { ...r, type: (v as ItemRelation['type']) ?? 'incompatible_with' } : r,
                    ),
                  )
                }
                options={Object.entries(RELATION_LABELS).map(([value, label]) => ({ value, label }))}
                isDisabled={!canEdit}
              />
            </div>

            {canEdit && (
              <button
                type="button"
                className="btn secondary sm"
                onClick={() => setRelations(relations.filter((_, i) => i !== index))}
                aria-label="حذف رابطه"
              >
                <TrashIcon style={{ width: 15 }} />
              </button>
            )}
          </div>
        ))}

        {canEdit && (
          <div style={{ display: 'flex', gap: 8 }}>
            <button
              type="button"
              className="btn secondary sm"
              onClick={() =>
                setRelations([...relations, { related_item_uuid: '', type: 'incompatible_with' }])
              }
            >
              <PlusIcon style={{ width: 15 }} /> افزودن رابطه
            </button>
            <button
              type="button"
              className="btn primary sm"
              disabled={saveRelations.isPending || relations.some((r) => r.related_item_uuid === '')}
              onClick={() => saveRelations.mutate(relations)}
            >
              ذخیرهٔ روابط
            </button>
          </div>
        )}
      </section>

      {/* ── پیش‌نمایش زنده ────────────────────────────────────────────────── */}
      <section className="card card-pad" style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <h3 style={{ fontSize: 15, margin: 0 }}>پیش‌نمایش انتخاب</h3>
          <span style={{ fontSize: 12, color: 'var(--text-3)' }}>
            همان محاسبه‌ای که بیمار می‌بیند — یک آیتم با «مدت تنها» و بقیه با «مدت اضافه».
          </span>
        </div>

        <SearchableSelect
          value={null}
          onChange={(v) => {
            const uuid = String(v ?? '');
            if (uuid && !selected.includes(uuid)) setSelected([...selected, uuid]);
          }}
          options={itemOptions.filter((o) => !selected.includes(o.value))}
          placeholder="آیتمی را برای آزمایش انتخاب کنید"
        />

        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {selected.map((uuid) => (
            <button
              key={uuid}
              type="button"
              className="badge"
              onClick={() => setSelected(selected.filter((u) => u !== uuid))}
            >
              {nameOf(uuid)} ✕
            </button>
          ))}
        </div>

        {selected.length === 0 ? (
          <span style={{ fontSize: 13, color: 'var(--text-3)' }}>
            چند آیتم انتخاب کنید تا مدت، قیمت و خطاهای ترکیب را ببینید.
          </span>
        ) : previewing ? (
          <span style={{ fontSize: 13, color: 'var(--text-3)' }}>در حال محاسبه…</span>
        ) : preview ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', fontSize: 14 }}>
              <span>
                مدت: <strong>{preview.total_duration_minutes}</strong> دقیقه
              </span>
              <span>قیمت: {formatRial(preview.total_price_rials)}</span>
              {preview.valid ? (
                <span className="badge green"><span className="bdot" />ترکیب معتبر</span>
              ) : (
                <span className="badge red"><span className="bdot" />ترکیب نامعتبر</span>
              )}
            </div>

            {/* همهٔ خطاها با هم می‌آیند، نه اولی — کاربر نباید سه بار رفت‌وبرگشت کند. */}
            {preview.errors.map((error, index) => (
              <span key={index} style={{ fontSize: 13, color: 'var(--danger)' }}>
                {error.message}
              </span>
            ))}

            <div style={{ overflowX: 'auto' }}>
              <table style={{ width: '100%', fontSize: 13, borderCollapse: 'collapse' }}>
                <thead>
                  <tr style={{ color: 'var(--text-3)', textAlign: 'right' }}>
                    <th style={{ padding: '6px 4px', fontWeight: 500 }}>آیتم</th>
                    <th style={{ padding: '6px 4px', fontWeight: 500 }}>شمرده‌شده به‌عنوان</th>
                    <th style={{ padding: '6px 4px', fontWeight: 500 }}>دقیقه</th>
                    <th style={{ padding: '6px 4px', fontWeight: 500 }}>قیمت</th>
                  </tr>
                </thead>
                <tbody>
                  {preview.breakdown.map((row) => (
                    <tr key={row.item_uuid} style={{ borderTop: '1px solid var(--border)' }}>
                      <td style={{ padding: '6px 4px' }}>{row.item_name}</td>
                      <td style={{ padding: '6px 4px', color: 'var(--text-2)' }}>
                        {row.counted_as === 'solo' ? 'مدت تنها (لنگر)' : 'مدت اضافه'}
                      </td>
                      <td style={{ padding: '6px 4px' }}>{row.minutes}</td>
                      <td style={{ padding: '6px 4px' }}>{formatRial(row.price_rials)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        ) : null}
      </section>

      <ConfirmDialog
        open={deleting !== null}
        title="حذف گروه"
        message="آیتم‌های گروه حذف نمی‌شوند؛ فقط قاعدهٔ «حداقل/حداکثر انتخاب» برداشته می‌شود."
        confirmLabel="حذف کن"
        danger
        loading={remove.isPending}
        onCancel={() => setDeleting(null)}
        onConfirm={async () => {
          await remove.mutateAsync(deleting!);
          setDeleting(null);
        }}
      />
    </div>
  );
}
