import { test, expect } from '@playwright/test';
import { closeOnboardingModal } from '../helpers/navigation.js';

/**
 * Calendar Panel Tests
 *
 * Tests for the calendar panel control that allows users to navigate between
 * different years and months. The panel is opened via the "Toggle Panel" button
 * in the top-right corner of the map.
 */

test.describe('Calendar Panel', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/map');
    await closeOnboardingModal(page);

    // Wait for map to be fully loaded
    await page.waitForSelector('.leaflet-container', { state: 'visible', timeout: 10000 });
    await page.waitForTimeout(2000); // Wait for all controls to be initialized
  });

  /**
   * Helper function to find and click the calendar toggle button
   */
  async function clickCalendarButton(page) {
    // The calendar button is the "Toggle Panel" button with a calendar icon
    // It's the third button in the top-right control stack (after Select Area and Add Visit)
    const calendarButton = await page.locator('button.toggle-panel-button').first();
    await expect(calendarButton).toBeVisible({ timeout: 5000 });
    await calendarButton.click();
    await page.waitForTimeout(500); // Wait for panel animation
  }

  /**
   * Helper function to check if panel is visible
   */
  async function isPanelVisible(page) {
    const panel = page.locator('.leaflet-right-panel');
    const isVisible = await panel.isVisible().catch(() => false);
    if (!isVisible) return false;

    const displayStyle = await panel.evaluate(el => el.style.display);
    return displayStyle !== 'none';
  }

  test('should open calendar panel on first click', async ({ page }) => {
    // Verify panel is not visible initially
    const initiallyVisible = await isPanelVisible(page);
    expect(initiallyVisible).toBe(false);

    // Click calendar button
    await clickCalendarButton(page);

    // Verify panel is now visible
    const panelVisible = await isPanelVisible(page);
    expect(panelVisible).toBe(true);

    // Verify panel contains expected elements
    const yearSelect = page.locator('#year-select');
    await expect(yearSelect).toBeVisible();

    const monthsGrid = page.locator('#months-grid');
    await expect(monthsGrid).toBeVisible();

    // Verify "Whole year" link is present
    const wholeYearLink = page.locator('#whole-year-link');
    await expect(wholeYearLink).toBeVisible();
  });

  test('should close calendar panel on second click', async ({ page }) => {
    // Open panel
    await clickCalendarButton(page);
    await page.waitForTimeout(300);

    // Verify panel is visible
    let panelVisible = await isPanelVisible(page);
    expect(panelVisible).toBe(true);

    // Click button again to close
    await clickCalendarButton(page);
    await page.waitForTimeout(300);

    // Verify panel is hidden
    panelVisible = await isPanelVisible(page);
    expect(panelVisible).toBe(false);
  });

  test('should allow year selection', async ({ page }) => {
    // Open panel
    await clickCalendarButton(page);

    // Wait for year select to be populated (it loads from API)
    await page.waitForTimeout(2000);

    const yearSelect = page.locator('#year-select');
    await expect(yearSelect).toBeVisible();

    // Get available years
    const options = await yearSelect.locator('option:not([disabled])').all();

    // Should have at least one year available
    expect(options.length).toBeGreaterThan(0);

    // Select the first available year
    const firstYearOption = options[0];
    const yearValue = await firstYearOption.getAttribute('value');

    await yearSelect.selectOption(yearValue);

    // Verify year was selected
    const selectedValue = await yearSelect.inputValue();
    expect(selectedValue).toBe(yearValue);
  });

  test('should navigate to month when clicking month button', async ({ page }) => {
    // Open panel
    await clickCalendarButton(page);

    // Wait for months to load
    await page.waitForTimeout(3000);

    // Select year 2024 (which has October data in demo)
    const yearSelect = page.locator('#year-select');
    await yearSelect.selectOption('2024');
    await page.waitForTimeout(500);

    // Find October button (demo data has October 2024)
    const octoberButton = page.locator('#months-grid a[data-month-name="Oct"]');
    await expect(octoberButton).toBeVisible({ timeout: 5000 });

    // Verify October is enabled (not disabled)
    const isDisabled = await octoberButton.evaluate(el => el.classList.contains('disabled'));
    expect(isDisabled).toBe(false);

    // Verify button is clickable
    const pointerEvents = await octoberButton.evaluate(el => el.style.pointerEvents);
    expect(pointerEvents).not.toBe('none');

    // Get the expected href before clicking
    const expectedHref = await octoberButton.getAttribute('href');
    expect(expectedHref).toBeTruthy();
    const decodedHref = decodeURIComponent(expectedHref);

    expect(decodedHref).toContain('map?');
    expect(decodedHref).toContain('start_at=2024-10-01T00:00');
    expect(decodedHref).toContain('end_at=2024-10-31T23:59');

    // Click the month button and wait for navigation
    await Promise.all([
      page.waitForURL('**/map**', { timeout: 10000 }),
      octoberButton.click()
    ]);

    // Wait for page to settle
    await page.waitForLoadState('networkidle', { timeout: 10000 });

    // Verify we navigated to the map page
    expect(page.url()).toContain('/map');

    // Verify map loaded with data
    await page.waitForSelector('.leaflet-container', { state: 'visible', timeout: 10000 });
  });

  test('should navigate to whole year when clicking "Whole year" button', async ({ page }) => {
    // Open panel
    await clickCalendarButton(page);

    // Wait for panel to load
    await page.waitForTimeout(2000);

    const wholeYearLink = page.locator('#whole-year-link');
    await expect(wholeYearLink).toBeVisible();

    // Get the href and decode it
    const href = await wholeYearLink.getAttribute('href');
    expect(href).toBeTruthy();
    const decodedHref = decodeURIComponent(href);

    expect(decodedHref).toContain('map?');
    expect(decodedHref).toContain('start_at=');
    expect(decodedHref).toContain('end_at=');

    // Href should contain full year dates (01-01 to 12-31)
    expect(decodedHref).toContain('-01-01T00:00');
    expect(decodedHref).toContain('-12-31T23:59');

    // Store the expected year from the href
    const yearMatch = decodedHref.match(/(\d{4})-01-01/);
    expect(yearMatch).toBeTruthy();
    const expectedYear = yearMatch[1];

    // Click the link and wait for navigation
    await Promise.all([
      page.waitForURL('**/map**', { timeout: 10000 }),
      wholeYearLink.click()
    ]);

    // Wait for page to settle
    await page.waitForLoadState('networkidle', { timeout: 10000 });

    // Verify we navigated to the map page
    expect(page.url()).toContain('/map');

    // The URL parameters might be processed differently (e.g., stripped by Turbo or redirected)
    // Instead of checking URL, verify the panel updates to show the whole year is selected
    // by checking the year in the select dropdown
    const panelVisible = await isPanelVisible(page);
    if (!panelVisible) {
      // Panel might have closed on navigation, reopen it
      await clickCalendarButton(page);
      await page.waitForTimeout(1000);
    }

    const yearSelect = page.locator('#year-select');
    const selectedYear = await yearSelect.inputValue();
    expect(selectedYear).toBe(expectedYear);
  });

  test('should update month buttons when year is changed', async ({ page }) => {
    // Open panel
    await clickCalendarButton(page);

    // Wait for data to load
    await page.waitForTimeout(2000);

    const yearSelect = page.locator('#year-select');

    // Get available years
    const options = await yearSelect.locator('option:not([disabled])').all();

    if (options.length < 2) {
      console.log('Test skipped: Less than 2 years available');
      test.skip();
      return;
    }

    // Select first year and capture month states
    const firstYearOption = options[0];
    const firstYear = await firstYearOption.getAttribute('value');
    await yearSelect.selectOption(firstYear);
    await page.waitForTimeout(500);

    // Get enabled months for first year
    const firstYearMonths = await page.locator('#months-grid a:not(.disabled)').count();

    // Select second year
    const secondYearOption = options[1];
    const secondYear = await secondYearOption.getAttribute('value');
    await yearSelect.selectOption(secondYear);
    await page.waitForTimeout(500);

    // Get enabled months for second year
    const secondYearMonths = await page.locator('#months-grid a:not(.disabled)').count();

    // Months should be different (unless both years have same tracked months)
    // At minimum, verify that month buttons are updated (content changed from loading dots)
    const monthButtons = await page.locator('#months-grid a').all();

    for (const button of monthButtons) {
      const buttonText = await button.textContent();
      // Should not contain loading dots anymore
      expect(buttonText).not.toContain('loading');
    }
  });

  test('should highlight active month based on current URL parameters', async ({ page }) => {
    // Navigate to a specific month first
    await page.goto('/map?start_at=2024-10-01T00:00&end_at=2024-10-31T23:59');
    await closeOnboardingModal(page);
    await page.waitForSelector('.leaflet-container', { state: 'visible', timeout: 10000 });
    await page.waitForTimeout(2000);

    // Open calendar panel
    await clickCalendarButton(page);
    await page.waitForTimeout(2000);

    // Find October button (month index 9, displayed as "Oct")
    const octoberButton = page.locator('#months-grid a[data-month-name="Oct"]');
    await expect(octoberButton).toBeVisible();

    // Verify October is marked as active
    const hasActiveClass = await octoberButton.evaluate(el =>
      el.classList.contains('btn-active')
    );
    expect(hasActiveClass).toBe(true);
  });

  test('should show visited cities section in panel', async ({ page }) => {
    // Open panel
    await clickCalendarButton(page);
    await page.waitForTimeout(2000);

    // Verify visited cities section is present
    const visitedCitiesContainer = page.locator('#visited-cities-container');
    await expect(visitedCitiesContainer).toBeVisible();

    const visitedCitiesTitle = visitedCitiesContainer.locator('h3');
    await expect(visitedCitiesTitle).toHaveText('Visited cities');

    const visitedCitiesList = page.locator('#visited-cities-list');
    await expect(visitedCitiesList).toBeVisible();

    // List should eventually load (either with cities or "No places visited")
    await page.waitForTimeout(2000);
    const listContent = await visitedCitiesList.textContent();
    expect(listContent.length).toBeGreaterThan(0);
  });
});
