const { useState, useEffect } = React;

// Top-level tabs that map 1:1 to a URL path. Order in the tab strip is
// driven by the JSX below; this set is just for "is this a recognised tab"
// validation when reading from the URL on load / popstate.
const APP_TABS = ['dashboard', 'panels', 'credentials', 'config', 'logs', 'usage', 'update', 'appstore', 'devmodules'];

function tabFromPath(pathname) {
  // Pathname like "/credentials" -> "credentials". Empty / unknown / "/"
  // falls back to the default dashboard tab so refreshing on "/" doesn't
  // pick a random tab.
  const first = (pathname || '/').split('/').filter(Boolean)[0];
  return APP_TABS.includes(first) ? first : 'dashboard';
}

function pushTabUrl(tab) {
  // pushState updates the address bar without reloading. Preserve the
  // existing query string (notably ?hash= used for nginx auth) and any
  // hash fragment so the auth round-trip survives navigation.
  const url = `/${tab}${window.location.search}${window.location.hash}`;
  if (window.location.pathname !== `/${tab}`) {
    window.history.pushState({}, '', url);
  }
}

// Main App Component
function App() {
  const [activeTab, setActiveTabState] = useState(() => tabFromPath(window.location.pathname));
  const [status, setStatus] = useState(null);
  const [setupStatus, setSetupStatus] = useState(null);
  const [logs, setLogs] = useState([]);
  const [loading, setLoading] = useState(true);
  const [containerRestarting, setContainerRestarting] = useState(false);

  // Wrapper so every tab change (button clicks, programmatic switches)
  // updates the URL alongside the React state.
  const setActiveTab = (tab) => {
    setActiveTabState(tab);
    pushTabUrl(tab);
  };

  // Browser back/forward: re-derive active tab from the URL the browser
  // just restored. Doesn't pushState (would create a loop).
  useEffect(() => {
    const onPopState = () => setActiveTabState(tabFromPath(window.location.pathname));
    window.addEventListener('popstate', onPopState);
    return () => window.removeEventListener('popstate', onPopState);
  }, []);

  // Load initial data and set up WebSocket subscriptions
  useEffect(() => {
    // Load initial data
    loadData();

    // Subscribe to WebSocket events for real-time updates
    const unsubscribeStatus = wsClient.on('bot:status', (data) => {
      console.log('[WebSocket] Bot status update:', data);
      setStatus(data);
    });

    const unsubscribeLog = wsClient.on('bot:log', (data) => {
      console.log('[WebSocket] New log:', data.line);
      setLogs((prevLogs) => {
        const newLogs = [...prevLogs, data.line];
        // Keep last 50 logs to match polling behavior
        return newLogs.slice(-50);
      });
    });

    const unsubscribeStartup = wsClient.on('bot:startup', (data) => {
      console.log('[WebSocket] Bot started:', data);
      setStatus(data);
      showToast('Bot started successfully!', 'success');
    });

    const unsubscribeShutdown = wsClient.on('bot:shutdown', (data) => {
      console.log('[WebSocket] Bot shutdown:', data);
      loadData(); // Reload to get updated status
    });

    const unsubscribeCrash = wsClient.on('bot:crash', (data) => {
      console.log('[WebSocket] Bot crashed:', data);
      showToast('Bot has crashed! Check logs for details.', 'error');
      loadData(); // Reload to get crash status
    });

    const unsubscribeConnection = wsClient.on('_connection', (data) => {
      console.log('[WebSocket] Connection status:', data.connected);
      if (data.connected) {
        // Clear stale messages and reload data when WebSocket reconnects
        loadData();
      }
    });

    // Cleanup subscriptions on unmount
    return () => {
      unsubscribeStatus();
      unsubscribeLog();
      unsubscribeStartup();
      unsubscribeShutdown();
      unsubscribeCrash();
      unsubscribeConnection();
    };
  }, []);

  async function loadData() {
    try {
      const [statusRes, setupRes, logsRes] = await Promise.all([
        api.get('/bot/status'),
        api.get('/setup/status'),
        api.get('/bot/logs?limit=50')
      ]);

      setStatus(statusRes.status);
      setSetupStatus(setupRes);
      setLogs(logsRes.logs.current);
      setLoading(false);
    } catch (err) {
      showToast(err.message, 'error');
      setLoading(false);
    }
  }

  async function startBot() {
    try {
      setLoading(true);
      const res = await api.post('/bot/start');
      if (res.success) {
        showToast('Bot started successfully!', 'success');
        await loadData();
      } else {
        showToast(res.error || 'Failed to start bot', 'error');
      }
    } catch (err) {
      showToast(err.message, 'error');
    } finally {
      setLoading(false);
    }
  }

  async function restartBot(skipConfirmation = false) {
    if (!skipConfirmation && !confirm('Restart the bot?')) return;
    try {
      setLoading(true);
      const res = await api.post('/bot/restart');
      if (!res.success) {
        showToast(res.error || 'Failed to restart bot', 'error');
      }
      // Don't call loadData() here; let WebSocket bot:startup event
      // drive the status update so BotControlPanel's restarting state works.
    } catch (err) {
      showToast(err.message, 'error');
    } finally {
      setLoading(false);
    }
  }

  async function startOrRestartBot() {
    // If bot is already running, restart it (with confirmation)
    if (status?.running) {
      await restartBot();
    } else {
      // If bot is not running, start it (no confirmation needed)
      await startBot();
    }
  }

  async function shutdownBot(emergency = false) {
    const msg = emergency
      ? 'This will restart the entire container (bot + Web-UI). You will briefly lose access. Are you sure?'
      : 'Are you sure you want to stop the bot? Web-UI will remain accessible.';
    if (!confirm(msg)) return;
    try {
      setLoading(true);
      if (emergency) setContainerRestarting(true);
      await api.post('/bot/shutdown', { emergency });
      if (emergency) {
        showToast('Container restarting... page will reload when ready.', 'info', 15000);
        const poll = setInterval(async () => {
          try {
            await api.get('/bot/status');
            clearInterval(poll);
            window.location.reload();
          } catch (_) { /* still down, keep polling */ }
        }, 3000);
      } else {
        showToast('Bot stopped successfully', 'success');
        await loadData();
      }
    } catch (err) {
      if (emergency) {
        setContainerRestarting(true);
        showToast('Container restarting... page will reload when ready.', 'info', 15000);
        const poll = setInterval(async () => {
          try {
            await api.get('/bot/status');
            clearInterval(poll);
            window.location.reload();
          } catch (_) { /* still down */ }
        }, 3000);
      } else {
        showToast(err.message, 'error');
      }
    } finally {
      setLoading(false);
    }
  }

  if (loading && !status) {
    return <div className="loading">Loading...</div>;
  }

  return (
    <div>
      <div className="header">
        <span
          style={{ minWidth: '140px', paddingLeft: '20px', color: '#666', fontSize: '0.75rem', fontFamily: 'monospace', userSelect: 'text' }}
          title={window.BOT_BUILD ? `branch: ${window.BOT_BUILD.branch}\nbuild: ${window.BOT_BUILD.buildDate}\ncommit: ${window.BOT_BUILD.commit}` : 'running in dev mode'}
        >
          {window.BOT_BUILD ? `v${window.BOT_BUILD.version} · ${window.BOT_BUILD.commitShort}` : 'Development'}
        </span>
        <h1 style={{ margin: '0', padding: '20px 0', color: '#a0a0a0', flex: 1, textAlign: 'center' }}>Discord Bot System Settings</h1>
        <span style={{ minWidth: '140px', paddingRight: '20px', textAlign: 'right' }}>
          {status && (
            <span className={`status-badge ${status.running ? 'running' : status.crashed ? 'crashed' : 'stopped'}`}>
              {status.running ? '● Online' : status.crashed ? '⚠ Crashed' : '○ Offline'}
            </span>
          )}
        </span>
      </div>

      <div className="tabs">
        <button
          className={`tab ${activeTab === 'dashboard' ? 'active' : ''}`}
          onClick={() => setActiveTab('dashboard')}
        >
          Dashboard
        </button>
        <button
          className={`tab ${activeTab === 'panels' ? 'active' : ''}`}
          onClick={() => setActiveTab('panels')}
        >
          Panels
        </button>
        <button
          className={`tab ${activeTab === 'credentials' ? 'active' : ''}`}
          onClick={() => setActiveTab('credentials')}
        >
          Credentials
        </button>
        <button
          className={`tab ${activeTab === 'config' ? 'active' : ''}`}
          onClick={() => setActiveTab('config')}
        >
          Config
        </button>
        <button
          className={`tab ${activeTab === 'logs' ? 'active' : ''}`}
          onClick={() => setActiveTab('logs')}
        >
          Logs
        </button>
        <button
          className={`tab ${activeTab === 'usage' ? 'active' : ''}`}
          onClick={() => setActiveTab('usage')}
        >
          Usage
        </button>
        <button
          className={`tab ${activeTab === 'update' ? 'active' : ''}`}
          onClick={() => setActiveTab('update')}
        >
          Update
        </button>
        <button
          className={`tab ${activeTab === 'appstore' ? 'active' : ''}`}
          onClick={() => setActiveTab('appstore')}
        >
          App Store
        </button>
        <button
          className={`tab ${activeTab === 'devmodules' ? 'active' : ''}`}
          onClick={() => setActiveTab('devmodules')}
        >
          Dev Modules
        </button>
      </div>

      <div className="tab-content">
        {activeTab === 'dashboard' && (
          <BotControlPanel
            status={status}
            onStart={startBot}
            onRestart={restartBot}
            onShutdown={shutdownBot}
            loading={loading}
            configured={setupStatus?.configured}
            containerRestarting={containerRestarting}
          />
        )}

        {activeTab === 'panels' && <PanelsPanel />}

        {activeTab === 'credentials' && (
          <CredentialsPanel
            setupStatus={setupStatus}
            isBotRunning={!!status?.running}
            onUpdate={loadData}
            onUpdateAndRestart={async () => {
              await loadData();
              // Full server restart to pick up OAuth/session changes
              try {
                await api.post('/bot/restart-server');
                // Server will restart, page will reconnect
              } catch (err) {
                // Fallback to bot restart if server restart fails
                console.warn('Server restart failed, falling back to bot restart:', err);
                await startOrRestartBot();
              }
            }}
          />
        )}

        {activeTab === 'config' && <ConfigPanel />}

        {activeTab === 'logs' && <LogsPanel api={api} wsClient={wsClient} />}

        {activeTab === 'usage' && <UsagePanel api={api} wsClient={wsClient} />}

        {activeTab === 'update' && <UpdatePanel api={api} wsClient={wsClient} />}

        {activeTab === 'appstore' && <AppStorePanel />}

        {activeTab === 'devmodules' && <DevModulesPanel />}
      </div>
    </div>
  );
}

// Render
ReactDOM.render(<App />, document.getElementById('root'));
