import { useCallback, useEffect, useMemo, useState } from 'react';
import api from './lib/api.js';
import { useNotify } from './components/NotifyProvider.jsx';
import PageHeader from './components/PageHeader.jsx';
import TableSkeleton from './components/TableSkeleton.jsx';
import { countryToFlag } from './utils/serverUtils.js';
import {
  IconTopologyRing,
  IconNetwork,
  IconSearch,
  IconRefresh,
} from '@tabler/icons-react';

export default function InterfaceSpeedTest() {
  const notify = useNotify();

  const [servers, setServers] = useState([]);
  const [networkConfig, setNetworkConfig] = useState(null);
  const [loading, setLoading] = useState(true);
  const [serverSearch, setServerSearch] = useState('');

  const [serverId, setServerId] = useState('');
  const [selectedInterfaceName, setSelectedInterfaceName] = useState('');
  const [running, setRunning] = useState(false);
  const [speedResult, setSpeedResult] = useState(null);
  const [speedSettings, setSpeedSettings] = useState({
    protocol: 'tcp',
    durationSeconds: 10,
    cacheMinutes: 0,
  });

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;

    const load = async () => {
      setLoading(true);
      try {
        const [serversRes, netRes, uiRes] = await Promise.all([
          api.get('/servers', { signal }),
          api.get('/network-config', { signal }).catch(() => ({ data: null })),
          api.get('/ui-settings', { signal }).catch(() => ({ data: {} })),
        ]);

        setServers(Array.isArray(serversRes?.data) ? serversRes.data : []);
        setNetworkConfig(
          netRes?.data && typeof netRes.data === 'object'
            ? netRes.data
            : { gateways: [], tunnelInterfaces: [] }
        );

        const ui = uiRes?.data || {};
        const proto =
          String(ui.interfaceSpeedTestProtocol || 'tcp').toLowerCase() ===
          'udp'
            ? 'udp'
            : 'tcp';
        const duration = Math.max(
          1,
          Math.min(
            600,
            parseInt(ui.interfaceSpeedTestDurationSeconds, 10) || 5
          )
        );
        const cacheMinutes = Math.max(
          0,
          parseInt(ui.interfaceSpeedTestCacheMinutes, 10) || 0
        );
        setSpeedSettings({
          protocol: proto,
          durationSeconds: duration,
          cacheMinutes,
        });
      } catch (e) {
        if (e?.name === 'CanceledError' || e?.name === 'AbortError' || e?.code === 'ERR_CANCELED') return;
        console.error('[InterfaceSpeedTest] load failed', e);
        notify.error('Не удалось загрузить данные для замера скорости');
      } finally {
        setLoading(false);
      }
    };
    load();
    return () => controller.abort();
  }, [notify]);

  const _gateways = useMemo(
    () =>
      networkConfig?.gateways && Array.isArray(networkConfig.gateways)
        ? networkConfig.gateways
        : [],
    [networkConfig]
  );

  const tunnelInterfaces = useMemo(
    () =>
      networkConfig?.tunnelInterfaces &&
      Array.isArray(networkConfig.tunnelInterfaces)
        ? networkConfig.tunnelInterfaces
        : [],
    [networkConfig]
  );

  const jumphostServers = useMemo(
    () =>
      (servers || []).filter((s) =>
        ['jumphost', 'home'].includes(
          String(s.type || '').toLowerCase()
        )
      ),
    [servers]
  );

  const makeServerId = (s) => (s.id || s.dns || s.ip || '').toString();

  const jumphostInputServers = useMemo(
    () => jumphostServers.map((s) => ({ ...s, id: makeServerId(s) })),
    [jumphostServers]
  );

  const visibleJumphostServers = useMemo(() => {
    if (!serverSearch.trim()) return jumphostInputServers;
    const q = serverSearch.trim().toLowerCase();
    return jumphostInputServers.filter((s) => {
      const fields = [
        s.id,
        s.ip,
        s.dns,
        s.extIp,
        s.internalIp,
        s.country,
        s.provider,
      ]
        .filter(Boolean)
        .join(' ')
        .toLowerCase();
      return fields.includes(q);
    });
  }, [jumphostInputServers, serverSearch]);

  const currentServer = useMemo(
    () => jumphostServers.find((s) => makeServerId(s) === serverId) || null,
    [jumphostServers, serverId]
  );

  const interfacesForServer = useMemo(() => {
    if (!serverId || !tunnelInterfaces.length) return [];
    const ids = new Set(
      [serverId, currentServer?.id, currentServer?.ip, currentServer?.dns]
        .filter(Boolean)
        .map(String)
    );
    return tunnelInterfaces.filter(
      (i) =>
        i &&
        i.name &&
        (ids.has(String(i.serverId)) || ids.has(String(i.serverId2)))
    );
  }, [tunnelInterfaces, serverId, currentServer]);

  const currentServerLabel =
    currentServer?.dns ||
    currentServer?.ip ||
    makeServerId(currentServer || {}) ||
    'Не выбран';

  const isInitialLoading = loading && servers.length === 0;

  const formatMbps = (bps) => {
    if (bps == null || Number.isNaN(bps)) return '—';
    const mbps = bps / 1_000_000;
    if (!Number.isFinite(mbps)) return '—';
    return `${mbps.toFixed(2)} Мбит/с`;
  };

  /** Запросить только кеш (без замера). При выборе сервера/интерфейса показываем кеш, если есть. */
  const fetchCachedResult = useCallback(async () => {
    if (!serverId || !selectedInterfaceName) {
      setSpeedResult(null);
      return;
    }
    try {
      const res = await api.post('/mikrotik/speed-test', {
        serverId,
        interfaceName: selectedInterfaceName,
        cacheOnly: true,
      });
      const data = res?.data || {};
      if (data.ok !== false && !data.notInCache && (data.tcpDownloadBps != null || data.tcpUploadBps != null)) {
        setSpeedResult(data);
      } else {
        setSpeedResult(null);
      }
    } catch {
      setSpeedResult(null);
    }
  }, [serverId, selectedInterfaceName]);

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

  const handleRunTest = async () => {
    if (!serverId) {
      notify.error('Выберите сервер (jumphost/home) для замера скорости');
      return;
    }
    if (!selectedInterfaceName) {
      notify.error('Выберите туннельный интерфейс для замера скорости');
      return;
    }

    setRunning(true);
    setSpeedResult(null);

    try {
      const body = {
        serverId,
        interfaceName: selectedInterfaceName,
        durationSeconds: speedSettings.durationSeconds,
        forceRefresh: true,
      };
      const res = await api.post('/mikrotik/speed-test', body, {
        timeout: 120000,
      });
      const data = res?.data || {};
      if (data.ok === false) {
        notify.error(
          data.error || 'Замер скорости по интерфейсу завершился с ошибкой'
        );
        return;
      }
      setSpeedResult(data);
    } catch (e) {
      console.error('[InterfaceSpeedTest] test failed', e);
      notify.error(
        e?.response?.data?.message || e?.message || 'Ошибка замера скорости'
      );
    } finally {
      setRunning(false);
    }
  };

  const handleReset = () => {
    setServerId('');
    setSelectedInterfaceName('');
    setSpeedResult(null);
  };

  return (
    <div className="page">
      <PageHeader
        title="Скорость интерфейсов MikroTik"
        icon={<IconTopologyRing size={24} />}
        meta={`Текущий сервер: ${currentServerLabel}`}
      />

      <div className="row g-2">
        <div className="col-md-5">
          <div className="card mb-2">
            <div className="card-header py-2 d-flex align-items-center justify-content-between">
              <div>
                <h3 className="card-title mb-0">Серверы (jumphost / home)</h3>
                <p className="text-muted small mb-0 mt-0">
                  Выберите роутер с настроенным MikroTik API
                </p>
              </div>
              <div className="input-icon input-icon-sm" style={{ minWidth: 200 }}>
                <input
                  type="text"
                  className="form-control form-control-sm"
                  placeholder="Поиск серверов..."
                  value={serverSearch}
                  onChange={(e) => setServerSearch(e.target.value)}
                />
                <span className="input-icon-addon">
                  <IconSearch size={14} className="text-muted" />
                </span>
              </div>
            </div>
            <div className="card-body py-2">
              {isInitialLoading ? (
                <TableSkeleton rows={2} columns={2} />
              ) : jumphostServers.length === 0 ? (
                <div className="text-muted small">
                  Нет серверов типа <code>jumphost</code> или <code>home</code>.
                  Добавьте их в разделе «Серверы», чтобы использовать замер
                  скорости.
                </div>
              ) : visibleJumphostServers.length === 0 ? (
                <div className="text-muted small">
                  По вашему запросу серверы не найдены. Попробуйте изменить фильтр
                  поиска.
                </div>
              ) : (
                <div className="row row-cards g-1">
                  {visibleJumphostServers.map((s) => {
                    const id = s.id;
                    const isActive = id === serverId;
                    const flag = s.country ? countryToFlag(s.country) : '';
                    const line = [s.dns, s.ip].filter(Boolean).join(' · ');
                    return (
                      <div
                        className="col-12 col-sm-6 col-md-6"
                        key={id}
                      >
                        <div
                          className={`card card-sm h-100 cursor-pointer ${
                            isActive ? 'border-primary card-hover' : 'card-hover'
                          }`}
                          onClick={() => setServerId(id)}
                        >
                          <div className="card-body py-2 px-2 d-flex align-items-center gap-2">
                            <span
                              className="avatar avatar-sm bg-primary-lt"
                              title={s.country || ''}
                            >
                              {flag || s.ip?.slice(0, 2) || '?'}
                            </span>
                            <div className="flex-grow-1 min-w-0">
                              <div
                                className="fw-semibold text-truncate small"
                                title={s.dns || s.ip || id}
                              >
                                {s.dns || s.ip || id}
                              </div>
                              <div
                                className="text-muted small text-truncate"
                                title={line}
                              >
                                {line ||
                                  [s.country, s.provider]
                                    .filter(Boolean)
                                    .join(' · ') ||
                                  '—'}
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}
              <div className="d-flex flex-wrap align-items-center gap-2 mt-2">
                <span className="badge bg-primary-lt text-primary">
                  Сервер: {currentServerLabel}
                </span>
              </div>
            </div>
          </div>

          <div className="card">
            <div className="card-header py-2">
              <h3 className="card-title mb-0">Интерфейсы туннелей</h3>
            </div>
            <div className="card-body py-2">
              {loading && !networkConfig ? (
                <div className="text-muted small">Загрузка сетевых настроек…</div>
              ) : !serverId ? (
                <div className="text-muted small">
                  Выберите сервер слева, затем интерфейс для замера скорости.
                </div>
              ) : interfacesForServer.length === 0 ? (
                <div className="text-muted small">
                  Для выбранного сервера нет туннельных интерфейсов в
                  <code> /network-config</code>. Добавьте интерфейсы в разделе
                  «Сетевые настройки».
                </div>
              ) : (
                <>
                  <div className="mb-2">
                    <select
                      className="form-select form-select-sm"
                      value={selectedInterfaceName}
                      onChange={(e) => setSelectedInterfaceName(e.target.value)}
                    >
                      <option value="">Не выбран</option>
                      {interfacesForServer.map((iface) => (
                        <option key={iface.name} value={iface.name}>
                          {iface.name} ({iface.localIp} ⇄ {iface.remoteIp})
                        </option>
                      ))}
                    </select>
                  </div>
                  <div className="text-muted small">
                    Для сопоставления используется имя интерфейса из
                    <code> /network-config.tunnelInterfaces</code>. В RouterOS
                    имя должно совпадать.
                  </div>
                </>
              )}
            </div>
          </div>
        </div>

        <div className="col-md-7">
          <div className="card mb-2">
            <div className="card-header py-2 d-flex align-items-center justify-content-between">
              <h3 className="card-title mb-0">Параметры замера</h3>
              <div className="btn-list">
                <button
                  type="button"
                  className="btn btn-outline-secondary btn-sm"
                  onClick={handleReset}
                  disabled={running}
                >
                  <IconRefresh size={16} className="me-1" />
                  Сбросить
                </button>
                <button
                  type="button"
                  className="btn btn-primary btn-sm"
                  onClick={handleRunTest}
                  disabled={running || !serverId || !selectedInterfaceName}
                >
                  {running ? 'Замер…' : 'Запустить замер'}
                </button>
              </div>
            </div>
            <div className="card-body py-2">
              <div className="row g-2">
                <div className="col-md-4">
                  <label className="form-label small mb-0">Протокол</label>
                  <div className="d-flex align-items-center gap-1">
                    <IconNetwork size={16} className="text-muted" />
                    <span className="small text-uppercase">
                      {speedSettings.protocol === 'udp' ? 'UDP' : 'TCP'}
                    </span>
                  </div>
                  <div className="text-muted small">
                    Значение берётся из настроек интерфейса.
                  </div>
                </div>
                <div className="col-md-4">
                  <label className="form-label small mb-0">
                    Время замера (сек)
                  </label>
                  <div className="fw-semibold">
                    {speedSettings.durationSeconds}
                  </div>
                </div>
                <div className="col-md-4">
                  <label className="form-label small mb-0">
                    Кеш результата (мин)
                  </label>
                  <div className="fw-semibold">
                    {speedSettings.cacheMinutes}
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div className="card">
            <div className="card-header py-2">
              <h3 className="card-title mb-0">
                Скорость по интерфейсу MikroTik
              </h3>
            </div>
            <div className="card-body">
              {!speedResult ? (
                <div className="text-muted small">
                  Выберите сервер и интерфейс, затем запустите замер. Средние
                  скорости приёма и передачи появятся здесь.
                </div>
              ) : (
                <div className="row g-3">
                  <div className="col-12 col-md-6">
                    <div className="card bg-blue-lt">
                      <div className="card-body py-2">
                        <div className="text-muted small mb-1">Интерфейс</div>
                        <div className="fw-semibold">
                          {speedResult.interfaceName || selectedInterfaceName}
                        </div>
                        <div className="text-muted small mt-1">
                          Замер за {speedResult.durationSeconds} сек
                          {speedResult.cached ? ' (из кеша)' : ''}
                        </div>
                      </div>
                    </div>
                  </div>
                  <div className="col-12 col-md-6">
                    <div className="card bg-azure-lt">
                      <div className="card-body py-2">
                        <div className="text-muted small mb-1">
                          TCP скорость
                        </div>
                        <div className="fw-bold">
                          Download: {formatMbps(speedResult.tcpDownloadBps)}
                        </div>
                        <div className="fw-bold mt-1">
                          Upload: {formatMbps(speedResult.tcpUploadBps)}
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

