<script lang="ts">
  import { onMount } from 'svelte';
  import LoginPage from './components/auth/LoginPage.svelte';
  import AdminShell from './components/shell/AdminShell.svelte';
  import type { PublicStatusResponse, ShellPage, StatusResponse } from './types';
  import { fromStore } from 'svelte/store';
  import {
    ensureApiURL,
    exchangeOAuthCode,
    GlobalStateStore,
    isLoggedInStore,
    loginWithCredentials,
    setCurrentPath
  } from './shellState';

  let authMessage = $state('');
  let authError = $state('');
  let authBusy = $state(false);
  let callbackBusy = $state(false);
  let data = $state<StatusResponse | null>(null);
  let loading = $state(false);
  let error = $state('');
  let publicStatus = $state<PublicStatusResponse | null>(null);
  let publicStatusLoading = $state(false);
  let publicStatusError = $state('');
  let currentPage = $state<ShellPage>('dashboard');

  ensureApiURL(import.meta.env.VITE_API_URL);

  GlobalStateStore.setState({
    onFetchSession: async (state) => {
      const token = state.session?.authToken;
      if (!token) return {};
      const res = await fetch('/api/rs/public/projects', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${token}`
        },
        body: JSON.stringify({
          operation: 'read',
          options: { limit: 1 }
        })
      });
      if (!res.ok) return { session: { loggedIn: false } };
      return { session: { loggedIn: true, authToken: token } };
    }
  });

  const isLoggedIn = fromStore(isLoggedInStore);
  const currentPath = $derived(typeof window !== 'undefined' ? window.location.pathname : '/');
  const isOAuthCallback = $derived(currentPath === '/oauth/callback');

  async function handleCredentialLogin(username: string, password: string): Promise<void> {
    authBusy = true;
    authError = '';
    authMessage = '';

    try {
      const token = await loginWithCredentials(username, password);
      await GlobalStateStore.getState().login(token, { username });
      authMessage = 'Login successful.';
      await loadDashboardStatus();
    } catch (err) {
      authError = err instanceof Error ? err.message : 'Login failed.';
    } finally {
      authBusy = false;
    }
  }

  async function finishOAuthLogin(): Promise<void> {
    callbackBusy = true;
    authError = '';
    authMessage = '';

    try {
      const params = new URLSearchParams(window.location.search);
      const code = params.get('code');
      const returnedState = params.get('state');
      const oauthError = params.get('error');

      if (oauthError) {
        throw new Error(`OAuth login failed: ${oauthError}`);
      }
      if (!code || !returnedState) {
        throw new Error('OAuth callback is missing code or state.');
      }

      const token = await exchangeOAuthCode(code, returnedState);
      await GlobalStateStore.getState().login(token, { username: 'OAuth operator' });

      authMessage = 'OAuth login complete. Welcome back.';
      window.history.replaceState({}, '', '/');
      await loadDashboardStatus();
    } catch (err) {
      authError = err instanceof Error ? err.message : 'OAuth callback failed.';
    } finally {
      callbackBusy = false;
    }
  }

  async function logout(): Promise<void> {
    await GlobalStateStore.getState().logout();
    authMessage = 'Logged out.';
    authError = '';
    await loadPublicStatus();
  }

  async function loadDashboardStatus(): Promise<void> {
    loading = true;
    error = '';

    try {
      const token = GlobalStateStore.getState().session?.authToken;
      if (!token) {
        throw new Error('Missing auth token for dashboard status.');
      }
      const response = await fetch('/api/status', {
        headers: {
          Authorization: `Bearer ${token}`
        }
      });
      if (!response.ok) {
        throw new Error(`Status request failed with ${response.status}`);
      }
      const raw = (await response.json()) as Partial<StatusResponse> | null;
      data = {
        title: raw?.title ?? 'AMCS',
        description: raw?.description ?? '',
        version: raw?.version ?? 'unknown',
        build_date: raw?.build_date ?? 'unknown',
        commit: raw?.commit ?? 'unknown',
        connected_count: raw?.connected_count ?? 0,
        total_known: raw?.total_known ?? 0,
        connected_window: raw?.connected_window ?? 'last 10 minutes',
        oauth_enabled: !!raw?.oauth_enabled,
        entries: Array.isArray(raw?.entries) ? raw.entries : [],
        metrics: {
          total_requests: raw?.metrics?.total_requests ?? 0,
          unique_principals: raw?.metrics?.unique_principals ?? 0,
          unique_ips: raw?.metrics?.unique_ips ?? 0,
          unique_agents: raw?.metrics?.unique_agents ?? 0,
          unique_tools: raw?.metrics?.unique_tools ?? 0,
          top_ips: Array.isArray(raw?.metrics?.top_ips) ? raw.metrics.top_ips : [],
          top_agents: Array.isArray(raw?.metrics?.top_agents) ? raw.metrics.top_agents : [],
          top_tools: Array.isArray(raw?.metrics?.top_tools) ? raw.metrics.top_tools : []
        }
      };
    } catch (err) {
      error = err instanceof Error ? err.message : 'Failed to load status';
    } finally {
      loading = false;
    }
  }

  async function loadPublicStatus(): Promise<void> {
    publicStatusLoading = true;
    publicStatusError = '';

    try {
      const response = await fetch('/status');
      if (!response.ok) {
        throw new Error(`Public status request failed with ${response.status}`);
      }
      const raw = (await response.json()) as Partial<PublicStatusResponse> | null;
      publicStatus = {
        connected_count: raw?.connected_count ?? 0,
        connected_window: raw?.connected_window ?? 'last 10 minutes',
        entries: Array.isArray(raw?.entries) ? raw.entries : []
      };
    } catch (err) {
      publicStatusError = err instanceof Error ? err.message : 'Failed to load public status';
    } finally {
      publicStatusLoading = false;
    }
  }

  onMount(async () => {
    if (typeof window !== 'undefined') {
      setCurrentPath(window.location.pathname);
    }

    if (isOAuthCallback) {
      await finishOAuthLogin();
      return;
    }

    await GlobalStateStore.getState().fetchData();

    if (GlobalStateStore.getState().isLoggedIn()) {
      await loadDashboardStatus();
      return;
    }
    await loadPublicStatus();
  });
</script>

<svelte:head>
  <title>AMCS Admin</title>
</svelte:head>

<div data-theme="amcs" class="min-h-screen bg-slate-950 text-slate-100">
  {#if !isLoggedIn.current}
    <LoginPage
      {isOAuthCallback}
      {callbackBusy}
      {authBusy}
      {authError}
      {authMessage}
      statusData={publicStatus}
      statusLoading={publicStatusLoading}
      statusError={publicStatusError}
      onlogin={handleCredentialLogin}
    />
  {:else}
    <AdminShell
      {currentPage}
      {data}
      {loading}
      {error}
      onlogout={logout}
      onnavigate={(page) => { currentPage = page; }}
      onrefresh={loadDashboardStatus}
    />
  {/if}
</div>
