/**
 * Test: Appointment disappears when dragged past 8 PM
 *
 * This test reproduces the bug where dragging an appointment
 * past 8 PM on the scheduler causes it to disappear.
 */

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

test.describe('Scheduler Drag Past 8 PM Bug', () => {
  test.beforeEach(async ({ page, context }) => {
    // Clear cookies to avoid stale auth issues
    await context.clearCookies();

    // Login as acme business owner
    await page.goto('http://acme.lvh.me:5173/login');
    await page.fill('input[name="username"], input[placeholder*="username" i], input[type="text"]', 'acme_owner');
    await page.fill('input[name="password"], input[placeholder*="password" i], input[type="password"]', 'password123');
    await page.click('button[type="submit"]');

    // Wait for dashboard to load
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    // Click on Scheduler in the sidebar
    await page.getByRole('link', { name: 'Scheduler' }).click();
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(500);
  });

  test('should not disappear when dragging appointment past 8 PM', async ({ page }) => {
    // Wait for scheduler to load
    await page.waitForSelector('.timeline-scroll', { timeout: 10000 });

    // Find an appointment on the scheduler
    const appointments = page.locator('[draggable="true"]').filter({ hasText: /min/ });
    const appointmentCount = await appointments.count();

    console.log(`Found ${appointmentCount} appointments`);

    if (appointmentCount === 0) {
      test.skip('No appointments found to test with');
      return;
    }

    // Get the first appointment
    const appointment = appointments.first();
    const appointmentText = await appointment.textContent();
    console.log(`Testing with appointment: ${appointmentText}`);

    // Get initial bounding box
    const initialBox = await appointment.boundingBox();
    if (!initialBox) {
      test.skip('Could not get appointment bounding box');
      return;
    }

    console.log(`Initial position: x=${initialBox.x}, y=${initialBox.y}`);

    // Find the timeline container
    const timeline = page.locator('.timeline-scroll');
    const timelineBox = await timeline.boundingBox();
    if (!timelineBox) {
      throw new Error('Could not get timeline bounding box');
    }

    // Calculate 8 PM position (20 hours * 60 minutes * 2.5 pixels per minute = 3000 pixels from start)
    // Plus we need to scroll and find the exact position
    const pixelsPerMinute = 2.5;
    const eightPMMinutes = 20 * 60; // 1200 minutes
    const tenPMMinutes = 22 * 60;   // 1320 minutes - drag past 8 PM
    const targetX = tenPMMinutes * pixelsPerMinute; // 3300 pixels from midnight

    console.log(`Target X position for 10 PM: ${targetX}`);

    // First, scroll the timeline to show the 8 PM area
    await timeline.evaluate((el, scrollTo) => {
      el.scrollLeft = scrollTo - 500; // Scroll to show 8 PM area with some padding
    }, targetX);

    await page.waitForTimeout(500); // Wait for scroll to complete

    // Get the scroll position
    const scrollLeft = await timeline.evaluate(el => el.scrollLeft);
    console.log(`Scrolled to: ${scrollLeft}`);

    // Now drag the appointment to 10 PM position (past 8 PM)
    // The target position relative to the viewport
    const targetXViewport = timelineBox.x + (targetX - scrollLeft);
    const targetY = initialBox.y + initialBox.height / 2;

    console.log(`Dragging to viewport position: x=${targetXViewport}, y=${targetY}`);

    // Perform the drag
    await appointment.hover();
    await page.mouse.down();
    await page.mouse.move(targetXViewport, targetY, { steps: 20 });
    await page.waitForTimeout(100);
    await page.mouse.up();

    // Wait for any updates
    await page.waitForTimeout(1000);

    // Take a screenshot for debugging
    await page.screenshot({ path: 'scheduler-after-drag-to-10pm.png', fullPage: true });

    // Check if the appointment still exists
    // First, look for it in the timeline
    const appointmentsAfterDrag = page.locator('[draggable="true"]').filter({ hasText: /min/ });
    const countAfterDrag = await appointmentsAfterDrag.count();

    console.log(`Appointments after drag: ${countAfterDrag}`);

    // The appointment should still be visible (either in timeline or pending)
    expect(countAfterDrag).toBeGreaterThanOrEqual(appointmentCount);

    // Also check console for any errors
    const consoleErrors: string[] = [];
    page.on('console', msg => {
      if (msg.type() === 'error') {
        consoleErrors.push(msg.text());
      }
    });

    // Check network requests for failed appointment updates
    const failedRequests: string[] = [];
    page.on('response', response => {
      if (response.url().includes('/appointments/') && response.status() >= 400) {
        failedRequests.push(`${response.url()} - ${response.status()}`);
      }
    });

    await page.waitForTimeout(500);

    if (consoleErrors.length > 0) {
      console.log('Console errors:', consoleErrors);
    }

    if (failedRequests.length > 0) {
      console.log('Failed requests:', failedRequests);
    }
  });

  test('debug: log scheduler time range and appointments', async ({ page }) => {
    // Wait for scheduler to load
    await page.waitForSelector('.timeline-scroll', { timeout: 10000 });

    // Take initial screenshot
    await page.screenshot({ path: 'scheduler-initial.png', fullPage: true });

    // Log timeline info
    const timeline = page.locator('.timeline-scroll');
    const timelineInfo = await timeline.evaluate(el => ({
      scrollWidth: el.scrollWidth,
      clientWidth: el.clientWidth,
      scrollLeft: el.scrollLeft,
    }));

    console.log('Timeline info:', timelineInfo);

    // Log all appointments
    const appointments = page.locator('[draggable="true"]').filter({ hasText: /min/ });
    const count = await appointments.count();

    console.log(`Total appointments: ${count}`);

    for (let i = 0; i < count; i++) {
      const apt = appointments.nth(i);
      const text = await apt.textContent();
      const box = await apt.boundingBox();
      console.log(`Appointment ${i}: "${text}" at position x=${box?.x}, y=${box?.y}, width=${box?.width}`);
    }

    // Scroll to different times and check visibility
    const timesToCheck = [
      { hour: 8, name: '8 AM' },
      { hour: 12, name: '12 PM' },
      { hour: 17, name: '5 PM' },
      { hour: 20, name: '8 PM' },
      { hour: 22, name: '10 PM' },
    ];

    for (const { hour, name } of timesToCheck) {
      const scrollPosition = hour * 60 * 2.5 - 200; // pixels from midnight, minus padding
      await timeline.evaluate((el, pos) => { el.scrollLeft = pos; }, scrollPosition);
      await page.waitForTimeout(300);

      const visibleApts = await appointments.count();
      console.log(`At ${name}: ${visibleApts} appointments visible, scrollLeft=${await timeline.evaluate(el => el.scrollLeft)}`);

      await page.screenshot({ path: `scheduler-at-${hour}h.png` });
    }
  });

  test('debug: monitor network during drag operation', async ({ page }) => {
    // Set up network logging
    const networkLog: { method: string; url: string; status?: number; body?: any }[] = [];

    page.on('request', request => {
      if (request.url().includes('/api/')) {
        networkLog.push({
          method: request.method(),
          url: request.url(),
          body: request.postData() ? JSON.parse(request.postData() || '{}') : null,
        });
      }
    });

    page.on('response', async response => {
      if (response.url().includes('/api/')) {
        const entry = networkLog.find(e => e.url === response.url() && !e.status);
        if (entry) {
          entry.status = response.status();
        }
      }
    });

    // Wait for scheduler
    await page.waitForSelector('.timeline-scroll', { timeout: 10000 });
    await page.waitForTimeout(1000);

    // Clear log after initial load
    networkLog.length = 0;

    // Find first appointment
    const appointments = page.locator('[draggable="true"]').filter({ hasText: /min/ });
    const appointment = appointments.first();

    if (await appointment.count() === 0) {
      test.skip('No appointments found');
      return;
    }

    const initialBox = await appointment.boundingBox();
    if (!initialBox) return;

    // Scroll to 8 PM area
    const timeline = page.locator('.timeline-scroll');
    await timeline.evaluate(el => { el.scrollLeft = 2800; }); // Near 8 PM
    await page.waitForTimeout(500);

    const timelineBox = await timeline.boundingBox();
    if (!timelineBox) return;

    // Drag to 9 PM (21 * 60 * 2.5 = 3150, minus scroll)
    const scrollLeft = await timeline.evaluate(el => el.scrollLeft);
    const targetX = timelineBox.x + (3150 - scrollLeft);

    console.log('Starting drag to 9 PM...');
    await appointment.hover();
    await page.mouse.down();
    await page.mouse.move(targetX, initialBox.y + 50, { steps: 30 });
    await page.waitForTimeout(200);
    await page.mouse.up();

    // Wait for network requests to complete
    await page.waitForTimeout(2000);

    console.log('Network requests during drag:', JSON.stringify(networkLog, null, 2));

    // Check if there were any PATCH requests and their responses
    const patchRequests = networkLog.filter(r => r.method === 'PATCH');
    console.log(`PATCH requests: ${patchRequests.length}`);

    for (const req of patchRequests) {
      console.log(`PATCH ${req.url}: status=${req.status}, body=${JSON.stringify(req.body)}`);
    }

    await page.screenshot({ path: 'scheduler-after-drag-debug.png' });
  });
});
