import { test, expect } from '@playwright/test';
import {
  loginSeedUser,
  takeScreenshot,
  setupConsoleErrorTracking,
  setupNetworkTracking,
  assertCleanPage,
} from './utils/test-helpers';

test.describe('Journey 3: Spending Page & Cost CRUD', () => {
  let consoleErrors: string[];
  let network: ReturnType<typeof setupNetworkTracking>;

  test.beforeEach(async ({ page }) => {
    consoleErrors = setupConsoleErrorTracking(page);
    network = setupNetworkTracking(page);
  });

  test('should load spending page without errors', async ({ page }) => {
    await loginSeedUser(page);
    await page.goto('/dashboard/spending');
    await page.waitForTimeout(2000);
    await takeScreenshot(page, '12-spending-page');

    const pageContent = await page.textContent('body');
    expect(pageContent).toBeTruthy();
    assertCleanPage(consoleErrors, network);
  });

  test('should display spending page UI elements', async ({ page }) => {
    await loginSeedUser(page);
    await page.goto('/dashboard/spending');
    await page.waitForTimeout(2000);
    await takeScreenshot(page, '13-spending-ui-elements');

    // Verify heading exists
    await expect(page.locator('h1:has-text("Spending")')).toBeVisible();

    // Verify filter controls exist
    await expect(page.locator('#provider-filter')).toBeVisible();
    await expect(page.locator('#period-filter')).toBeVisible();

    // Verify stat cards exist
    const statCards = page.locator('text=Total (Filtered)');
    await expect(statCards).toBeVisible();

    expect(page.url()).toContain('/dashboard/spending');
    assertCleanPage(consoleErrors, network);
  });

  test('should create a cost entry via API and see it on spending page', async ({ page }) => {
    await loginSeedUser(page);

    // Create entry via the API (using the authenticated session)
    const uniqueNote = `E2E-test-${Date.now()}`;
    const response = await page.request.post('/api/costs', {
      data: {
        provider: 'openai',
        amount: 42.50,
        period: '2026-02',
        category: 'api',
        note: uniqueNote,
      },
    });

    expect(response.status()).toBe(201);
    const { entry } = await response.json();
    expect(entry.id).toBeTruthy();
    expect(entry.provider).toBe('openai');
    expect(entry.amount).toBe(42.5);

    await takeScreenshot(page, '12a-cost-entry-created');

    // Navigate to spending and verify entry appears
    await page.goto('/dashboard/spending');
    await page.waitForTimeout(2000);

    const pageText = await page.textContent('body');
    expect(pageText).toContain(uniqueNote);
    await takeScreenshot(page, '12b-cost-entry-visible');

    // Cleanup: delete the entry
    const deleteResponse = await page.request.delete(`/api/costs/${entry.id}`);
    expect(deleteResponse.status()).toBe(200);

    assertCleanPage(consoleErrors, network);
  });

  test('should create entry via add page UI form', async ({ page }) => {
    await loginSeedUser(page);
    await page.goto('/dashboard/add');
    await page.waitForTimeout(1000);
    await takeScreenshot(page, '12c-add-entry-form');

    // Verify form elements
    await expect(page.locator('#provider')).toBeVisible();
    await expect(page.locator('#amount')).toBeVisible();
    await expect(page.locator('#period')).toBeVisible();
    await expect(page.locator('#category')).toBeVisible();
    await expect(page.locator('#note')).toBeVisible();

    // Fill form
    await page.selectOption('#provider', 'anthropic');
    await page.fill('#amount', '19.99');
    await page.fill('#note', `E2E-form-test-${Date.now()}`);
    await takeScreenshot(page, '12d-add-entry-filled');

    // Submit
    await page.click('button[type="submit"]');

    // Wait for success state or redirect
    await page.waitForURL('**/dashboard/spending', { timeout: 10000 });
    await takeScreenshot(page, '12e-add-entry-redirected');

    expect(page.url()).toContain('/dashboard/spending');
    assertCleanPage(consoleErrors, network);
  });

  test('should delete a cost entry via API', async ({ page }) => {
    await loginSeedUser(page);

    // Create an entry first
    const createResponse = await page.request.post('/api/costs', {
      data: {
        provider: 'google',
        amount: 5.00,
        period: '2026-01',
        category: 'api',
        note: `E2E-delete-test-${Date.now()}`,
      },
    });
    expect(createResponse.status()).toBe(201);
    const { entry } = await createResponse.json();

    // Delete it
    const deleteResponse = await page.request.delete(`/api/costs/${entry.id}`);
    expect(deleteResponse.status()).toBe(200);

    // Verify it's gone
    const getResponse = await page.request.get('/api/costs');
    expect(getResponse.status()).toBe(200);
    const { entries } = await getResponse.json();
    const found = entries.find((e: { id: string }) => e.id === entry.id);
    expect(found).toBeUndefined();

    assertCleanPage(consoleErrors, network);
  });

  test('should reject unauthenticated cost entry access', async ({ page }) => {
    const response = await page.request.get('/api/costs');
    expect(response.status()).toBe(401);
  });

  test('should reject invalid cost entry creation', async ({ page }) => {
    await loginSeedUser(page);

    // Missing required fields
    const response = await page.request.post('/api/costs', {
      data: { provider: 'openai' },
    });
    expect(response.status()).toBe(400);

    // Invalid provider
    const response2 = await page.request.post('/api/costs', {
      data: { provider: 'invalid', amount: 10, period: '2026-02' },
    });
    expect(response2.status()).toBe(400);

    // Invalid period format
    const response3 = await page.request.post('/api/costs', {
      data: { provider: 'openai', amount: 10, period: 'bad-format' },
    });
    expect(response3.status()).toBe(400);
  });

  test('should filter cost entries by provider', async ({ page }) => {
    await loginSeedUser(page);

    // Fetch all entries to get baseline
    const allResponse = await page.request.get('/api/costs');
    expect(allResponse.status()).toBe(200);

    // Fetch filtered entries
    const filteredResponse = await page.request.get('/api/costs?provider=openai');
    expect(filteredResponse.status()).toBe(200);
    const { entries } = await filteredResponse.json();

    // All returned entries should be openai
    for (const entry of entries) {
      expect(entry.provider).toBe('openai');
    }

    assertCleanPage(consoleErrors, network);
  });
});
