import jsPDF from 'jspdf';
import { toPng } from 'html-to-image';
import toast from 'react-hot-toast';
import { formatDate } from '@/lib/helper';
import { DashboardFilterType } from '@/components/pages/dashboard/filter/DashboardProductionFilter.schema';
import { DashboardExportChartsRef } from '@/components/pages/dashboard/export/DashboardExportCharts';
import { DashboardExportStatsRef } from '@/components/pages/dashboard/export/DashboardExportStats';

interface DashboardPDFExportParams {
  filterValues: DashboardFilterType;
  allStatsRef: React.RefObject<DashboardExportStatsRef | null>;
  allChartsRef: React.RefObject<DashboardExportChartsRef | null>;
  setExporting: (value: boolean) => void;
}

export const generateDashboardPDF = async ({
  filterValues,
  allStatsRef,
  allChartsRef,
  setExporting,
}: DashboardPDFExportParams): Promise<void> => {
  try {
    setExporting(true);
    toast.loading('Generating PDF...', { id: 'export-pdf' });

    // Wait for DOM to update
    await new Promise((resolve) => setTimeout(resolve, 200));

    const pdf = new jsPDF('p', 'mm', 'a4');
    const pageWidth = pdf.internal.pageSize.getWidth();
    const pageHeight = pdf.internal.pageSize.getHeight();
    const margin = 10;
    let yPosition = margin;

    // Add title
    pdf.setFontSize(16);
    pdf.setFont('helvetica', 'bold');
    pdf.text('Dashboard Produksi', margin, yPosition);
    yPosition += 10;

    // Add filter information (horizontal layout)
    pdf.setFontSize(6);
    pdf.setFont('helvetica', 'normal');

    const filterItems: string[] = [];

    // Period
    if (filterValues.startDate || filterValues.endDate) {
      const periodText = `Periode: ${
        filterValues.startDate
          ? formatDate(filterValues.startDate, 'DD MMM YYYY')
          : '-'
      } s.d ${
        filterValues.endDate
          ? formatDate(filterValues.endDate, 'DD MMM YYYY')
          : '-'
      }`;
      filterItems.push(periodText);
    }

    // Analysis Mode
    const analysisModeText = `Analysis Mode: ${
      filterValues.analysisMode === 'OVERVIEW'
        ? 'Performance Overview'
        : 'Performance Comparison'
    }`;
    filterItems.push(analysisModeText);

    // Comparison Type (only for COMPARISON mode)
    if (
      filterValues.analysisMode === 'COMPARISON' &&
      filterValues.comparisonType
    ) {
      const comparisonTypeLabel =
        filterValues.comparisonType === 'FARM'
          ? 'Farm'
          : filterValues.comparisonType === 'FLOCK'
            ? 'Flock'
            : filterValues.comparisonType === 'KANDANG'
              ? 'Kandang'
              : filterValues.comparisonType;
      filterItems.push(`Compared By: ${comparisonTypeLabel}`);
    }

    // Farm
    if (filterValues.location) {
      const locationText = Array.isArray(filterValues.location)
        ? filterValues.location.map((loc) => loc.label).join(', ')
        : filterValues.location.label;
      filterItems.push(`Farm: ${locationText || '-'}`);
    }

    // Flock
    if (
      filterValues.flock &&
      (Array.isArray(filterValues.flock)
        ? filterValues.flock.length > 0
        : filterValues.flock)
    ) {
      const flockText = Array.isArray(filterValues.flock)
        ? filterValues.flock.map((f) => f.label).join(', ')
        : filterValues.flock.label;
      filterItems.push(`Flock: ${flockText || '-'}`);
    }

    // Kandang
    if (
      filterValues.kandang &&
      (Array.isArray(filterValues.kandang)
        ? filterValues.kandang.length > 0
        : filterValues.kandang)
    ) {
      const kandangText = Array.isArray(filterValues.kandang)
        ? filterValues.kandang.map((k) => k.label).join(', ')
        : filterValues.kandang.label;
      filterItems.push(`Kandang: ${kandangText || '-'}`);
    }

    // Generated timestamp
    filterItems.push(`Dicetak: ${formatDate(new Date(), 'DD MMM YYYY HH:mm')}`);

    // Render filter items horizontally with word wrap and gray background
    const maxWidth = pageWidth - 2 * margin;
    let currentLine = '';
    const lines: string[] = [];

    // First pass: calculate all lines
    filterItems.forEach((item, index) => {
      const separator = index > 0 ? ' | ' : '';
      const testLine = currentLine + separator + item;
      const testWidth = pdf.getTextWidth(testLine);

      if (testWidth > maxWidth && currentLine !== '') {
        lines.push(currentLine);
        currentLine = item;
      } else {
        currentLine = testLine;
      }
    });

    // Add last line
    if (currentLine) {
      lines.push(currentLine);
    }

    // Calculate background dimensions
    const lineHeight = 3;
    const padding = 1;
    const backgroundHeight = lines.length * lineHeight + padding * 2;

    // Draw gray background
    pdf.setFillColor(240, 240, 240); // Light gray (RGB: 240, 240, 240)
    pdf.rect(
      margin - padding,
      yPosition - padding - 2,
      pageWidth - 2 * margin + padding * 2,
      backgroundHeight,
      'F'
    );

    // Render text on top of background
    lines.forEach((line, index) => {
      pdf.text(line, margin, yPosition);
      if (index < lines.length - 1) {
        yPosition += lineHeight;
      }
    });

    yPosition += 10;

    // Capture and add stats if available
    if (allStatsRef.current) {
      const statsContainer = allStatsRef.current.getContainerRef();
      if (statsContainer) {
        const statsImage = await toPng(statsContainer, {
          quality: 1,
          pixelRatio: 2,
        });
        const statsImgProps = pdf.getImageProperties(statsImage);
        const statsWidth = pageWidth - 2 * margin;
        const statsHeight =
          (statsImgProps.height * statsWidth) / statsImgProps.width;

        // Check if we need a new page
        if (yPosition + statsHeight > pageHeight - margin) {
          pdf.addPage();
          yPosition = margin;
        }

        pdf.addImage(
          statsImage,
          'PNG',
          margin,
          yPosition,
          statsWidth,
          statsHeight
        );
        yPosition += statsHeight + 10;
      }
    }

    if (allChartsRef.current) {
      // Get all individual chart refs
      const chartRefs = allChartsRef.current.getChartRefs();

      // Capture each chart separately and add to PDF
      for (let i = 0; i < chartRefs.length; i++) {
        const { ref: chartElement, label } = chartRefs[i];

        if (chartElement) {
          // Add chart title
          pdf.setFontSize(12);
          pdf.setFont('helvetica', 'bold');

          const chartImage = await toPng(chartElement, {
            quality: 1,
            pixelRatio: 2,
          });
          const chartImgProps = pdf.getImageProperties(chartImage);
          const chartWidth = pageWidth - 2 * margin;
          const chartHeight =
            (chartImgProps.height * chartWidth) / chartImgProps.width;

          // Calculate total height needed (title + spacing + chart)
          const titleHeight = 10;
          const totalHeight = titleHeight + chartHeight;

          // Check if chart fits on current page
          if (yPosition + totalHeight > pageHeight - margin) {
            pdf.addPage();
            yPosition = margin;
          }

          // Add title
          pdf.text(label, margin, yPosition);
          yPosition += titleHeight;

          // Add chart image
          pdf.addImage(
            chartImage,
            'PNG',
            margin,
            yPosition,
            chartWidth,
            chartHeight
          );

          // Update yPosition for next chart (add spacing between charts)
          yPosition += chartHeight + 10;
        }
      }
    }

    // Save the PDF
    const fileName = `dashboard-production-${new Date().toISOString().split('T')[0]}.pdf`;
    pdf.save(fileName);

    toast.success('PDF exported successfully!', { id: 'export-pdf' });
  } catch {
    toast.error('Failed to export PDF. Please try again.', {
      id: 'export-pdf',
    });
  } finally {
    setExporting(false);
  }
};
