import React, { useEffect, useMemo, useState } from 'react';
import {
  DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors,
} from '@dnd-kit/core';
import {
  arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { ruleTemplates } from '../templates/ruleTemplates.js';
import { ruleErrors, hasErrors } from '../utils/validation.js';
import { RuleEditorDrawer } from './RuleEditorDrawer.jsx';
import { RouteChecker } from './RouteChecker.jsx';
import { api } from '../api.js';

const OUTBOUND_KIND = {
  direct: { kind: 'success', label: 'direct' },
  vpn:    { kind: 'info',    label: 'VPN' },
  block:  { kind: 'danger',  label: 'block' },
};

const DEVICE_MODES = {
  bypass: { kind: 'warning', label: 'bypass TProxy', hint: 'мимо sing-box; ручной proxy отдельно' },
  direct: { kind: 'success', label: 'direct', hint: 'fallback после global rules' },
  vpn:    { kind: 'info',    label: 'VPN',    hint: 'fallback после global rules' },
  rules:  { kind: 'neutral', label: 'default', hint: 'использует transparent default' },
  block:  { kind: 'danger',  label: 'block',  hint: 'fallback после global rules' },
};

function DeviceModeSelect({ value, onChange }) {
  return (
    <select className="select sm" value={value || 'rules'} onChange={(e) => onChange(e.target.value)}>
      <option value="bypass">bypass TProxy</option>
      <option value="direct">direct</option>
      <option value="vpn">VPN</option>
      <option value="rules">default</option>
      <option value="block">block</option>
    </select>
  );
}

function DevicesCard({ devicesConfig, onDefaultsChange, onAdd, onUpdate, onRemove }) {
  const devices = devicesConfig?.devices || [];
  const defaultTransparentMode = devicesConfig?.defaultTransparentMode || devicesConfig?.defaultMode || 'vpn';
  const proxyDefaultMode = devicesConfig?.proxyDefaultMode || 'vpn';

  return (
    <div className="card">
      <div className="card-header">
        <div>
          <h2>Устройства</h2>
          <small className="muted">bypass TProxy применяется до sing-box. Остальные режимы — fallback после global rules.</small>
        </div>
        <div className="btn-group">
          <label className="field" style={{ minWidth: 180, margin: 0 }}>
            <span className="field-label">Transparent default</span>
            <select
              className="select sm"
              value={defaultTransparentMode}
              onChange={(e) => onDefaultsChange({ defaultTransparentMode: e.target.value })}
            >
              <option value="direct">direct</option>
              <option value="vpn">VPN</option>
              <option value="block">block</option>
            </select>
          </label>
          <label className="field" style={{ minWidth: 160, margin: 0 }}>
            <span className="field-label">Proxy default</span>
            <select
              className="select sm"
              value={proxyDefaultMode}
              onChange={(e) => onDefaultsChange({ proxyDefaultMode: e.target.value })}
            >
              <option value="vpn">VPN</option>
              <option value="direct">direct</option>
              <option value="block">block</option>
            </select>
          </label>
          <button className="btn btn-primary sm" onClick={onAdd}>
            + Добавить устройство
          </button>
        </div>
      </div>
      {devices.length === 0 ? (
        <div className="empty-state" style={{ padding: '16px 0' }}>
          <p style={{ margin: 0 }}>Нет профилей устройств. Неизвестные transparent-устройства используют transparent default.</p>
        </div>
      ) : (
        <div style={{ overflowX: 'auto' }}>
          <table className="table">
            <thead>
              <tr>
                <th style={{ width: 40 }}></th>
                <th>Название</th>
                <th style={{ width: 170 }}>IP</th>
                <th style={{ width: 150 }}>MAC</th>
                <th style={{ width: 150 }}>Mode</th>
                <th>Поведение</th>
                <th style={{ width: 40 }}></th>
              </tr>
            </thead>
            <tbody>
              {devices.map((dev) => {
                const mode = DEVICE_MODES[dev.mode] || DEVICE_MODES.rules;
                return (
                  <tr key={dev.id} className={dev.enabled !== false ? '' : 'disabled'}>
                    <td>
                      <input
                        type="checkbox"
                        checked={dev.enabled !== false}
                        onChange={(e) => onUpdate(dev.id, { enabled: e.target.checked })}
                        style={{ accentColor: 'var(--accent)' }}
                      />
                    </td>
                    <td>
                      <input
                        className="input sm"
                        value={dev.name || ''}
                        onChange={(e) => onUpdate(dev.id, { name: e.target.value })}
                        placeholder="Название устройства"
                        style={{ width: '100%', minWidth: 120 }}
                      />
                    </td>
                    <td>
                      <input
                        className="input sm"
                        value={dev.ip || ''}
                        onChange={(e) => onUpdate(dev.id, { ip: e.target.value })}
                        placeholder="192.168.1.50"
                        style={{ width: '100%', minWidth: 140 }}
                      />
                    </td>
                    <td>
                      <input
                        className="input sm"
                        value={dev.mac || ''}
                        onChange={(e) => onUpdate(dev.id, { mac: e.target.value })}
                        placeholder="опционально"
                        style={{ width: '100%', minWidth: 120 }}
                      />
                    </td>
                    <td>
                      <DeviceModeSelect value={dev.mode} onChange={(mode) => onUpdate(dev.id, { mode })} />
                    </td>
                    <td>
                      <span className={`badge ${mode.kind}`}>{mode.label}</span>
                      <small className="muted" style={{ marginLeft: 8 }}>{mode.hint}</small>
                    </td>
                    <td>
                      <button
                        className="btn btn-ghost sm"
                        onClick={() => {
                          if (confirm('Удалить устройство?')) onRemove(dev.id);
                        }}
                      >×</button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function summary(rule) {
  const parts = [];
  const totalDomains = (rule.domains?.length || 0) + (rule.domainSuffixes?.length || 0) + (rule.domainKeywords?.length || 0);
  if (totalDomains) parts.push(`${totalDomains} дом.`);
  if (rule.ipCidrs?.length) parts.push(`${rule.ipCidrs.length} CIDR`);
  if (rule.ports?.length) parts.push(`${rule.ports.length} портов`);
  if (rule.networks?.length) parts.push(rule.networks.join('/'));
  return parts.join(' · ') || '—';
}

function SortableRuleRow({ rule, index, total, onEdit, onUpdate, onRemove, conflict }) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: rule.id });
  const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1 };
  const errors = ruleErrors(rule);
  const invalid = hasErrors(errors);
  const ob = OUTBOUND_KIND[rule.outbound] || OUTBOUND_KIND.direct;

  return (
    <tr ref={setNodeRef} style={style} className={`rule-row ${rule.enabled ? '' : 'disabled'} ${invalid ? 'invalid' : ''}`}>
      <td style={{ width: 30 }}>
        <span className="drag-handle" {...attributes} {...listeners} title="Перетащить">⠿</span>
      </td>
      <td style={{ width: 36 }} className="muted text-mono">#{index + 1}</td>
      <td>
        <div className="flex" style={{ alignItems: 'center' }}>
          <input
            type="checkbox"
            checked={rule.enabled !== false}
            onChange={(e) => onUpdate(rule.id, { enabled: e.target.checked })}
            style={{ accentColor: 'var(--accent)' }}
          />
          <button className="btn btn-link" style={{ padding: 0, fontWeight: 600 }} onClick={() => onEdit(rule.id)}>
            {rule.name || '(без названия)'}
          </button>
          {invalid && <span className="badge danger">ошибки</span>}
          {conflict && <span className={`badge ${conflict.severity === 'warning' ? 'warning' : 'info'}`} title={`Перекрывается с #${conflict.conflictWithIndex + 1}`}>конфликт</span>}
        </div>
      </td>
      <td><span className={`badge ${ob.kind}`}>{ob.label}</span></td>
      <td className="muted" style={{ fontSize: 12 }}>{summary(rule)}</td>
      <td style={{ textAlign: 'right' }}>
        <div className="row-actions">
          <button className="btn btn-ghost sm" onClick={() => onEdit(rule.id)}>Редактировать</button>
          <button className="btn btn-ghost sm" onClick={() => { if (confirm('Удалить правило?')) onRemove(rule.id); }}>×</button>
        </div>
      </td>
    </tr>
  );
}

function TemplatesModal({ open, onClose, onAdd }) {
  if (!open) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal lg" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3>Шаблоны маршрутизации</h3>
          <button className="btn btn-ghost sm" onClick={onClose}>Закрыть</button>
        </div>
        <div className="modal-body">
          <div className="template-grid">
            {ruleTemplates.map((tpl) => (
              <div key={tpl.key} className="template-card">
                <h4>{tpl.label}</h4>
                <small>{tpl.description}</small>
                <button className="btn btn-secondary sm" onClick={() => { onAdd(tpl.build()); onClose(); }}>
                  + Добавить
                </button>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

export function RoutingPage({
  rules, saveStatus, busy,
  onAdd, onAddTemplate, onUpdate, onRemove, onSaveNow, onReorder,
  devicesConfig, onUpdateDeviceDefaults, onAddDevice, onUpdateDevice, onRemoveDevice,
}) {
  const [editingId, setEditingId] = useState(null);
  const [showTemplates, setShowTemplates] = useState(false);
  const [conflicts, setConflicts] = useState([]);
  const [availableRuleSets, setAvailableRuleSets] = useState([]);
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
    useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
  );

  useEffect(() => {
    api.ruleSets.get().then((data) => setAvailableRuleSets(data.ruleSets || [])).catch(() => {});
  }, []);

  useEffect(() => {
    let cancelled = false;
    const t = setTimeout(() => {
      api.rules.conflicts().then((data) => { if (!cancelled) setConflicts(data.conflicts || []); }).catch(() => {});
    }, 600);
    return () => { cancelled = true; clearTimeout(t); };
  }, [rules]);

  const conflictsByRuleId = useMemo(() => {
    const map = {};
    for (const c of conflicts) map[c.ruleId] = c;
    return map;
  }, [conflicts]);

  function handleDragEnd(event) {
    const { active, over } = event;
    if (!over || active.id === over.id) return;
    const oldIndex = rules.findIndex((r) => r.id === active.id);
    const newIndex = rules.findIndex((r) => r.id === over.id);
    if (oldIndex < 0 || newIndex < 0) return;
    onReorder(arrayMove(rules, oldIndex, newIndex));
  }

  const editing = rules.find((r) => r.id === editingId) || null;

  return (
    <div className="section-stack">
      <RouteChecker />

      <DevicesCard
        devicesConfig={devicesConfig}
        onDefaultsChange={onUpdateDeviceDefaults}
        onAdd={onAddDevice}
        onUpdate={onUpdateDevice}
        onRemove={onRemoveDevice}
      />

      <div className="card">
        <div className="card-header">
          <h2>Правила маршрутизации</h2>
          <div className="btn-group">
            <button className="btn btn-secondary sm" onClick={() => setShowTemplates(true)}>Шаблоны</button>
            <button className="btn btn-primary sm" onClick={() => { const newId = `rule-${Date.now()}`; onAdd(); setTimeout(() => setEditingId(newId), 50); }}>
              + Добавить
            </button>
          </div>
        </div>

        {conflicts.length > 0 && (
          <div className="conflict-banner" style={{ marginBottom: 12 }}>
            <span>⚠</span>
            <div>
              <strong>{conflicts.length} конфликт(ов) обнаружено</strong>
              <div style={{ marginTop: 4 }}>
                {conflicts.slice(0, 3).map((c, i) => (
                  <div key={i} style={{ fontSize: 12 }}>
                    #{c.ruleIndex + 1} «{c.ruleName}» перекрывается правилом #{c.conflictWithIndex + 1} «{c.conflictWithName}»
                  </div>
                ))}
              </div>
            </div>
          </div>
        )}

        <small className="muted" style={{ display: 'block', marginBottom: 8 }}>
          Применяются <strong>сверху вниз</strong>. Перетаскивай ⠿ чтобы менять порядок.
        </small>

        {rules.length === 0 ? (
          <div className="empty-state">
            <h3>Правил пока нет</h3>
            <p>Добавь шаблон (например «League of Legends → direct») или создай пустое правило.</p>
            <button className="btn btn-primary" onClick={() => setShowTemplates(true)} style={{ marginTop: 12 }}>
              Открыть шаблоны
            </button>
          </div>
        ) : (
          <div style={{ overflowX: 'auto' }}>
            <table className="table">
              <thead>
                <tr>
                  <th></th>
                  <th>#</th>
                  <th>Правило</th>
                  <th>Outbound</th>
                  <th>Условия</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
                  <SortableContext items={rules.map((r) => r.id)} strategy={verticalListSortingStrategy}>
                    {rules.map((rule, i) => (
                      <SortableRuleRow
                        key={rule.id}
                        rule={rule}
                        index={i}
                        total={rules.length}
                        onEdit={setEditingId}
                        onUpdate={onUpdate}
                        onRemove={onRemove}
                        conflict={conflictsByRuleId[rule.id]}
                      />
                    ))}
                  </SortableContext>
                </DndContext>
              </tbody>
            </table>
          </div>
        )}
      </div>

      <RuleEditorDrawer
        rule={editing}
        onUpdate={onUpdate}
        onClose={() => setEditingId(null)}
        onRemove={onRemove}
        availableRuleSets={availableRuleSets}
      />
      <TemplatesModal open={showTemplates} onClose={() => setShowTemplates(false)} onAdd={onAddTemplate} />
    </div>
  );
}
