import { test, expect } from "@playwright/test";

// Run tests serially to avoid provider cleanup conflicts
test.describe.configure({ mode: 'serial' });

let apiAvailable = false;

test.describe("AI Providers", () => {
  test.beforeEach(async ({ page, request }) => {
    apiAvailable = false;

    // Clean up any existing test providers first
    try {
      const response = await request.get("http://127.0.0.1:3000/api/ai/providers");
      if (response.ok()) {
        apiAvailable = true;
        const providers = await response.json();
        for (const provider of providers) {
          if (provider.name.includes("Test")) {
            await request.delete(`http://127.0.0.1:3000/api/ai/providers/${provider.id}`);
          }
        }
      }
    } catch {
      // Ignore cleanup errors
    }

    // Clear localStorage and set local API URL
    await page.goto("/settings");
    await page.evaluate(() => {
      localStorage.clear();
      localStorage.setItem(
        "settings",
        JSON.stringify({ apiUrl: "http://127.0.0.1:3000" })
      );
    });
    // Reload to pick up new settings
    await page.reload();
    // Wait for the page to load
    await expect(page.getByRole("heading", { name: "Settings" })).toBeVisible();
    // Wait for providers to load
    await page.waitForTimeout(1000);
  });

  test.afterEach(async ({ request }) => {
    if (!apiAvailable) return;

    // Clean up any test providers created
    try {
      const response = await request.get("http://127.0.0.1:3000/api/ai/providers");
      if (response.ok()) {
        const providers = await response.json();
        for (const provider of providers) {
          if (provider.name.includes("Test")) {
            await request.delete(`http://127.0.0.1:3000/api/ai/providers/${provider.id}`);
          }
        }
      }
    } catch {
      // Ignore cleanup errors
    }
  });

  test("shows AI Providers section", async ({ page }) => {
    // Check the AI Providers section exists
    await expect(page.getByRole("heading", { name: "AI Providers" })).toBeVisible({ timeout: 10000 });
    await expect(page.getByText("Configure inference providers for OpenCode")).toBeVisible();
  });

  test("shows empty state when no providers configured", async ({ page }) => {
    // Check for empty state message (may or may not be visible depending on existing providers)
    const emptyState = page.locator("text=No providers configured");
    const providerList = page.locator('[class*="rounded-lg border p-3"]');

    // Either empty state or provider list should be visible
    const isEmpty = await emptyState.isVisible().catch(() => false);
    if (isEmpty) {
      await expect(emptyState).toBeVisible();
      await expect(
        page.locator("text=Add an AI provider to enable inference capabilities")
      ).toBeVisible();
    } else {
      // Providers exist
      await expect(providerList.first()).toBeVisible();
    }
  });

  test("can open add provider modal", async ({ page }) => {
    // Click the Add Provider button
    await page.click("text=Add Provider");

    // Check modal appears
    await expect(page.getByRole("heading", { name: "Add Provider" })).toBeVisible();
  });

  test("provider list shows common providers", async ({ page }) => {
    test.skip(!apiAvailable, 'API not available');

    // Click the Add Provider button
    await page.click("text=Add Provider");

    // Should list common providers
    await expect(page.getByRole("button", { name: "Anthropic" })).toBeVisible();
    await expect(page.getByRole("button", { name: "OpenAI" })).toBeVisible();
  });

  test("shows OAuth options for Anthropic provider", async ({ page }) => {
    test.skip(!apiAvailable, 'API not available');

    // Open modal
    await page.click("text=Add Provider");

    // Select Anthropic
    await page.getByRole("button", { name: "Anthropic" }).click();

    // Should show auth methods
    await expect(page.getByRole("heading", { name: /Connect Anthropic/i })).toBeVisible();
    await expect(page.getByRole("button", { name: /Claude Pro\/Max/i })).toBeVisible();
    await expect(page.getByRole("button", { name: /Enter API Key/i })).toBeVisible();
  });

  test("shows OAuth options for OpenAI provider", async ({ page }) => {
    test.skip(!apiAvailable, 'API not available');

    // Open modal
    await page.click("text=Add Provider");

    // Select OpenAI
    await page.getByRole("button", { name: "OpenAI" }).click();

    // Should show auth methods
    await expect(page.getByRole("heading", { name: /Connect OpenAI/i })).toBeVisible();
    await expect(
      page.getByRole("button", { name: /ChatGPT Plus\/Pro/i })
    ).toBeVisible();
    await expect(page.getByRole("button", { name: /Enter API Key/i })).toBeVisible();
  });

  test("can cancel add provider modal", async ({ page }) => {
    // Open modal
    await page.click("text=Add Provider");
    await expect(page.getByRole("heading", { name: "Add Provider" })).toBeVisible();

    // Close with Escape
    await page.keyboard.press('Escape');
    await expect(page.getByRole("heading", { name: "Add Provider" })).not.toBeVisible();
  });

  test("validates required fields when adding provider", async ({ page }) => {
    test.skip(!apiAvailable, 'API not available');

    // Open modal and pick OpenAI
    await page.click("text=Add Provider");
    await page.getByRole("button", { name: "OpenAI" }).click();

    // Select API key method
    await page.getByRole("button", { name: /Enter API Key/i }).click();

    // Should show API key field
    await expect(page.getByPlaceholder("sk-...")).toBeVisible();

    const addButton = page.getByRole("button", { name: "Add Provider" });
    await expect(addButton).toBeDisabled();

    // Fill API key
    await page.getByPlaceholder("sk-...").fill("sk-test-key");
    await expect(addButton).toBeEnabled();
  });

  test("can create an API key provider", async ({ page, request }) => {
    test.skip(!apiAvailable, 'API not available');

    // Create provider via API directly for reliability
    await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "openai",
        name: "Test OpenAI Provider",
        api_key: "sk-test-key-12345",
      },
    });

    // Reload to see the new provider
    await page.reload();
    await page.waitForTimeout(1000);

    // The new provider should appear in the list
    await expect(page.getByText("Test OpenAI Provider")).toBeVisible({ timeout: 10000 });
  });

  test("can create an OAuth provider", async ({ page, request }) => {
    test.skip(!apiAvailable, 'API not available');

    // Create OAuth provider via API directly
    await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "anthropic",
        name: "Test Anthropic Provider",
      },
    });

    // Reload to see the new provider
    await page.reload();
    await page.waitForTimeout(1000);

    // The new provider should appear in the list
    await expect(page.getByText("Test Anthropic Provider")).toBeVisible({ timeout: 10000 });
  });

  test("shows Connect button for providers needing auth", async ({ page, request }) => {
    test.skip(!apiAvailable, 'API not available');

    // Create OAuth provider via API
    await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "anthropic",
        name: "Auth Test Provider",
      },
    });

    // Reload to see the new provider
    await page.reload();
    await page.waitForTimeout(1000);

    // Should see the provider first
    const providerRow = page.locator('div').filter({ hasText: "Auth Test Provider" }).filter({
      has: page.locator('button[title="Connect"]'),
    }).first();
    await expect(providerRow).toBeVisible({ timeout: 10000 });

    await providerRow.hover();
    await expect(providerRow.locator('button[title="Connect"]')).toBeVisible();
  });

  test("can edit a provider", async ({ page, request }) => {
    test.skip(!apiAvailable, 'API not available');

    // Create provider via API
    await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "openai",
        name: "Edit Test Provider",
        api_key: "sk-test-key-edit",
      },
    });

    // Reload to see the new provider
    await page.reload();
    await page.waitForTimeout(1000);

    const providerRow = page.locator('div').filter({ hasText: "Edit Test Provider" }).filter({
      has: page.locator('button[title="Edit"]'),
    }).first();
    await expect(providerRow).toBeVisible({ timeout: 10000 });

    await providerRow.hover();
    await providerRow.locator('button[title="Edit"]').click();

    // Should see the edit form with Name placeholder
    await expect(page.getByPlaceholder("Name")).toBeVisible({ timeout: 5000 });

    // Should be able to save or cancel
    await expect(page.getByRole("button", { name: "Save" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Cancel" }).first()).toBeVisible();

    // Cancel the edit
    await page.getByRole("button", { name: "Cancel" }).first().click();
  });

  test("can set a provider as default", async ({ page, request }) => {
    test.skip(!apiAvailable, 'API not available');

    // Create two providers via API
    await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "openai",
        name: "Default Test Provider 1",
        api_key: "sk-test-key-default-1",
      },
    });
    await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "groq",
        name: "Default Test Provider 2",
        api_key: "sk-test-key-default-2",
      },
    });

    const listResponse = await request.get("http://127.0.0.1:3000/api/ai/providers");
    const providers = await listResponse.json();
    const candidates = providers.filter((provider: { name: string }) =>
      provider.name.startsWith("Default Test Provider")
    );
    const target = candidates.find((provider: { is_default: boolean }) => !provider.is_default);

    test.skip(!target, 'No non-default provider to update');

    // Reload to see the providers
    await page.reload();
    await page.waitForTimeout(1000);

    const providerRow = page.locator('div').filter({ hasText: target.name }).filter({
      has: page.locator('button[title="Set as default"]'),
    }).first();
    await expect(providerRow).toBeVisible({ timeout: 10000 });

    await providerRow.hover();
    await providerRow.locator('button[title="Set as default"]').click();

    // Should see the Default star indicator
    await expect(providerRow.locator('svg.text-indigo-400')).toBeVisible({ timeout: 10000 });
  });

  test("can delete a provider", async ({ page, request }) => {
    test.skip(!apiAvailable, 'API not available');

    // Create provider via API
    const response = await request.post("http://127.0.0.1:3000/api/ai/providers", {
      data: {
        provider_type: "openai",
        name: "Delete Test Provider",
        api_key: "sk-delete-test",
      },
    });

    if (!response.ok()) {
      const text = await response.text();
      throw new Error(`Failed to create provider: ${text}`);
    }

    // Reload to see the new provider
    await page.reload();
    await page.waitForTimeout(1000);

    const providerRow = page.locator('div').filter({ hasText: "Delete Test Provider" }).filter({
      has: page.locator('button[title="Delete"]'),
    }).first();
    await expect(providerRow).toBeVisible({ timeout: 10000 });

    await providerRow.hover();
    await providerRow.locator('button[title="Delete"]').click();
    await page.waitForTimeout(1000);

    // Provider should be removed
    await expect(page.getByText("Delete Test Provider")).not.toBeVisible();
  });
});
