import React, { useEffect, useReducer, useRef, useState } from 'react';
import { createRoot } from 'react-dom/client';
import './styles.css';
import { api } from './api.js';
import { ClientOverviewPage } from './components/ClientOverviewPage.jsx';
import { BootStatePage, StaleBanner } from './components/SyncStatus.jsx';
import {
  compatibleSnapshot,
  harborReducer,
  initialHarborState,
} from './state/harborReducer.js';

function App() {
  const previewReady = new URLSearchParams(window.location.search).has('preview-ready');
  const [{ snapshot: state, pendingServerId: pendingTag, transport }, dispatch] = useReducer(
    harborReducer,
    initialHarborState,
  );
  const [subscriptionUrl, setSubscriptionUrl] = useState('');
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState('');
  const pollGeneration = useRef(0);

  function setPendingTag(serverId) {
    dispatch({ type: 'select-server', serverId });
  }

  async function loadState({ retry = false } = {}) {
    if (retry) dispatch({ type: 'retry-sync' });
    const generation = pollGeneration.current;
    try {
      const snapshot = await api.state();
      if (!compatibleSnapshot(snapshot)) {
        const incompatible = new Error('Ожидался Harbor state apiVersion 1');
        incompatible.code = 'INCOMPATIBLE_API';
        throw incompatible;
      }
      if (generation === pollGeneration.current) {
        dispatch({ type: 'sync-succeeded', snapshot, receivedAt: new Date().toISOString() });
      }
    } catch (requestError) {
      if (generation === pollGeneration.current) {
        dispatch({ type: 'sync-failed', error: requestError });
      }
    }
  }

  useEffect(() => {
    loadState();
    const timer = setInterval(loadState, 5000);
    return () => clearInterval(timer);
  }, []);

  useEffect(() => {
    if (!state?.mode) return;
    const isGateway = state.mode === 'gateway';
    document.title = isGateway ? 'Harbor Gateway' : 'Harbor Connect';
    document.getElementById('harbor-favicon').href = isGateway
      ? '/harbor-gateway.svg?v=2'
      : '/harbor-connect.svg?v=2';
  }, [state?.mode]);

  async function run(action) {
    setBusy(true);
    setError('');
    try {
      return await applyMutation(action);
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setBusy(false);
    }
  }

  async function applyMutation(action) {
    pollGeneration.current += 1;
    const result = await action();
    if (!result?.state) throw new Error('Harbor API не вернул state snapshot');
    if (!compatibleSnapshot(result.state)) throw new Error('Harbor API не вернул state snapshot v1');
    dispatch({
      type: 'sync-succeeded',
      snapshot: result.state,
      receivedAt: new Date().toISOString(),
    });
    return result;
  }

  async function fetchSubscription() {
    return run(async () => {
      const data = await api.subscription.fetch(subscriptionUrl);
      dispatch({ type: 'clear-pending-server' });
      return data;
    });
  }

  async function refreshSubscription() {
    try {
      return await applyMutation(api.subscription.refresh);
    } catch (refreshError) {
      setError(refreshError.message);
      throw refreshError;
    }
  }

  async function forgetSubscription() {
    return run(async () => {
      const data = await api.subscription.forget();
      setSubscriptionUrl('');
      dispatch({ type: 'clear-pending-server' });
      return data;
    });
  }

  if (!state) return <BootStatePage transport={transport} onRetry={() => loadState({ retry: true })} />;

  return (
    <div className={`app client-app${state.mode === 'gateway' ? ' is-gateway-app' : ''}`}>
      <StaleBanner transport={transport} onRetry={() => loadState({ retry: true })} />
      <div className="app-body client-mode">
        <main className="app-main">
          <ClientOverviewPage
            state={previewReady ? { ...state, mode: 'client', hasSubscription: true, subscriptionHost: 'harbor.example', selectedTag: 'Amsterdam', proxyPort: 8082 } : state}
            busy={busy}
            error={error}
            subscriptionUrl={subscriptionUrl}
            setSubscriptionUrl={setSubscriptionUrl}
            servers={previewReady ? [{ tag: 'Amsterdam', server: '127.0.0.1', server_port: 443 }] : state.servers || []}
            pendingTag={previewReady ? 'Amsterdam' : pendingTag}
            setPendingTag={setPendingTag}
            onFetchSubscription={fetchSubscription}
            onRefreshSubscription={refreshSubscription}
            onForgetSubscription={forgetSubscription}
            onApply={(tag) => run(() => api.apply(tag))}
            onRestart={() => run(api.singbox.restart)}
            onStop={() => run(api.singbox.stop)}
            onSetGatewayAuto={(enabled) => run(() => api.gatewayAuto.setEnabled(enabled))}
          />
        </main>
      </div>
    </div>
  );
}

createRoot(document.getElementById('root')).render(<App />);
