import React, { useEffect, useState } from 'react';
import { backendApi, PermissionTemplateRow, PortalUserRow } from '../../services/apiClient';
import { UserRole } from '../../types';
import { Loader2, Shield, Plus, Pencil, Trash2, CheckSquare, Square } from 'lucide-react';
import { ROLE_NAMES } from '../../constants/roleAccess';
import {
  SECTION_LABELS,
  SECTION_SUBS,
  ALL_SECTION_KEYS,
  getPermissionLevel,
  permissionKey,
  PERMISSION_LEVEL_LABELS,
  type PermissionLevel,
} from '../../constants/permissions';

/** Текущий уровень доступа подраздела по массиву прав (для формы) */
function getSubLevelFromPermissions(permissions: string[], section: string, subId: string): PermissionLevel {
  const base = `${section}_${subId}`;
  if (permissions.includes(`${base}:own`)) return 'own';
  if (permissions.includes(`${base}:edit`) || permissions.includes(base)) return 'edit';
  if (permissions.includes(`${base}:read`)) return 'read';
  return 'none';
}

/** Краткое описание прав для отображения в таблице */
function formatPermissionsShort(permissions: string[]): string {
  if (!permissions.length) return '—';
  if (permissions.includes('all')) return 'Все разделы';
  const parts: string[] = [];
  for (const section of ALL_SECTION_KEYS) {
    if (permissions.includes(section)) {
      parts.push(`${SECTION_LABELS[section] || section} (все)`);
    } else {
      const subs = SECTION_SUBS[section];
      if (subs) {
        const withLevel = subs
          .map((s) => {
            const lvl = getPermissionLevel(permissions, section, s.id);
            if (lvl === 'none') return null;
            const label = PERMISSION_LEVEL_LABELS[lvl];
            return `${s.label} — ${label}`;
          })
          .filter(Boolean);
        if (withLevel.length) parts.push(`${SECTION_LABELS[section]} (${withLevel.join('; ')})`);
      }
    }
  }
  return parts.join('; ') || '—';
}

export const PermissionsSection: React.FC = () => {
  const [templates, setTemplates] = useState<PermissionTemplateRow[]>([]);
  const [portalUsers, setPortalUsers] = useState<PortalUserRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [showForm, setShowForm] = useState(false);
  const [editingId, setEditingId] = useState<number | null>(null);
  const [formName, setFormName] = useState('');
  const [formDescription, setFormDescription] = useState('');
  const [formPermissions, setFormPermissions] = useState<string[]>([]);
  const [formScope, setFormScope] = useState<'all' | 'own_district'>('all');
  const [formForPosition, setFormForPosition] = useState('');
  const [formSuggestedRole, setFormSuggestedRole] = useState<string>('');
  const [saving, setSaving] = useState(false);
  const [applyToUserId, setApplyToUserId] = useState<number | null>(null);

  const load = async () => {
    setLoading(true);
    setError(null);
    try {
      const [t, u] = await Promise.all([
        backendApi.getPermissionTemplates(),
        backendApi.getPortalUsers(),
      ]);
      setTemplates(t);
      setPortalUsers(u);
    } catch (e: any) {
      setError(e?.message || 'Ошибка загрузки');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    load();
  }, []);

  const toggleSection = (section: string) => {
    setFormPermissions((prev) => {
      const hasSection = prev.includes(section);
      const subs = SECTION_SUBS[section];
      const subKeyPrefixes = subs
        ? subs.flatMap((s) => {
            const base = `${section}_${s.id}`;
            return [base, `${base}:read`, `${base}:edit`, `${base}:own`];
          })
        : [];
      if (hasSection) {
        return prev.filter((p) => p !== section && !subKeyPrefixes.some((prefix) => p === prefix));
      } else {
        const filtered = prev.filter((p) => p !== section && !subKeyPrefixes.some((prefix) => p === prefix));
        return filtered.concat([section]);
      }
    });
  };

  const setSubLevel = (section: string, subId: string, level: PermissionLevel) => {
    setFormPermissions((prev) => {
      const base = `${section}_${subId}`;
      const toRemove = prev.filter(
        (p) => p === base || p === `${base}:read` || p === `${base}:edit` || p === `${base}:own`
      );
      const next = prev.filter((p) => !toRemove.includes(p));
      if (level !== 'none') {
        next.push(permissionKey(section, subId, level));
      }
      return next.filter((p) => p !== section);
    });
  };

  const hasSection = (section: string) => formPermissions.includes(section);
  const getSubLevel = (section: string, subId: string) => getSubLevelFromPermissions(formPermissions, section, subId);
  const hasSub = (section: string, subId: string) => getSubLevel(section, subId) !== 'none';

  const handleCreate = () => {
    setEditingId(null);
    setFormName('');
    setFormDescription('');
    setFormPermissions([]);
    setFormScope('all');
    setFormForPosition('');
    setFormSuggestedRole('');
    setShowForm(true);
  };

  const handleEdit = (t: PermissionTemplateRow) => {
    setEditingId(t.id);
    setFormName(t.name);
    setFormDescription(t.description || '');
    setFormPermissions(t.permissions || []);
    setFormScope(t.scope === 'own_district' ? 'own_district' : 'all');
    setFormForPosition(t.forPosition || '');
    setFormSuggestedRole(t.suggestedRole || '');
    setShowForm(true);
  };

  const handleSave = async () => {
    if (!formName.trim()) {
      alert('Укажите название шаблона');
      return;
    }
    setSaving(true);
    try {
      if (editingId != null) {
        await backendApi.updatePermissionTemplate(editingId, {
          name: formName.trim(),
          description: formDescription.trim() || undefined,
          permissions: formPermissions,
          scope: formScope,
          forPosition: formForPosition.trim() || null,
          suggestedRole: formSuggestedRole || null,
        });
      } else {
        await backendApi.createPermissionTemplate({
          name: formName.trim(),
          description: formDescription.trim() || undefined,
          permissions: formPermissions,
          scope: formScope,
          forPosition: formForPosition.trim() || null,
          suggestedRole: formSuggestedRole || null,
        });
      }
      setShowForm(false);
      await load();
    } catch (e: any) {
      alert(e?.message || 'Ошибка сохранения');
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async (id: number) => {
    if (!confirm('Удалить шаблон прав?')) return;
    setSaving(true);
    try {
      await backendApi.deletePermissionTemplate(id);
      await load();
    } catch (e: any) {
      alert(e?.message || 'Ошибка удаления');
    } finally {
      setSaving(false);
    }
  };

  const handleApplyToUser = async (templateId: number, portalUserId: number) => {
    const template = templates.find((t) => t.id === templateId);
    if (!template) return;
    setSaving(true);
    try {
      await backendApi.updatePortalUser(portalUserId, {
        permissions: template.permissions.length > 0 ? template.permissions : null,
        scope: template.scope || 'all',
        role: template.suggestedRole || undefined,
      });
      setApplyToUserId(null);
      await load();
    } catch (e: any) {
      alert(e?.message || 'Ошибка применения');
    } finally {
      setSaving(false);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12">
        <Loader2 className="w-8 h-8 animate-spin text-primary-500" />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex justify-between items-center">
        <h3 className="text-lg font-bold text-slate-800">Шаблоны прав</h3>
        <button
          type="button"
          onClick={handleCreate}
          className="flex items-center gap-2 px-4 py-2 bg-primary-600 text-white text-sm font-bold rounded-xl hover:bg-primary-700"
        >
          <Plus className="w-4 h-4" /> Создать шаблон
        </button>
      </div>
      <p className="text-sm text-slate-500">
        Сохраните набор прав как шаблон и применяйте его к пользователям или настраивайте права вручную в разделе «Пользователи».
      </p>

      {error && (
        <div className="rounded-xl border border-red-200 bg-red-50 p-4 text-red-700 text-sm">{error}</div>
      )}

      {showForm && (
        <div className="rounded-xl border border-slate-200 bg-slate-50 p-6 space-y-4">
          <h4 className="font-bold text-slate-800">{editingId != null ? 'Редактирование шаблона' : 'Новый шаблон'}</h4>
          <div>
            <label className="block text-xs font-bold text-slate-600 mb-1">Название</label>
            <input
              type="text"
              value={formName}
              onChange={(e) => setFormName(e.target.value)}
              placeholder="Например: Мастер участка"
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
            />
          </div>
          <div>
            <label className="block text-xs font-bold text-slate-600 mb-1">Описание (необязательно)</label>
            <input
              type="text"
              value={formDescription}
              onChange={(e) => setFormDescription(e.target.value)}
              placeholder="Краткое описание"
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
            />
          </div>
          <div>
            <label className="block text-xs font-bold text-slate-600 mb-1">Обзор данных (дашборды)</label>
            <select
              value={formScope}
              onChange={(e) => setFormScope(e.target.value as 'all' | 'own_district')}
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
            >
              <option value="all">По всем участкам (как директор)</option>
              <option value="own_district">Только свой участок (мастер / начальник участка)</option>
            </select>
            <p className="text-xs text-slate-500 mt-1">В сводках и отчётах пользователь увидит данные по всем участкам или только по своему.</p>
          </div>
          <div>
            <label className="block text-xs font-bold text-slate-600 mb-1">Должность для привязки (необязательно)</label>
            <input
              type="text"
              value={formForPosition}
              onChange={(e) => setFormForPosition(e.target.value)}
              placeholder="Например: Мастер участка, Начальник PR отдела"
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
            />
            <p className="text-xs text-slate-500 mt-1">При настройке прав пользователя можно применить шаблон по должности сотрудника.</p>
          </div>
          <div>
            <label className="block text-xs font-bold text-slate-600 mb-1">Роль по шаблону (необязательно)</label>
            <select
              value={formSuggestedRole}
              onChange={(e) => setFormSuggestedRole(e.target.value)}
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
            >
              <option value="">— Не задана —</option>
              {(Object.keys(ROLE_NAMES) as UserRole[]).map((r) => (
                <option key={r} value={r}>{ROLE_NAMES[r]}</option>
              ))}
            </select>
            <p className="text-xs text-slate-500 mt-1">При применении шаблона к пользователю можно подставить эту роль (права задаются шаблоном).</p>
          </div>
          <div>
            <label className="block text-xs font-bold text-slate-600 mb-2">Разделы и подразделы (отчёты, вкладки)</label>
            <p className="text-xs text-slate-500 mb-3">Отметьте раздел целиком или только нужные подразделы/отчёты.</p>
            <div className="space-y-1 max-h-[320px] overflow-y-auto pr-2">
              {ALL_SECTION_KEYS.map((section) => {
                const subs = SECTION_SUBS[section];
                const sectionChecked = hasSection(section);
                return (
                  <div key={section} className="rounded-lg border border-slate-200 bg-white overflow-hidden">
                    <label className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-slate-50">
                      <input
                        type="checkbox"
                        checked={sectionChecked}
                        onChange={() => toggleSection(section)}
                        className="sr-only"
                      />
                      {sectionChecked ? (
                        <CheckSquare className="w-4 h-4 text-primary-600 shrink-0" />
                      ) : (
                        <Square className="w-4 h-4 text-slate-400 shrink-0" />
                      )}
                      <span className="text-sm font-medium text-slate-800">{SECTION_LABELS[section] || section}</span>
                      {subs && subs.length > 0 && !sectionChecked && (
                        <span className="text-xs text-slate-500">
                          ({subs.filter((s) => hasSub(section, s.id)).length} из {subs.length})
                        </span>
                      )}
                    </label>
                    {subs && subs.length > 0 && !sectionChecked && (
                      <div className="pl-6 pr-3 pb-2 pt-0 space-y-2 border-t border-slate-100">
                        {subs.map((sub) => (
                          <div key={sub.id} className="flex items-center justify-between gap-2 py-1">
                            <span className="text-xs text-slate-600">{sub.label}</span>
                            <select
                              value={getSubLevel(section, sub.id)}
                              onChange={(e) => setSubLevel(section, sub.id, e.target.value as PermissionLevel)}
                              className="text-xs border border-slate-200 rounded-lg px-2 py-1 bg-white min-w-[140px]"
                            >
                              <option value="none">Нет доступа</option>
                              <option value="read">{PERMISSION_LEVEL_LABELS.read}</option>
                              <option value="edit">{PERMISSION_LEVEL_LABELS.edit}</option>
                              <option value="own">{PERMISSION_LEVEL_LABELS.own}</option>
                            </select>
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
          <div className="flex gap-2">
            <button
              type="button"
              onClick={handleSave}
              disabled={saving}
              className="px-4 py-2 bg-primary-600 text-white text-sm font-bold rounded-lg hover:bg-primary-700 disabled:opacity-50"
            >
              {saving ? <Loader2 className="w-4 h-4 animate-spin inline" /> : 'Сохранить'}
            </button>
            <button
              type="button"
              onClick={() => setShowForm(false)}
              className="px-4 py-2 border border-slate-200 text-slate-700 text-sm font-medium rounded-lg hover:bg-slate-50"
            >
              Отмена
            </button>
          </div>
        </div>
      )}

      <div className="rounded-xl border border-slate-200 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
          <thead className="bg-slate-50 border-b border-slate-200">
            <tr>
              <th className="text-left py-3 px-4 font-bold text-slate-700">Название</th>
              <th className="text-left py-3 px-4 font-bold text-slate-700">Описание</th>
              <th className="text-left py-3 px-4 font-bold text-slate-700">Обзор / Должность</th>
              <th className="text-left py-3 px-4 font-bold text-slate-700">Разделы</th>
              <th className="text-right py-3 px-4 font-bold text-slate-700">Действия</th>
            </tr>
          </thead>
          <tbody>
            {templates.length === 0 ? (
              <tr>
                <td colSpan={5} className="py-8 px-4 text-center text-slate-500">
                  Нет шаблонов. Создайте первый выше.
                </td>
              </tr>
            ) : (
              templates.map((t) => (
                <tr key={t.id} className="border-b border-slate-100 hover:bg-slate-50/50">
                  <td className="py-3 px-4 font-medium text-slate-800">{t.name}</td>
                  <td className="py-3 px-4 text-slate-600">{t.description || '—'}</td>
                  <td className="py-3 px-4 text-slate-600 text-xs">
                    {t.scope === 'own_district' ? 'Свой участок' : 'Все участки'}
                    {t.forPosition ? ` · ${t.forPosition}` : ''}
                    {t.suggestedRole ? ` · ${ROLE_NAMES[t.suggestedRole] || t.suggestedRole}` : ''}
                  </td>
                  <td className="py-3 px-4">
                    <span className="text-slate-600 text-xs">
                      {formatPermissionsShort(t.permissions || [])}
                    </span>
                  </td>
                  <td className="py-3 px-4 text-right flex items-center justify-end gap-1">
                    {applyToUserId === null ? (
                      <>
                        <button
                          type="button"
                          onClick={() => setApplyToUserId(t.id)}
                          className="p-2 text-slate-500 hover:text-primary-600"
                          title="Применить к пользователю"
                        >
                          <Shield className="w-4 h-4" />
                        </button>
                        <button
                          type="button"
                          onClick={() => handleEdit(t)}
                          className="p-2 text-slate-500 hover:text-primary-600"
                          title="Изменить"
                        >
                          <Pencil className="w-4 h-4" />
                        </button>
                        <button
                          type="button"
                          onClick={() => handleDelete(t.id)}
                          disabled={saving}
                          className="p-2 text-slate-500 hover:text-red-600"
                          title="Удалить"
                        >
                          <Trash2 className="w-4 h-4" />
                        </button>
                      </>
                    ) : applyToUserId === t.id ? (
                      <div className="flex flex-col gap-1 items-end">
                        <span className="text-xs text-slate-600">Применить к:</span>
                        <select
                          className="text-xs border border-slate-200 rounded px-2 py-1"
                          onChange={(e) => {
                            const uid = e.target.value ? Number(e.target.value) : 0;
                            if (uid) handleApplyToUser(t.id, uid);
                          }}
                        >
                          <option value="">— Выберите пользователя —</option>
                          {portalUsers.map((u) => (
                            <option key={u.id} value={u.id}>
                              {u.employeeName} ({u.login})
                            </option>
                          ))}
                        </select>
                        <button
                          type="button"
                          onClick={() => setApplyToUserId(null)}
                          className="text-xs text-slate-500 hover:text-slate-700"
                        >
                          Отмена
                        </button>
                      </div>
                    ) : null}
                  </td>
                </tr>
              ))
            )}
          </tbody>
        </table>
        </div>
      </div>
    </div>
  );
};
