<script lang="ts">
  export let apiBase: string;
  export let onLogin: (detail: { apiBase: string; account: string }) => void = () => {};

  let server = apiBase;
  let account = '';
  let password = '';
  let error = '';
  let connectionStatus = 'Not connected. Enter a server address to continue.';

  function normalizeServer(value: string): { apiBase?: string; error?: string } {
    if (!value.trim()) {
      return { error: 'Enter a server address.' };
    }

    if (hasWhitespace(value) || value.includes('\\') || hasMalformedHttpProtocol(value) || hasUnsupportedProtocol(value)) {
      return { error: 'Enter a valid HTTP or HTTPS server address.' };
    }

    const candidate = /^https?:\/\//i.test(value) ? value : `http://${value}`;
    if (!/^https?:\/\/(?![\\/])/i.test(candidate) || hasCredentials(candidate)) {
      return { error: 'Enter a valid HTTP or HTTPS server address.' };
    }

    try {
      const parsed = new URL(candidate);
      if (
        !parsed.hostname ||
        parsed.username ||
        parsed.password ||
        !['http:', 'https:'].includes(parsed.protocol) ||
        !isValidHostname(parsed.hostname)
      ) {
        return { error: 'Enter a valid HTTP or HTTPS server address.' };
      }
      return { apiBase: candidate };
    } catch {
      return { error: 'Enter a valid HTTP or HTTPS server address.' };
    }
  }

  function hasWhitespace(value: string): boolean {
    if (/\s/u.test(value)) return true;

    try {
      return /\s/u.test(decodeURIComponent(value));
    } catch {
      return true;
    }
  }

  function hasUnsupportedProtocol(value: string): boolean {
    const explicitProtocol = value.match(/^([a-z][a-z\d+.-]*):\/\//i);
    if (explicitProtocol) {
      return !['http', 'https'].includes(explicitProtocol[1].toLowerCase());
    }

    return /^[a-z][a-z\d+.-]*:(?!\d)/i.test(value);
  }

  function hasMalformedHttpProtocol(value: string): boolean {
    return /^https?:\/(?!\/)/i.test(value) || /^https?\/{2}(?!\/)/i.test(value);
  }

  function hasCredentials(value: string): boolean {
    const authority = value.replace(/^https?:\/\//i, '').split(/[/?#]/, 1)[0];
    return authority.includes('@');
  }

  function isValidHostname(hostname: string): boolean {
    if (hostname === 'localhost') return true;
    if (/^\[[\da-f:.]+\]$/i.test(hostname)) return true;
    if (/^\d+(?:\.\d+){3}$/.test(hostname)) {
      return hostname.split('.').every((segment) => Number(segment) <= 255);
    }

    return hostname.split('.').every((label) => /^[a-z\d](?:[a-z\d-]{0,61}[a-z\d])?$/i.test(label));
  }

  function submitLogin() {
    error = '';
    const normalized = normalizeServer(server);
    if (normalized.error) {
      error = normalized.error;
      connectionStatus = 'Check the server address before signing in.';
      return;
    }

    if (!account.trim() || !password.trim()) {
      error = 'Enter an account and password.';
      return;
    }

    server = normalized.apiBase ?? server;
    connectionStatus = 'Connection settings are ready.';
    onLogin({ apiBase: server, account: account.trim() });
  }
</script>

<main class="login-page">
  <section class="login-panel" aria-labelledby="login-title">
    <div class="login-brand" aria-hidden="true">SA</div>
    <div class="login-heading">
      <p>Private workbench</p>
      <h1 id="login-title">SenlinAI Workbench</h1>
    </div>

    <form class="server-login" aria-label="Server login" on:submit|preventDefault={submitLogin}>
      <label for="server-address">Server IP or domain</label>
      <input id="server-address" name="server" bind:value={server} placeholder="http://localhost:8080" />

      <label for="login-account">Email or username</label>
      <input id="login-account" name="account" bind:value={account} autocomplete="username" />

      <label for="login-password">Password</label>
      <input
        id="login-password"
        name="password"
        type="password"
        bind:value={password}
        autocomplete="current-password"
      />

      {#if error}
        <p class="form-error" aria-live="polite">{error}</p>
      {/if}

      <p class="connection-status" role="status">{connectionStatus}</p>

      <button type="submit">Log in</button>
      <p class="login-note">The server address is remembered on this device.</p>
    </form>
  </section>
</main>
