import { type BrowserContext, type Page } from '@playwright/test';

const SERVER_ENDPOINTS_STORAGE_KEY = 'metoyou_server_endpoints';
const REMOVED_DEFAULT_KEYS_STORAGE_KEY = 'metoyou_removed_default_server_keys';

export interface SeededEndpointInput {
  id: string;
  name: string;
  url: string;
  isActive?: boolean;
  isDefault?: boolean;
  status?: string;
}

interface SeededEndpointStorageState {
  key: string;
  removedKey: string;
  endpoints: {
    id: string;
    name: string;
    url: string;
    isActive: boolean;
    isDefault: boolean;
    status: string;
  }[];
}

function buildSeededEndpointStorageState(
  endpointsOrPort: readonly SeededEndpointInput[] | number = Number(process.env.TEST_SERVER_PORT) || 3099
): SeededEndpointStorageState {
  const endpoints = Array.isArray(endpointsOrPort)
    ? endpointsOrPort.map((endpoint) => ({
      id: endpoint.id,
      name: endpoint.name,
      url: endpoint.url,
      isActive: endpoint.isActive ?? true,
      isDefault: endpoint.isDefault ?? false,
      status: endpoint.status ?? 'unknown'
    }))
    : [
      {
        id: 'e2e-test-server',
        name: 'E2E Test Server',
        url: `http://localhost:${endpointsOrPort}`,
        isActive: true,
        isDefault: false,
        status: 'unknown'
      }
    ];

  return {
    key: SERVER_ENDPOINTS_STORAGE_KEY,
    removedKey: REMOVED_DEFAULT_KEYS_STORAGE_KEY,
    endpoints
  };
}

function applySeededEndpointStorageState(storageState: SeededEndpointStorageState): void {
  try {
    const storage = window.localStorage;
    const currentUserId = storage.getItem('metoyou_currentUserId')?.trim() || null;
    const generalSettings = JSON.stringify({
      reopenLastViewedChat: false
    });

    storage.setItem(storageState.key, JSON.stringify(storageState.endpoints));
    storage.setItem(storageState.removedKey, JSON.stringify([
      'default',
      'toju-primary',
      'toju-sweden'
    ]));

    storage.setItem('metoyou_general_settings', generalSettings);

    if (currentUserId) {
      storage.setItem(`metoyou_general_settings__${encodeURIComponent(currentUserId)}`, generalSettings);
    }

    const keysToRemove: string[] = [];

    for (let index = 0; index < storage.length; index += 1) {
      const key = storage.key(index);

      if (key === 'metoyou_lastViewedChat' || key?.startsWith('metoyou_lastViewedChat__')) {
        keysToRemove.push(key);
      }
    }

    for (const key of keysToRemove) {
      storage.removeItem(key);
    }
  } catch {
    // about:blank and some Playwright UI pages deny localStorage access.
  }
}

export async function disableLastViewedChatResume(page: Page): Promise<void> {
  await page.evaluate(() => {
    const currentUserId = localStorage.getItem('metoyou_currentUserId')?.trim() || null;
    const generalSettings = JSON.stringify({ reopenLastViewedChat: false });
    const keysToRemove: string[] = [];

    localStorage.setItem('metoyou_general_settings', generalSettings);

    if (currentUserId) {
      localStorage.setItem(`metoyou_general_settings__${encodeURIComponent(currentUserId)}`, generalSettings);
    }

    for (let index = 0; index < localStorage.length; index += 1) {
      const key = localStorage.key(index);

      if (key === 'metoyou_lastViewedChat' || key?.startsWith('metoyou_lastViewedChat__')) {
        keysToRemove.push(key);
      }
    }

    for (const key of keysToRemove) {
      localStorage.removeItem(key);
    }
  });
}

export async function installTestServerEndpoint(
  context: BrowserContext,
  port: number = Number(process.env.TEST_SERVER_PORT) || 3099
): Promise<void> {
  const storageState = buildSeededEndpointStorageState(port);

  await context.addInitScript(applySeededEndpointStorageState, storageState);
}

export async function installTestServerEndpoints(
  context: BrowserContext,
  endpoints: readonly SeededEndpointInput[]
): Promise<void> {
  const storageState = buildSeededEndpointStorageState(endpoints);

  await context.addInitScript(applySeededEndpointStorageState, storageState);
}

/**
 * Seed localStorage with a single signal endpoint pointing at the test server.
 * Must be called AFTER navigating to the app origin (localStorage is per-origin)
 * but BEFORE the app reads from storage (i.e. before the Angular bootstrap is
 * relied upon - calling it in the first goto() landing page is fine since the
 * page will re-read on next navigation/reload).
 *
 * Typical usage:
 *   await page.goto('/');
 *   await seedTestServerEndpoint(page);
 *   await page.reload();   // App now picks up the test endpoint
 */
export async function seedTestServerEndpoint(
  page: Page,
  port: number = Number(process.env.TEST_SERVER_PORT) || 3099
): Promise<void> {
  const storageState = buildSeededEndpointStorageState(port);

  await page.evaluate(applySeededEndpointStorageState, storageState);
}

export async function seedTestServerEndpoints(
  page: Page,
  endpoints: readonly SeededEndpointInput[]
): Promise<void> {
  const storageState = buildSeededEndpointStorageState(endpoints);

  await page.evaluate(applySeededEndpointStorageState, storageState);
}
