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

async function login(page: Page) {
  await page.goto('/login');
  await page.fill('input[type="email"]', 'superuser@headroom.test');
  await page.fill('input[type="password"]', 'password');
  await page.click('button[type="submit"]');
  await page.waitForURL('/dashboard');
}

async function getAccessToken(page: Page): Promise<string> {
  return (await page.evaluate(() => localStorage.getItem('headroom_access_token'))) as string;
}

async function setPeriod(page: Page, period = '2026-02') {
  await page.evaluate((value) => {
    localStorage.setItem('headroom_selected_period', value);
  }, period);
}

async function goToCapacity(page: Page) {
  await page.goto('/capacity');
  await expect(page).toHaveURL(/\/capacity/);
  // Click on Calendar tab to ensure it's active
  await page.getByRole('button', { name: 'Calendar' }).click();
  // Wait for team member selector to be visible
  await expect(page.locator('select[aria-label="Select team member"]')).toBeVisible({ timeout: 10000 });
  // Wait a moment for data to load
  await page.waitForTimeout(500);
}

// Backend API base URL (direct access since Vite proxy doesn't work in test env)
const API_BASE = 'http://localhost:3000';

async function createTeamMember(page: Page, token: string, overrides: Record<string, unknown> = {}) {
  const payload = {
    name: `Capacity Tester ${Date.now()}`,
    role_id: 1,
    hourly_rate: 150,
    active: true,
    ...overrides
  };

  const response = await page.request.post(`${API_BASE}/api/team-members`, {
    headers: { 
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    data: payload
  });

  return response.json();
}

async function createHoliday(page: Page, token: string, payload: { date: string; name: string; description?: string }) {
  return page.request.post(`${API_BASE}/api/holidays`, {
    headers: { 
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    data: payload
  });
}

async function createPTO(page: Page, token: string, payload: { team_member_id: string; start_date: string; end_date: string; reason?: string }) {
  return page.request.post(`${API_BASE}/api/ptos`, {
    headers: { 
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    data: payload
  });
}

test.describe('Capacity Planning - Phase 1 Tests (RED)', () => {
  let authToken: string;
  let mainMemberId: string;
  let createdMembers: string[] = [];
  let createdHolidayIds: string[] = [];

  test.beforeEach(async ({ page }) => {
    createdMembers = [];
    createdHolidayIds = [];
    await login(page);
    authToken = await getAccessToken(page);
    await setPeriod(page, '2026-02');
    const member = await createTeamMember(page, authToken);
    mainMemberId = member.id;
    createdMembers.push(mainMemberId);
    await goToCapacity(page);
    await page.selectOption('select[aria-label="Select team member"]', mainMemberId);
    // Wait for calendar to be visible after selecting team member
    await expect(page.getByTestId('capacity-calendar')).toBeVisible({ timeout: 10000 });
  });

  test.afterEach(async ({ page }) => {
    for (const holidayId of createdHolidayIds.splice(0)) {
      await page.request.delete(`${API_BASE}/api/holidays/${holidayId}`, {
        headers: { Authorization: `Bearer ${authToken}` }
      }).catch(() => null);
    }

    for (const memberId of createdMembers.splice(0)) {
      await page.request.delete(`${API_BASE}/api/team-members/${memberId}`, {
        headers: { Authorization: `Bearer ${authToken}` }
      }).catch(() => null);
    }
  });

  test.fixme('4.1.1 Calculate capacity for full month', async ({ page }) => {
    const card = page.getByTestId('team-capacity-card');
    await expect(card).toContainText('20.0d');
    await expect(card).toContainText('160 hrs');
  });

  test.fixme('4.1.2 Calculate capacity with half-day availability', async ({ page }) => {
    const targetCell = page.locator('[data-date="2026-02-03"]');
    await targetCell.locator('select').selectOption('0.5');
    await expect(targetCell).toContainText('Half day');
  });

  test.fixme('4.1.3 Calculate capacity with PTO', async ({ page }) => {
    await createPTO(page, authToken, {
      team_member_id: mainMemberId,
      start_date: '2026-02-10',
      end_date: '2026-02-12',
      reason: 'Testing PTO'
    });
    await setPeriod(page, '2026-02');
    await goToCapacity(page);
    await page.selectOption('select[aria-label="Select team member"]', mainMemberId);
    await expect(page.locator('[data-date="2026-02-10"]')).toContainText('PTO');
  });

  test.fixme('4.1.4 Calculate capacity with holidays', async ({ page }) => {
    const holiday = await createHoliday(page, authToken, {
      date: '2026-02-17',
      name: 'President Day',
      description: 'Company holiday'
    });
    const holidayId = await holiday.json().then((body) => body.id);
    createdHolidayIds.push(holidayId);
    await setPeriod(page, '2026-02');
    await goToCapacity(page);
    await page.selectOption('select[aria-label="Select team member"]', mainMemberId);
    await expect(page.locator('[data-date="2026-02-17"]')).toContainText('Holiday');
    await expect(page.getByText('President Day')).toBeVisible();
  });

  test.fixme('4.1.5 Calculate capacity with mixed availability', async ({ page }) => {
    const firstCell = page.locator('[data-date="2026-02-04"]');
    const secondCell = page.locator('[data-date="2026-02-05"]');
    await firstCell.locator('select').selectOption('0.5');
    await secondCell.locator('select').selectOption('0');
    await expect(firstCell).toContainText('Half day');
    await expect(secondCell).toContainText('Off');
  });

  test.fixme('4.1.6 Calculate team capacity sum', async ({ page }) => {
    const extra = await createTeamMember(page, authToken, { name: 'Capacity Pal', hourly_rate: 160 });
    createdMembers.push(extra.id);
    await setPeriod(page, '2026-02');
    await goToCapacity(page);
    await expect(page.getByText('2 members')).toBeVisible();
    const totalCard = page.getByTestId('team-capacity-card');
    await expect(totalCard).toContainText('40.0d');
    await expect(totalCard).toContainText('320 hrs');
  });

  test.fixme('4.1.7 Exclude inactive from team capacity', async ({ page }) => {
    const inactive = await createTeamMember(page, authToken, { name: 'Inactive Pal', active: false });
    createdMembers.push(inactive.id);
    await setPeriod(page, '2026-02');
    await goToCapacity(page);
    await expect(page.getByText('1 members')).toBeVisible();
    await expect(page.getByTestId('team-capacity-card')).toContainText('20.0d');
  });

  test.fixme('4.1.8 Calculate possible revenue', async ({ page }) => {
    const revenueResponse = await page.request.get(`${API_BASE}/api/capacity/revenue?month=2026-02`, {
      headers: { Authorization: `Bearer ${authToken}` }
    });
    const { possible_revenue } = await revenueResponse.json();
    const formatted = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(possible_revenue);
    await expect(page.getByTestId('possible-revenue-card')).toContainText(formatted);
  });

  test.fixme('4.1.9 View capacity calendar', async ({ page }) => {
    await expect(page.getByText('Sun')).toBeVisible();
    await expect(page.getByText('Mon')).toBeVisible();
  });

  test.fixme('4.1.10 Edit availability in calendar', async ({ page }) => {
    const cell = page.locator('[data-date="2026-02-07"]');
    await cell.locator('select').selectOption('0');
    await expect(cell).toContainText('Off');
    await cell.locator('select').selectOption('1');
    await expect(cell).toContainText('Full day');
  });
});

test.describe('Expert Mode E2E Tests', () => {
  let authToken: string;
  let mainMemberId: string;
  let createdMembers: string[] = [];

  test.beforeEach(async ({ page }) => {
    createdMembers = [];
    await login(page);
    authToken = await getAccessToken(page);
    await setPeriod(page, '2026-02');
    const member = await createTeamMember(page, authToken);
    mainMemberId = member.id;
    createdMembers.push(mainMemberId);
    await goToCapacity(page);
  });

  test.afterEach(async ({ page }) => {
    for (const memberId of createdMembers.splice(0)) {
      await page.request.delete(`${API_BASE}/api/team-members/${memberId}`, {
        headers: { Authorization: `Bearer ${authToken}` }
      }).catch(() => null);
    }
  });

  test.fixme('11.1 Expert Mode toggle appears on Capacity page and persists after reload', async ({ page }) => {
    await expect(page.getByLabel('Toggle Expert Mode')).toBeVisible();
    await page.getByLabel('Toggle Expert Mode').check();
    await expect(page.getByLabel('Toggle Expert Mode')).toBeChecked();
    await page.reload();
    await expect(page.getByLabel('Toggle Expert Mode')).toBeChecked();
  });

  test.fixme('11.2 Grid renders all team members as rows for selected month', async ({ page }) => {
    const extra = await createTeamMember(page, authToken, { name: 'Expert Mode Tester' });
    createdMembers.push(extra.id);
    await page.getByLabel('Toggle Expert Mode').check();
    await expect(page.getByRole('row', { name: /Capacity Tester/ })).toBeVisible();
    await expect(page.getByRole('row', { name: /Expert Mode Tester/ })).toBeVisible();
  });

  test.fixme('11.3 Typing invalid token shows red cell and disables Submit', async ({ page }) => {
    await page.getByLabel('Toggle Expert Mode').check();
    const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
    await cell.fill('invalid');
    await cell.blur();
    await expect(cell).toHaveClass(/border-error/);
    await expect(page.getByRole('button', { name: /Submit/ })).toBeDisabled();
  });

  test.fixme('11.4 Typing valid tokens and clicking Submit saves and shows success toast', async ({ page }) => {
    await page.getByLabel('Toggle Expert Mode').check();
    const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
    await cell.fill('0.5');
    await cell.blur();
    await expect(page.getByRole('button', { name: /Submit/ })).toBeEnabled();
    await page.getByRole('button', { name: /Submit/ }).click();
    await expect(page.getByText(/saved/i)).toBeVisible();
  });

  test.fixme('11.5 KPI bar updates when cell value changes', async ({ page }) => {
    await page.getByLabel('Toggle Expert Mode').check();
    const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
    await cell.fill('0.5');
    await cell.blur();
    await expect(page.getByText(/Capacity:/)).toBeVisible();
    await expect(page.getByText(/Revenue:/)).toBeVisible();
  });

  test.fixme('11.6 Switching off Expert Mode with dirty cells shows confirmation dialog', async ({ page }) => {
    await page.getByLabel('Toggle Expert Mode').check();
    const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
    await cell.fill('0.5');
    await cell.blur();
    await page.getByLabel('Toggle Expert Mode').uncheck();
    await expect(page.getByRole('dialog')).toContainText('unsaved changes');
  });
});
