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

const visualizationTests = [
  { name: 'pztour', viewport: { width: 1440, height: 900, name: 'laptop-hd' } },
  
];

for (const vis of visualizationTests) {
  test.describe(`Visualization-Drag&Drop Page - ${vis.name}`, () => {
    test(`Drag & Drop Widgets, Save Template, Apply Template, and Remove Widgets in ${vis.name}`, async ({ page }) => {
      // Increase timeout for the whole test
      test.setTimeout(120000);
      page.setDefaultTimeout(60000);

      // Create screenshots directory if it doesn't exist
      const screenshotsDir = path.join(process.cwd(), `screenshots/visualization2D/${vis.viewport.name}`);
      if (!fs.existsSync(screenshotsDir)) {
        fs.mkdirSync(screenshotsDir, { recursive: true });
      }

      // Widget locators
      const widgets = [
        page.locator('.chart.chart-1'),
        page.locator('.chart.chart-2'),
        page.locator('.chart.chart-3'),
        page.locator('.chart.chart-4'),
        page.locator('.chart.chart-5'),
        page.getByText("Widget 7").first(),
        page.getByText("Widget 8").first(),
      ];

      // Panel locators
      const panels = {
        left: page.locator('.left-panel.panel'),
        bottom: page.locator('.bottom-panel.panel'),
        top: page.locator('.top-panel.panel'),
        right: page.locator('.right-panel.panel'),
      };

      // Remove button locators
      const removeButtons = {
        top: page.getByTitle('Remove all items and close top panel'),
        right: page.getByTitle('Remove all items and close right panel'),
        bottom: page.getByTitle('Remove all items and close bottom panel'),
        left: page.getByTitle('Remove all items and close left panel'),
      };

      // Helper function to activate panel and wait for visibility
      const activateAndCheckPanel = async (panelLocator, activateButtonTitle) => {
        console.log(`Activating ${activateButtonTitle}...`);
        try {
          // Wait for the button to be visible and enabled
          console.log(`Waiting for button with title: ${activateButtonTitle}`);
          await page.waitForSelector(`[title="${activateButtonTitle}"]`, { state: 'visible', timeout: 20000 });

          // Click the button
          console.log(`Clicking button with title: ${activateButtonTitle}`);
          await page.getByTitle(activateButtonTitle).click();

          // Wait for the panel to become visible
          console.log(`Waiting for panel to become visible...`);
          await expect(panelLocator).toBeVisible({ timeout: 10000 });
        } catch (error) {
          console.error(`Failed to activate panel: ${activateButtonTitle}`);
          console.error(error);
          throw error;
        }
      };

      // Helper function to drag widgets with retries
      const dragWithRetry = async (source, target, retries = 3) => {
        for (let i = 0; i < retries; i++) {
          try {
            console.log(`Dragging widget to panel (attempt ${i + 1})...`);
            await source.dragTo(target, { force: true });
            return;
          } catch (error) {
            if (i === retries - 1) throw error;
            console.warn(`Drag failed (attempt ${i + 1}), retrying...`);
            await new Promise(res => setTimeout(res, 1000));
          }
        }
      };

      // Helper function to remove all items from panels
      const removeAllItemsFromPanels = async () => {
        console.log('Removing all items from panels...');
        const panelOrder = ['top', 'right', 'bottom', 'left'];
        for (const panelName of panelOrder) {
          console.log(`Removing items from ${panelName} panel...`);
          await removeButtons[panelName].click();
          await page.waitForTimeout(2000); // Wait for removal animation or transition
        }
      };

      // Navigate to app
      console.log(`Navigating to app for ${vis.name}...`);
      await page.goto('http://185.100.212.76:8200');
      await page.getByPlaceholder('Email').fill('ramkumar@testdomin.local');
      await page.getByPlaceholder('Password').fill('123456');
      await page.getByRole('button', { name: 'Continue', exact: true }).click();
      await expect(page.getByText('Visualization')).toBeVisible({ timeout: 20000 });

      // Set viewport size and toggle full-screen mode
      console.log('Setting viewport size and toggling full-screen mode...');
      await page.setViewportSize({
        width: vis.viewport.width,
        height: vis.viewport.height,
      });
      await page.evaluate(() => document.documentElement.requestFullscreen());

      // Go to Visualization > Zone
      console.log(`Navigating to Visualization > ${vis.name}...`);
      await page.getByText('Visualization').click();
      await page.getByText(vis.name).click();

      // Drag widgets into all panels
      console.log('Dragging widgets into all panels...');
      const panelOrder = ['left', 'right', 'bottom', 'top'];
      for (const panelName of panelOrder) {
        await activateAndCheckPanel(panels[panelName], `Activate ${panelName} panel`);
        for (const widget of widgets) {
          await dragWithRetry(widget, panels[panelName]);
        }
      }

      // Verify that all panels contain widgets
      console.log('Verifying all panels contain widgets...');
      await page.waitForFunction(() => {
        return (
          document.querySelector('.left-panel')?.children.length > 0 &&
          document.querySelector('.right-panel')?.children.length > 0 &&
          document.querySelector('.bottom-panel')?.children.length > 0 &&
          document.querySelector('.top-panel')?.children.length > 0
        );
      });

      // Take a screenshot after drag-and-drop operations
      console.log('Taking screenshot after drag-and-drop...');
      await page.screenshot({ path: path.join(screenshotsDir, `${vis.name}-after-drag.png`) });

      // Save the template
      console.log('Saving template...');
      await page.getByRole('button', { name: /save template/i }).click();
      await expect(page.getByRole('button', { name: /save template/i })).toBeVisible();

      // Navigate to Templates tab
      console.log('Navigating to Templates tab...');
      await page.getByText('Templates', { exact: true }).click();
      await page.getByText('Zone 4').click();
      await page.waitForTimeout(2000);

      // Apply the saved template (Template 1)
      console.log('Applying saved template...');
      await page.locator('.template-item', { hasText: 'Template 1' }).click();
      await page.waitForTimeout(2000);

      // Optionally, assert widgets are restored in all panels
      console.log('Verifying widgets are restored in all panels...');
      await page.waitForFunction(() => {
        return (
          document.querySelector('.left-panel')?.children.length > 0 &&
          document.querySelector('.right-panel')?.children.length > 0 &&
          document.querySelector('.bottom-panel')?.children.length > 0 &&
          document.querySelector('.top-panel')?.children.length > 0
        );
      });

      // Remove all items from panels
      await removeAllItemsFromPanels();

      // Add a grace period for animations or transitions
      console.log('Waiting for panels to clear...');
      await page.waitForTimeout(3000); // Wait for 3 seconds to allow any animations or transitions to complete

      // Take a final screenshot after removal
      console.log('Taking screenshot after removal...');
      await page.screenshot({ path: path.join(screenshotsDir, `${vis.name}-after-remove.png`) });

      // Navigating back to Visualization > Zone
      console.log(`Navigating to Visualization > ${vis.name}...`);
      await page.getByText('Visualization').click();
      await page.getByText(vis.name).click();

      // Remove all items from panels again
      await removeAllItemsFromPanels();

      // Locate and click the delete button for "Template 1"
      console.log('Locating and clicking the delete button for "Template 1"...');
      const deleteButton = page.locator(
        '.template-details:has(.template-name > .input-value:text("Template 1")) #template-delete-button'
      );
      await deleteButton.waitFor({ state: 'visible', timeout: 10000 }); // Ensure the button is visible
      await deleteButton.click();

      console.log(`Test for ${vis.name} completed successfully.`);
    });
  });
}