<script lang="ts">
  import { onMount } from 'svelte';
  import LoginPage from './components/auth/LoginPage.svelte';
  import AdminShell from './components/shell/AdminShell.svelte';
  import type { 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 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 loadStatus();
    } 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 loadStatus();
    } 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 = '';
  }

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

    try {
      const response = await fetch('/api/status');
      if (!response.ok) {
        throw new Error(`Status request failed with ${response.status}`);
      }
      data = (await response.json()) as StatusResponse;
    } catch (err) {
      error = err instanceof Error ? err.message : 'Failed to load status';
    } finally {
      loading = 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 loadStatus();
    }
  });
</script>

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

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