/* eslint-disable no-console */
/* global Chart */
// Dashboard JavaScript
let dashboardData = null;
let connectorChart = null;
let distributionChart = null;
let avgDurationChart = null;
// Convert connector name to PascalCase
function toPascalCase(str) {
  return str
    .toLowerCase()
    .split("_")
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
    .join("");
}
// Initialize the dashboard
document.addEventListener("DOMContentLoaded", () => {
  loadTheme();
  setupUI();
  loadDashboardData();
  setupEventListeners();
  // Refresh data every 30 seconds
  setInterval(loadDashboardData, 30000);
});
// Setup UI based on environment
function setupUI() {
  const isHosted = window.location.hostname === "integ.hyperswitch.io";
  // Show/hide report loader for hosted environment
  const reportLoader = document.getElementById("reportLoader");
  if (isHosted) {
    reportLoader.style.display = "flex";
  }
}
// Setup event listeners
function setupEventListeners() {
  document
    .getElementById("refreshBtn")
    .addEventListener("click", loadDashboardData);
  document
    .getElementById("loadLatestBtn")
    .addEventListener("click", loadLatestReport);
  document.getElementById("themeToggle").addEventListener("click", toggleTheme);
  document
    .getElementById("connectorFilter")
    .addEventListener("change", filterData);
  document
    .getElementById("statusFilter")
    .addEventListener("change", filterData);
  // Add event listeners for hosted environment features
  const loadReportBtn = document.getElementById("loadReportBtn");
  const reportNameInput = document.getElementById("reportNameInput");
  if (loadReportBtn) {
    loadReportBtn.addEventListener("click", loadSpecificReport);
  }
  if (reportNameInput) {
    // Allow Enter key to load report
    reportNameInput.addEventListener("keypress", (e) => {
      if (e.key === "Enter") {
        loadSpecificReport();
      }
    });
  }
  // Modal controls
  const modal = document.getElementById("testRunnerModal");
  const closeBtn = document.getElementsByClassName("close")[0];
  closeBtn.onclick = () => {
    modal.style.display = "none";
  };
  window.onclick = (event) => {
    if (event.target === modal) {
      modal.style.display = "none";
    }
  };
  document
    .getElementById("runTestBtn")
    .addEventListener("click", runIndividualTest);
  document
    .getElementById("testConnector")
    .addEventListener("change", updateTestFiles);
  document
    .getElementById("testFile")
    .addEventListener("change", updateTestCases);
}
// Load dashboard data
async function loadDashboardData() {
  try {
    let response;
    // Simple logic: local uses dashboard-data.json, hosted uses report_latest.json
    if (window.location.hostname === "integ.hyperswitch.io") {
      // Hosted environment - use latest report
      response = await fetch("./reports/report_latest.json");
    } else {
      // Local environment - use dashboard data
      response = await fetch("../cypress/reports/dashboard-data.json");
    }
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    dashboardData = await response.json();
    updateDashboard();
  } catch (error) {
    console.error("Error loading dashboard data:", error);
    const environment =
      window.location.hostname === "integ.hyperswitch.io" ? "hosted" : "local";
    showError(
      `Failed to load dashboard data for ${environment} environment. ${environment === "local" ? "Make sure to run the report generator first." : "Check if the latest report is available."}`
    );
  }
}
// Load latest report (for hosted environment)
async function loadLatestReport() {
  try {
    let response;
    if (window.location.hostname === "integ.hyperswitch.io") {
      // Hosted environment - load latest report
      response = await fetch("./reports/report_latest.json");
    } else {
      // Local environment - just reload the dashboard data
      response = await fetch("../cypress/reports/dashboard-data.json");
    }
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    dashboardData = await response.json();
    updateDashboard();
    // Show success message
    showSuccess("Latest report loaded successfully!");
  } catch (error) {
    console.error("Error loading latest report:", error);
    showError(
      "Failed to load latest report. Please check if the report is available."
    );
  }
}
// Load specific report by name (for hosted environment)
async function loadSpecificReport() {
  const reportNameInput = document.getElementById("reportNameInput");
  const reportName = reportNameInput.value.trim();
  if (!reportName) {
    showError("Please enter a report name.");
    return;
  }
  try {
    // Add .json extension if not present
    const fileName = reportName.endsWith(".json")
      ? reportName
      : `${reportName}.json`;
    const response = await fetch(`./reports/${fileName}`);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    dashboardData = await response.json();
    updateDashboard();
    // Show success message
    showSuccess(`Report "${fileName}" loaded successfully!`);
    // Clear the input
    reportNameInput.value = "";
  } catch (error) {
    console.error("Error loading specific report:", error);
    showError(
      `Failed to load report "${reportName}". Please check if the report exists.`
    );
  }
}
// Update dashboard with loaded data
function updateDashboard() {
  if (!dashboardData) return;
  // Update last updated time (this is the test run timestamp)
  document.getElementById("lastUpdated").textContent =
    `Last Test Run: ${new Date(dashboardData.timestamp).toLocaleString()}`;
  // Update summary cards
  updateSummaryCards();
  // Update charts
  updateCharts();
  // Update connector filters
  updateConnectorFilters();
  // Apply filters
  filterData();
  // Setup collapsible failed tests
  setupFailedTestsCollapsible();
}
// Update summary cards
function updateSummaryCards() {
  // Count active connectors
  const activeConnectors = Object.entries(dashboardData.connectors).filter(
    ([, data]) => data.totalTests > 0
  ).length;
  // Update total connectors
  document.getElementById("totalConnectors").textContent = activeConnectors;
  // Merge skipped and pending
  const totalSkippedPending =
    dashboardData.totalSkipped + dashboardData.totalPending;
  document.getElementById("totalTests").textContent = dashboardData.totalTests;
  document.getElementById("totalPassed").textContent =
    dashboardData.totalPassed;
  document.getElementById("totalFailed").textContent =
    dashboardData.totalFailed;
  document.getElementById("totalSkipped").textContent = totalSkippedPending;
  document.getElementById("successRate").textContent =
    `${dashboardData.overallSuccessRate}%`;
  // Calculate and display failure rate
  const failureRate =
    dashboardData.totalTests > 0
      ? ((dashboardData.totalFailed / dashboardData.totalTests) * 100).toFixed(
          2
        )
      : 0;
  document.getElementById("failureRate").textContent = `${failureRate}%`;
  document.getElementById("executionTime").textContent = formatDuration(
    dashboardData.executionTime
  );
}
// Format duration from milliseconds
function formatDuration(ms) {
  const seconds = Math.floor(ms / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  if (hours > 0) {
    return `${hours}h ${minutes % 60}m`;
  } else if (minutes > 0) {
    return `${minutes}m ${seconds % 60}s`;
  } else {
    return `${seconds}s`;
  }
}
// Get chart colors based on theme
function getChartColors() {
  const isDark = document.body.classList.contains("dark-theme");
  return {
    textColor: isDark ? "#e0e0e0" : "#212529",
    gridColor: isDark ? "#2d2d2d" : "#e9ecef",
    executionLineColor: "#f59e0b",
    scales: {
      x: {
        ticks: {
          color: isDark ? "#e0e0e0" : "#212529",
        },
        grid: {
          color: isDark ? "#2d2d2d" : "#e9ecef",
        },
      },
      y: {
        ticks: {
          color: isDark ? "#e0e0e0" : "#212529",
        },
        grid: {
          color: isDark ? "#2d2d2d" : "#e9ecef",
        },
      },
    },
  };
}
// Update charts
function updateCharts() {
  updateCombinedChart();
  updateDistributionChart();
  updateAvgDurationChart();
}
// Update combined chart (test results + execution time)
function updateCombinedChart() {
  const ctx = document.getElementById("connectorChart").getContext("2d");
  const colors = getChartColors();
  // Filter out connectors with no tests
  const activeConnectors = Object.entries(dashboardData.connectors).filter(
    ([, data]) => data.totalTests > 0
  );
  const connectorNames = activeConnectors.map(([name]) => name);
  // Calculate execution times for secondary axis
  const executionTimes = connectorNames.map((c) => {
    const connector = dashboardData.connectors[c];
    const totalTime = connector.executionTime || 0;
    return (totalTime / 1000 / 60).toFixed(2); // Convert to minutes
  });
  const datasets = [
    {
      label: "Passed",
      data: connectorNames.map((c) => dashboardData.connectors[c].passed),
      backgroundColor: "#04c38d",
      stack: "tests",
      yAxisID: "y",
    },
    {
      label: "Failed",
      data: connectorNames.map((c) => dashboardData.connectors[c].failed),
      backgroundColor: "#ef4444",
      stack: "tests",
      yAxisID: "y",
    },
    {
      label: "Skipped/Pending",
      data: connectorNames.map(
        (c) =>
          dashboardData.connectors[c].skipped +
          dashboardData.connectors[c].pending
      ),
      backgroundColor: "#3b82f6",
      stack: "tests",
      yAxisID: "y",
    },
    {
      label: "Execution Time (min)",
      data: executionTimes,
      type: "line",
      borderColor: colors.executionLineColor,
      backgroundColor: "transparent",
      borderWidth: 2,
      pointBackgroundColor: colors.executionLineColor,
      pointBorderColor: colors.executionLineColor,
      pointRadius: 4,
      yAxisID: "y1",
    },
  ];
  if (connectorChart) {
    connectorChart.destroy();
  }
  connectorChart = new Chart(ctx, {
    type: "bar",
    data: {
      labels: connectorNames.map((c) => toPascalCase(c)),
      datasets: datasets,
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        x: {
          stacked: true,
          ticks: {
            color: colors.textColor,
          },
          grid: {
            color: colors.gridColor,
          },
        },
        y: {
          stacked: true,
          beginAtZero: true,
          position: "left",
          title: {
            display: true,
            text: "Number of Tests",
            color: colors.textColor,
          },
          ticks: {
            color: colors.textColor,
          },
          grid: {
            color: colors.gridColor,
          },
        },
        y1: {
          beginAtZero: true,
          position: "right",
          title: {
            display: true,
            text: "Time (minutes)",
            color: colors.executionLineColor,
          },
          ticks: {
            color: colors.executionLineColor,
          },
          grid: {
            drawOnChartArea: false,
          },
        },
      },
      plugins: {
        legend: {
          position: "top",
          labels: {
            color: colors.textColor,
          },
        },
        tooltip: {
          mode: "index",
          intersect: false,
        },
      },
    },
  });
}
// Update distribution chart
function updateDistributionChart() {
  const ctx = document.getElementById("distributionChart").getContext("2d");
  const colors = getChartColors();
  const data = {
    labels: ["Passed", "Failed", "Skipped/Pending"],
    datasets: [
      {
        data: [
          dashboardData.totalPassed,
          dashboardData.totalFailed,
          dashboardData.totalSkipped + dashboardData.totalPending,
        ],
        backgroundColor: ["#04c38d", "#ef4444", "#3b82f6"],
      },
    ],
  };
  if (distributionChart) {
    distributionChart.destroy();
  }
  distributionChart = new Chart(ctx, {
    type: "doughnut",
    data: data,
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          position: "right",
          labels: {
            color: colors.textColor,
          },
        },
        tooltip: {
          callbacks: {
            label: function (context) {
              const label = context.label || "";
              const value = context.parsed || 0;
              const total = dashboardData.totalTests;
              const percentage = ((value / total) * 100).toFixed(1);
              return `${label}: ${value} (${percentage}%)`;
            },
          },
        },
      },
    },
  });
}
// Update average duration chart
function updateAvgDurationChart() {
  const ctx = document.getElementById("avgDurationChart").getContext("2d");
  const colors = getChartColors();
  // Filter out connectors with no tests
  const activeConnectors = Object.entries(dashboardData.connectors).filter(
    ([, data]) => data.totalTests > 0
  );
  const connectorNames = activeConnectors.map(([name]) => name);
  const avgDurations = connectorNames.map((c) => {
    const connector = dashboardData.connectors[c];
    const totalTime = connector.executionTime || 0;
    const totalTests = connector.totalTests || 1;
    return (totalTime / totalTests / 1000).toFixed(2); // Average time in seconds
  });
  if (avgDurationChart) {
    avgDurationChart.destroy();
  }
  avgDurationChart = new Chart(ctx, {
    type: "bar",
    data: {
      labels: connectorNames.map((c) => toPascalCase(c)),
      datasets: [
        {
          label: "Average Test Duration (seconds)",
          data: avgDurations,
          backgroundColor: "#04c38d",
          borderColor: "#059669",
          borderWidth: 1,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        x: {
          ticks: {
            color: colors.textColor,
          },
          grid: {
            color: colors.gridColor,
          },
        },
        y: {
          beginAtZero: true,
          title: {
            display: true,
            text: "Time (seconds)",
            color: colors.textColor,
          },
          ticks: {
            color: colors.textColor,
          },
          grid: {
            color: colors.gridColor,
          },
        },
      },
      plugins: {
        legend: {
          display: false,
        },
        tooltip: {
          callbacks: {
            label: function (context) {
              return `${context.parsed.y} seconds`;
            },
          },
        },
      },
    },
  });
}
// Update connector filters
function updateConnectorFilters() {
  const filterSelect = document.getElementById("connectorFilter");
  filterSelect.innerHTML = '';
  // Only show connectors with tests
  Object.entries(dashboardData.connectors)
    .filter(([, data]) => data.totalTests > 0)
    .forEach(([connector]) => {
      const option = document.createElement("option");
      option.value = connector;
      option.textContent = toPascalCase(connector);
      filterSelect.appendChild(option);
    });
}
// Filter data based on selections
function filterData() {
  const connectorFilter = document.getElementById("connectorFilter").value;
  const statusFilter = document.getElementById("statusFilter").value;
  // Update tables
  updateConnectorTables(connectorFilter);
  // Update failed tests
  updateFailedTests(connectorFilter, statusFilter);
}
// Update connector tables
function updateConnectorTables(connectorFilter) {
  const container = document.getElementById("connectorTables");
  container.innerHTML = "";
  Object.entries(dashboardData.connectors).forEach(([connector, data]) => {
    if (connectorFilter && connector !== connectorFilter) {
      return;
    }
    // Hide connectors with no tests executed
    if (data.totalTests === 0) {
      return;
    }
    const tableDiv = createConnectorTable(connector, data);
    container.appendChild(tableDiv);
  });
}
// Create connector table
function createConnectorTable(connector, data) {
  const div = document.createElement("div");
  div.className = "connector-table collapsed";
  div.dataset.connector = connector;
  const header = document.createElement("h3");
  const totalCount = data.totalTests;
  const passedCount = data.passed;
  const failedCount = data.failed;
  const skippedPendingCount = data.skipped + data.pending;
  // Create summary text
  const summaryParts = [];
  summaryParts.push(`${totalCount} tests`);
  if (passedCount > 0) summaryParts.push(`${passedCount} passed`);
  if (failedCount > 0)
    summaryParts.push(
      `${failedCount} failed`
    );
  if (skippedPendingCount > 0)
    summaryParts.push(`${skippedPendingCount} skipped`);
  // Add execution time if available
  if (data.executionTime) {
    const timeInMinutes = (data.executionTime / 1000 / 60).toFixed(1);
    summaryParts.push(`${timeInMinutes} min`);
  }
  // Create properly aligned header with padding
  header.innerHTML = `
        ${toPascalCase(connector)}
        (${summaryParts.join(", ")})
        
    `;
  // Add click handler to toggle collapse
  header.addEventListener("click", (e) => {
    if (!e.target.classList.contains("run-test-btn")) {
      div.classList.toggle("collapsed");
    }
  });
  div.appendChild(header);
  const table = document.createElement("table");
  table.innerHTML = `
        
            
                 
        
        Test File 
                Passed 
                Failed 
                Skipped/Pending 
                Total 
            
No failed tests! 🎉
'; document.getElementById("failedTestsSection").style.display = filteredTests.length === 0 && !connectorFilter ? "none" : "block"; return; } document.getElementById("failedTestsSection").style.display = "block"; // Update failed count in header document.getElementById("failedCount").textContent = `(${filteredTests.length})`; filteredTests.forEach((test, index) => { const testDiv = createFailedTestElement(test, index); container.appendChild(testDiv); }); } // Open test runner modal window.openTestRunner = function (connector) { const modal = document.getElementById("testRunnerModal"); modal.style.display = "block"; // Populate connector dropdown const connectorSelect = document.getElementById("testConnector"); connectorSelect.innerHTML = ""; if (connector) { const option = document.createElement("option"); option.value = connector; option.textContent = toPascalCase(connector); connectorSelect.appendChild(option); } else { Object.keys(dashboardData.connectors) .filter((conn) => dashboardData.connectors[conn].totalTests > 0) .forEach((conn) => { const option = document.createElement("option"); option.value = conn; option.textContent = toPascalCase(conn); connectorSelect.appendChild(option); }); } updateTestFiles(); }; // Update test files dropdown function updateTestFiles() { const connector = document.getElementById("testConnector").value; const fileSelect = document.getElementById("testFile"); fileSelect.innerHTML = ''; if (connector && dashboardData.connectors[connector]) { Object.keys(dashboardData.connectors[connector].testsByFile).forEach( (file) => { const option = document.createElement("option"); option.value = file; option.textContent = file.split("/").pop(); fileSelect.appendChild(option); } ); } updateTestCases(); } // Update test cases dropdown function updateTestCases() { const connector = document.getElementById("testConnector").value; const file = document.getElementById("testFile").value; const caseSelect = document.getElementById("testCase"); caseSelect.innerHTML = ''; if (connector && file && dashboardData.connectors[connector]) { const tests = dashboardData.connectors[connector].testsByFile[file].tests; tests.forEach((test) => { const option = document.createElement("option"); option.value = test.title; option.textContent = test.title; caseSelect.appendChild(option); }); } } // Run individual test async function runIndividualTest() { const connector = document.getElementById("testConnector").value; const file = document.getElementById("testFile").value; const testCase = document.getElementById("testCase").value; const output = document.getElementById("testOutput"); if (!connector || !file) { alert("Please select a connector and test file"); return; } output.innerHTML = ' Running test...'; try { // Construct the command const fileName = file.split("/").pop(); const spec = testCase ? `--spec "**/spec/**/${fileName}" --grep "${testCase}"` : `--spec "**/spec/**/${fileName}"`; const command = `CYPRESS_CONNECTOR="${connector}" npm run cypress:ci -- ${spec}`; // For demo purposes, we'll show the command output.innerHTML = ` Command to run:${command}
            To run this test, execute the above command in your terminal.
Note: Real-time test execution requires a backend service to execute commands and stream results.
`; } catch (error) { output.innerHTML = `