import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { Inject } from '@nestjs/common';
import { ReportsHistory } from './entities/reports_history.entity';
import { AnalyticsService } from '../analytics/analytics.service';
import { Franchises } from '../franchises/entities/franchises.entity';
import * as fs from 'fs';
import * as path from 'path';
import * as PDFDocument from 'pdfkit';
import { EmailService } from '../email/email.service';

// Professional PDF Document Configuration
const createProfessionalPDFDocument = (
  title: string,
  author: string = 'Jobvumi Analytics',
) => {
  return new (PDFDocument as any)({
    size: 'A4',
    margins: {
      top: 50,
      bottom: 50,
      left: 50,
      right: 50,
    },
    info: {
      Title: title,
      Author: author,
      Subject: 'Professional Report',
      Keywords: 'report, analytics, professional',
      CreationDate: new Date(),
    },
  });
};
@Injectable()
export class ReportsHistoryService {
  constructor(
    @InjectRepository(ReportsHistory)
    private reportsHistoryRepository: Repository<ReportsHistory>,
    @InjectRepository(Franchises)
    private franchisesRepository: Repository<Franchises>,
    private analyticsService: AnalyticsService,
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    private readonly emailService: EmailService,
  ) {}

  async generateReport(data: {
    type: string;
    dateRange: { start: Date; end: Date };
    createdBy: number;
    franchiseId: number; // Make franchiseId required
  }) {
    try {
      // Create reports directory if it doesn't exist
      const reportsDir = path.join(process.cwd(), 'uploads', 'reports');
      if (!fs.existsSync(reportsDir)) {
        fs.mkdirSync(reportsDir, { recursive: true });
      }

      // Generate unique filename
      const timestamp = new Date().getTime();
      const filename = `${data.type}_${timestamp}.pdf`;
      const filePath = path.join(reportsDir, filename);

      // Create professional PDF document
      const doc = createProfessionalPDFDocument(
        `${data.type.toUpperCase()} Analytics Report`,
      );

      // Add professional content to PDF first
      await this.addProfessionalReportContent(
        doc,
        data.type,
        data.franchiseId,
        data.dateRange,
      );

      // End the document
      doc.end();

      // Create write stream and pipe the document
      const writeStream = fs.createWriteStream(filePath);
      doc.pipe(writeStream);

      return new Promise((resolve, reject) => {
        writeStream.on('finish', async () => {
          try {
            // Verify file was created
            if (!fs.existsSync(filePath)) {
              reject({
                success: false,
                error: 'PDF file was not created successfully',
              });
              return;
            }

            // Store relative path for web access
            const relativePath = `uploads/reports/${filename}`;

            // Save report record to database
            const report = this.reportsHistoryRepository.create({
              type: data.type as any,
              file_path: relativePath, // Store relative path instead of absolute
              created_by: data.createdBy,
              franchise_id: data.franchiseId,
              date_range_start: data.dateRange.start,
              date_range_end: data.dateRange.end,
              status: 'generated' as any,
            });

            const savedReport =
              await this.reportsHistoryRepository.save(report);

            resolve({
              success: true,
              data: {
                reportId: savedReport.id,
                filePath: relativePath,
                filename: filename,
              },
            });
          } catch (error: any) {
            reject({
              success: false,
              error: error.message,
            });
          }
        });

        writeStream.on('error', (error: any) => {
          reject({
            success: false,
            error: error.message,
          });
        });
      });
    } catch (error: any) {
      return {
        success: false,
        error: error.message,
      };
    }
  }

  private async addProfessionalReportContent(
    doc: PDFKit.PDFDocument,
    type: string,
    franchiseId?: number,
    dateRange?: { start: Date; end: Date },
  ) {
    // Professional color scheme
    const colors = {
      primary: '#2563eb',
      secondary: '#64748b',
      success: '#10b981',
      warning: '#f59e0b',
      danger: '#ef4444',
      light: '#f8fafc',
      dark: '#1e293b',
      border: '#e2e8f0',
    };

    // Helper function to draw rounded rectangle
    const drawRoundedRect = (
      x: number,
      y: number,
      width: number,
      height: number,
      radius: number,
      fillColor?: string,
    ) => {
      doc.save();
      if (fillColor) {
        doc.fillColor(fillColor);
      }
      doc.roundedRect(x, y, width, height, radius);
      if (fillColor) {
        doc.fill();
      } else {
        doc.stroke();
      }
      doc.restore();
    };

    // Helper function to draw gradient background
    const drawGradientBackground = () => {
      const gradient = doc.linearGradient(0, 0, 0, 100);
      gradient.stop(0, colors.primary);
      gradient.stop(1, '#1d4ed8');
      doc.rect(0, 0, doc.page.width, 100).fill(gradient);
    };

    // Helper function to add section header
    const addSectionHeader = (text: string, y: number) => {
      doc.save();
      doc.fontSize(18);
      doc.font('Helvetica-Bold');
      doc.fillColor(colors.dark);
      doc.text(text, 50, y);

      // Add underline
      doc.strokeColor(colors.primary);
      doc.lineWidth(2);
      doc.moveTo(50, y + 25);
      doc.lineTo(200, y + 25);
      doc.stroke();
      doc.restore();
      return y + 40;
    };

    // Helper function to add KPI card
    const addKPICard = (
      title: string,
      value: string,
      subtitle: string,
      x: number,
      y: number,
      width: number,
      height: number,
      color: string,
    ) => {
      // Card background
      drawRoundedRect(x, y, width, height, 8, colors.light);
      drawRoundedRect(x, y, width, height, 8);

      // Title
      doc.save();
      doc.fontSize(12);
      doc.font('Helvetica');
      doc.fillColor(colors.secondary);
      doc.text(title, x + 15, y + 15);

      // Value
      doc.fontSize(24);
      doc.font('Helvetica-Bold');
      doc.fillColor(color);
      doc.text(value, x + 15, y + 35);

      // Subtitle
      doc.fontSize(10);
      doc.font('Helvetica');
      doc.fillColor(colors.secondary);
      doc.text(subtitle, x + 15, y + 65);
      doc.restore();
    };

    // Helper function to create data table
    const createDataTable = (
      headers: string[],
      data: any[][],
      startY: number,
      tableWidth: number,
    ) => {
      const rowHeight = 25;
      const colWidth = tableWidth / headers.length;

      // Table header
      doc.save();
      doc.fillColor(colors.primary);
      doc.strokeColor(colors.border);
      doc.lineWidth(1);

      headers.forEach((header, index) => {
        const x = 50 + index * colWidth;
        doc.rect(x, startY, colWidth, rowHeight).fill();
        doc.fillColor('white');
        doc.fontSize(10);
        doc.font('Helvetica-Bold');
        doc.text(header, x + 5, startY + 8);
        doc.fillColor(colors.primary);
      });

      // Table data
      data.forEach((row, rowIndex) => {
        const y = startY + rowHeight + rowIndex * rowHeight;

        row.forEach((cell, colIndex) => {
          const x = 50 + colIndex * colWidth;
          doc.rect(x, y, colWidth, rowHeight).stroke();
          doc.fillColor(colors.dark);
          doc.fontSize(9);
          doc.font('Helvetica');
          doc.text(cell.toString(), x + 5, y + 8);
        });
      });
      doc.restore();

      return startY + rowHeight + data.length * rowHeight + 20;
    };

    // Helper function to create bar chart
    const createBarChart = (
      data: any[],
      title: string,
      startY: number,
      chartWidth: number,
      chartHeight: number,
    ) => {
      const margin = 70;
      const chartAreaWidth = chartWidth - margin * 2;
      const chartAreaHeight = chartHeight - margin * 2;

      // Chart background with better contrast
      drawRoundedRect(50, startY, chartWidth, chartHeight, 8, '#f8f9fa');

      // Title with better visibility and more space
      doc.save();
      doc.fontSize(16);
      doc.font('Helvetica-Bold');
      doc.fillColor(colors.dark);
      doc.text(title, 50 + chartWidth / 2, startY + 35, { align: 'center' });
      doc.restore();

      if (data.length === 0) {
        doc.save();
        doc.fontSize(12);
        doc.fillColor(colors.secondary);
        doc.text(
          'No data available',
          50 + chartWidth / 2,
          startY + chartHeight / 2,
          { align: 'center' },
        );
        doc.restore();
        return startY + chartHeight + 20;
      }

      // Find max value for scaling
      const maxValue = Math.max(...data.map((d) => d.value));
      const barWidth = chartAreaWidth / data.length;

      // Draw bars with better spacing and visibility
      data.forEach((item, index) => {
        const x = 50 + margin + index * barWidth + barWidth * 0.15;
        const barHeight = (item.value / maxValue) * chartAreaHeight;
        const y = startY + margin + chartAreaHeight - barHeight;
        const width = barWidth * 0.7;

        // Bar with gradient effect
        doc.save();
        doc.fillColor(colors.primary);
        doc.rect(x, y, width, barHeight).fill();

        // Value label on top of bar with better visibility
        doc.fillColor(colors.dark);
        doc.fontSize(10);
        doc.font('Helvetica-Bold');
        const valueText = item.value.toString();
        const valueWidth = doc.widthOfString(valueText);
        doc.text(valueText, x + width / 2 - valueWidth / 2, y - 8);

        // Label below chart with better spacing
        doc.fontSize(9);
        doc.font('Helvetica');
        doc.fillColor(colors.secondary);
        const labelText = item.label;
        const labelWidth = doc.widthOfString(labelText);
        doc.text(
          labelText,
          x + width / 2 - labelWidth / 2,
          startY + margin + chartAreaHeight + 15,
        );
        doc.restore();
      });

      // Add chart border for better definition
      doc.save();
      doc.strokeColor(colors.light);
      doc.lineWidth(1);
      doc.rect(50, startY, chartWidth, chartHeight);
      doc.restore();

      return startY + chartHeight + 50;
    };

    // Page 1: Cover Page
    let currentY = 50;

    // Header with gradient
    drawGradientBackground();

    // Logo/Title area
    doc.save();
    doc.fillColor('white');
    doc.fontSize(32);
    doc.font('Helvetica-Bold');
    doc.text('Jobvumi Analytics', 50, 30);
    doc.fontSize(16);
    doc.font('Helvetica');
    doc.text('Professional Analytics Report', 50, 60);
    doc.restore();

    currentY = 150;

    // Report details
    doc.save();
    doc.fontSize(20);
    doc.font('Helvetica-Bold');
    doc.fillColor(colors.dark);
    doc.text(`${type.toUpperCase()} REPORT`, 50, currentY);
    currentY += 40;

    doc.fontSize(12);
    doc.font('Helvetica');
    doc.fillColor(colors.secondary);
    doc.text(
      `Generated: ${new Date().toLocaleDateString('en-US', {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
      })}`,
      50,
      currentY,
    );
    currentY += 20;

    if (dateRange) {
      doc.text(
        `Period: ${dateRange.start.toLocaleDateString()} - ${dateRange.end.toLocaleDateString()}`,
        50,
        currentY,
      );
      currentY += 20;
    }

    // Franchise information
    if (franchiseId) {
      try {
        const franchise = await this.franchisesRepository.findOne({
          where: { id: franchiseId },
          select: ['franchiseName'],
        });
        const franchiseName = franchise?.franchiseName || `ID: ${franchiseId}`;
        doc.text(`Franchise: ${franchiseName}`, 50, currentY);
        currentY += 20;
      } catch (error) {
        doc.text(`Franchise ID: ${franchiseId}`, 50, currentY);
        currentY += 20;
      }
    }
    doc.restore();

    // Add page number
    doc.save();
    doc.fontSize(10);
    doc.fillColor(colors.secondary);
    doc.text('Page 1', doc.page.width - 100, doc.page.height - 30);
    doc.restore();

    // Start content on the same page after cover
    currentY = 250;

    // Get analytics data
    let jobData = {};
    let applicationData = {};
    let companyData = {};
    let userData = {};

    try {
      const jobResult = await this.analyticsService.getJobAnalytics(
        30,
        franchiseId,
      );
      jobData = jobResult || {};
    } catch (error) {
      // Handle error silently
    }

    try {
      const appResult = await this.analyticsService.getApplicationAnalytics(
        30,
        franchiseId,
      );
      applicationData = appResult || {};
    } catch (error) {
      // Handle error silently
    }

    try {
      const companyResult =
        await this.analyticsService.getCompanyAnalytics(franchiseId);
      companyData = companyResult || {};
    } catch (error) {
      // Handle error silently
    }

    try {
      const userResult = await this.analyticsService.getUserAnalytics(
        30,
        franchiseId,
      );
      userData = userResult || {};
    } catch (error) {
      // Handle error silently
    }

    // Executive Summary Section
    currentY = addSectionHeader('Executive Summary', currentY);

    // KPI Cards
    const kpiCards = [
      {
        title: 'Total Jobs',
        value: (jobData as any).totalJobs?.toString() || '0',
        subtitle: 'Active job postings',
        color: colors.primary,
      },
      {
        title: 'Applications',
        value: (applicationData as any).totalApplications?.toString() || '0',
        subtitle: 'Total applications received',
        color: colors.success,
      },
      {
        title: 'Companies',
        value: (companyData as any).activeCompanies?.toString() || '0',
        subtitle: 'Active companies',
        color: colors.warning,
      },
      {
        title: 'Users',
        value: (userData as any).totalUsers?.toString() || '0',
        subtitle: 'Registered users',
        color: colors.danger,
      },
    ];

    // Draw KPI cards in a 2x2 grid
    kpiCards.forEach((kpi, index) => {
      const row = Math.floor(index / 2);
      const col = index % 2;
      const x = 50 + col * 250;
      const y = currentY + row * 100;
      addKPICard(kpi.title, kpi.value, kpi.subtitle, x, y, 230, 80, kpi.color);
    });

    currentY += 200;

    // Add new page for detailed analytics
    doc.addPage();
    currentY = 50;

    // Job Analytics Section
    if (
      type.toLowerCase() === 'job' ||
      type.toLowerCase() === 'comprehensive' ||
      type.toLowerCase() === 'finance'
    ) {
      currentY = addSectionHeader('Job Analytics', currentY);

      // Job trends chart
      if ((jobData as any).jobTrends && (jobData as any).jobTrends.length > 0) {
        const chartData = (jobData as any).jobTrends
          .slice(0, 6)
          .map((trend: any) => ({
            label: new Date(trend.year, trend.month - 1).toLocaleDateString(
              'en-US',
              { month: 'short' },
            ),
            value: trend.count,
          }));

        currentY = createBarChart(
          chartData,
          'Job Posting Trends (Last 6 Months)',
          currentY,
          500,
          200,
        );
      }

      // Job performance table
      if ((jobData as any).jobTrends && (jobData as any).jobTrends.length > 0) {
        const tableHeaders = ['Month', 'Jobs Posted', 'Growth'];
        const tableData = (jobData as any).jobTrends
          .slice(0, 6)
          .map((trend: any, index: number, array: any[]) => {
            const monthName = new Date(
              trend.year,
              trend.month - 1,
            ).toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
            const growth =
              index > 0
                ? (
                    ((trend.count - array[index - 1].count) /
                      array[index - 1].count) *
                    100
                  ).toFixed(1) + '%'
                : 'N/A';
            return [monthName, trend.count.toString(), growth];
          });

        currentY = createDataTable(tableHeaders, tableData, currentY, 500);
      }
    }

    // Application Analytics Section
    if (
      type.toLowerCase() === 'application' ||
      type.toLowerCase() === 'comprehensive' ||
      type.toLowerCase() === 'finance'
    ) {
      if (currentY > 600) {
        doc.addPage();
        currentY = 50;
      }

      currentY = addSectionHeader('Application Analytics', currentY);

      // Applications per job chart
      if (
        (applicationData as any).applicationsPerJob &&
        (applicationData as any).applicationsPerJob.length > 0
      ) {
        const chartData = (applicationData as any).applicationsPerJob
          .slice(0, 8)
          .map((app: any) => ({
            label:
              app.jobTitle.length > 15
                ? app.jobTitle.substring(0, 15) + '...'
                : app.jobTitle,
            value: app.applicationCount,
          }));

        currentY = createBarChart(
          chartData,
          'Applications per Job (Top 8)',
          currentY,
          500,
          200,
        );
      }

      // Application metrics
      doc.save();
      doc.fontSize(14);
      doc.font('Helvetica-Bold');
      doc.fillColor(colors.dark);
      doc.text('Key Metrics:', 50, currentY);
      currentY += 25;

      doc.fontSize(12);
      doc.font('Helvetica');
      doc.fillColor(colors.secondary);
      doc.text(
        `• Total Applications: ${(applicationData as any).totalApplications || 0}`,
        70,
        currentY,
      );
      currentY += 20;
      doc.text(
        `• Conversion Rate: ${(applicationData as any).conversionRate ? `${(applicationData as any).conversionRate.toFixed(1)}%` : '0%'}`,
        70,
        currentY,
      );
      currentY += 20;
      doc.text(
        `• Average Applications per Job: ${(applicationData as any).applicationsPerJob ? Math.round((applicationData as any).totalApplications / (applicationData as any).applicationsPerJob.length) : 0}`,
        70,
        currentY,
      );
      currentY += 40;
      doc.restore();
    }

    // Company Analytics Section
    if (
      type.toLowerCase() === 'company' ||
      type.toLowerCase() === 'comprehensive' ||
      type.toLowerCase() === 'finance'
    ) {
      if (currentY > 600) {
        doc.addPage();
        currentY = 50;
      }

      currentY = addSectionHeader('Company Analytics', currentY);

      // Company status distribution
      const companyChartData = [
        { label: 'Active', value: (companyData as any).activeCompanies || 0 },
        {
          label: 'Inactive',
          value: (companyData as any).inactiveCompanies || 0,
        },
      ];

      currentY = createBarChart(
        companyChartData,
        'Company Status Distribution',
        currentY,
        500,
        200,
      );

      // Company metrics
      doc.save();
      doc.fontSize(14);
      doc.font('Helvetica-Bold');
      doc.fillColor(colors.dark);
      doc.text('Company Metrics:', 50, currentY);
      currentY += 25;

      doc.fontSize(12);
      doc.font('Helvetica');
      doc.fillColor(colors.secondary);
      doc.text(
        `• Active Companies: ${(companyData as any).activeCompanies || 0}`,
        70,
        currentY,
      );
      currentY += 20;
      doc.text(
        `• Inactive Companies: ${(companyData as any).inactiveCompanies || 0}`,
        70,
        currentY,
      );
      currentY += 20;
      doc.text(
        `• Total Companies: ${((companyData as any).activeCompanies || 0) + ((companyData as any).inactiveCompanies || 0)}`,
        70,
        currentY,
      );
      currentY += 40;
      doc.restore();
    }

    // User Analytics Section
    if (
      type.toLowerCase() === 'user' ||
      type.toLowerCase() === 'comprehensive' ||
      type.toLowerCase() === 'finance'
    ) {
      if (currentY > 600) {
        doc.addPage();
        currentY = 50;
      }

      currentY = addSectionHeader('User Analytics', currentY);

      // User growth chart
      if (
        (userData as any).newUsersPerMonth &&
        (userData as any).newUsersPerMonth.length > 0
      ) {
        const chartData = (userData as any).newUsersPerMonth
          .slice(0, 6)
          .map((user: any) => ({
            label: new Date(user.year, user.month - 1).toLocaleDateString(
              'en-US',
              { month: 'short' },
            ),
            value: user.count,
          }));

        currentY = createBarChart(
          chartData,
          'New User Registrations (Last 6 Months)',
          currentY,
          500,
          180,
        );
      }

      // User metrics
      doc.save();
      doc.fontSize(14);
      doc.font('Helvetica-Bold');
      doc.fillColor(colors.dark);
      doc.text('User Metrics:', 50, currentY);
      currentY += 20;

      doc.fontSize(12);
      doc.font('Helvetica');
      doc.fillColor(colors.secondary);
      doc.text(
        `• Total Users: ${(userData as any).totalUsers || 0}`,
        70,
        currentY,
      );
      currentY += 15;
      doc.text(
        `• New Users (This Month): ${(userData as any).newUsersThisMonth || 0}`,
        70,
        currentY,
      );
      currentY += 15;
      doc.text(
        `• Active Users: ${(userData as any).activeUsers || 0}`,
        70,
        currentY,
      );
      currentY += 25;
      doc.restore();
    }

    // Recommendations Section
    if (currentY > 500) {
      doc.addPage();
      currentY = 50;
    }

    currentY = addSectionHeader('Recommendations & Insights', currentY);

    doc.save();
    doc.fontSize(12);
    doc.font('Helvetica');
    doc.fillColor(colors.dark);

    const recommendations = [
      '• Monitor job posting trends to optimize recruitment strategies',
      '• Focus on high-performing job categories to increase applications',
      '• Engage with inactive companies to boost platform activity',
      '• Implement user engagement campaigns to increase registrations',
      '• Regular analytics review for data-driven decision making',
    ];

    recommendations.forEach((rec, index) => {
      doc.text(rec, 50, currentY + index * 20);
    });

    currentY += recommendations.length * 20 + 40;
    doc.restore();

    // Footer with page numbers - only add to pages that exist
    const totalPages = doc.bufferedPageRange().count;
    if (totalPages > 0) {
      for (let i = 0; i < totalPages; i++) {
        try {
          doc.switchToPage(i);
          doc.save();
          doc.fontSize(10);
          doc.fillColor(colors.secondary);
          doc.text(
            `Page ${i + 1} of ${totalPages}`,
            doc.page.width - 100,
            doc.page.height - 30,
          );
          doc.text('Generated by Jobvumi Analytics', 50, doc.page.height - 30);
          doc.restore();
        } catch (error) {
          // Skip pages that don't exist
          // console.log(`Skipping page ${i} - page doesn't exist`);
        }
      }
    }
  }

  private async addReportContent(
    doc: PDFKit.PDFDocument,
    type: string,
    franchiseId?: number,
  ) {
    // Simple text-only styling
    const margin = 50;

    // Set consistent margins
    doc.page.margins = {
      top: margin,
      bottom: margin,
      left: margin,
      right: margin,
    };

    // Large title
    doc.fontSize(24).text('Jobvumi Analytics Report', { align: 'center' });

    doc.moveDown(2);

    // Report type
    doc.fontSize(16).text(`${type.toUpperCase()} REPORT`, { align: 'center' });

    doc.moveDown(1);

    // Generation timestamp
    doc.fontSize(12).text(
      `Generated: ${new Date().toLocaleDateString('en-US', {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
      })}`,
      { align: 'center' },
    );

    // Franchise information if available
    if (franchiseId) {
      try {
        const franchise = await this.franchisesRepository.findOne({
          where: { id: franchiseId },
          select: ['franchiseName'],
        });
        const franchiseName = franchise?.franchiseName || `ID: ${franchiseId}`;
        doc
          .fontSize(12)
          .text(`Franchise: ${franchiseName}`, { align: 'center' });
      } catch (error) {
        doc
          .fontSize(12)
          .text(`Franchise ID: ${franchiseId}`, { align: 'center' });
      }
    }

    doc.moveDown(3);

    try {
      // Get analytics data with error handling
      let jobData = {};
      let applicationData = {};
      let companyData = {};
      let userData = {};

      try {
        const jobResult = await this.analyticsService.getJobAnalytics(
          30,
          franchiseId,
        );
        jobData = jobResult || {};
      } catch (error) {
        // console.log('Error getting job analytics:', error);
      }

      try {
        const appResult = await this.analyticsService.getApplicationAnalytics(
          30,
          franchiseId,
        );
        applicationData = appResult || {};
      } catch (error) {
        // console.log('Error getting application analytics:', error);
      }

      try {
        const companyResult =
          await this.analyticsService.getCompanyAnalytics(franchiseId);
        companyData = companyResult || {};
      } catch (error) {
        // console.log('Error getting company analytics:', error);
      }

      try {
        const userResult = await this.analyticsService.getUserAnalytics(
          30,
          franchiseId,
        );
        userData = userResult || {};
      } catch (error) {
        // console.log('Error getting user analytics:', error);
      }

      // Add content based on report type
      switch (type.toLowerCase()) {
        case 'job':
          this.addJobReportContent(doc, jobData);
          break;
        case 'company':
          this.addCompanyReportContent(doc, companyData);
          break;
        case 'user':
          this.addUserReportContent(doc, userData);
          break;
        case 'finance':
        case 'comprehensive':
          this.addComprehensiveReportContent(doc, {
            jobs: jobData,
            applications: applicationData,
            companies: companyData,
            users: userData,
          });
          break;
        default:
          this.addComprehensiveReportContent(doc, {
            jobs: jobData,
            applications: applicationData,
            companies: companyData,
            users: userData,
          });
      }
    } catch (error: any) {
      doc
        .fontSize(14)
        .text('Error generating report content: ' + error.message);
    }
  }

  private addJobReportContent(doc: PDFKit.PDFDocument, data: any) {
    // Section header
    doc.fontSize(16).text('Job Analytics Overview');
    doc.moveDown(1.5);

    // KPI data
    doc.fontSize(14).text(`Total Jobs: ${data.totalJobs || 0}`);
    doc.moveDown(0.5);
    doc.fontSize(14).text(`Active Jobs: ${data.activeJobs || 0}`);
    doc.moveDown(1.5);

    if (data.jobTrends && data.jobTrends.length > 0) {
      doc.fontSize(14).text('Job Trends (Last 6 Months)');
      doc.moveDown(1);

      // Simple table format
      doc.fontSize(12).text('Period\t\tTotal Jobs');
      doc.fontSize(12).text('-------------------');
      doc.moveDown(0.5);

      data.jobTrends.forEach((trend: any) => {
        const monthName = new Date(
          trend.year,
          trend.month - 1,
        ).toLocaleDateString('en-US', {
          month: 'short',
          year: 'numeric',
        });
        doc.fontSize(12).text(`${monthName}\t\t${trend.count}`);
      });
    }

    doc.moveDown(2);
  }

  private addApplicationReportContent(doc: PDFKit.PDFDocument, data: any) {
    // Section header
    doc.fontSize(16).text('Application Analytics');
    doc.moveDown(1.5);

    // KPI data
    doc.fontSize(14).text(`Total Applications: ${data.totalApplications || 0}`);
    doc.moveDown(0.5);
    doc.fontSize(14).text(`Conversion Rate: ${data.conversionRate || 0}%`);
    doc.moveDown(1.5);

    if (data.applicationsPerJob && data.applicationsPerJob.length > 0) {
      doc.fontSize(14).text('Top Performing Jobs');
      doc.moveDown(1);

      // Simple table format
      doc.fontSize(12).text('Rank\tJob Title\t\tApplications');
      doc.fontSize(12).text('----------------------------------------');
      doc.moveDown(0.5);

      data.applicationsPerJob
        .slice(0, 10)
        .forEach((job: any, index: number) => {
          const jobTitle =
            job.jobTitle.length > 30
              ? job.jobTitle.substring(0, 30) + '...'
              : job.jobTitle;
          doc
            .fontSize(12)
            .text(`${index + 1}\t${jobTitle}\t\t${job.applicationCount}`);
        });
    }

    doc.moveDown(2);
  }

  private addCompanyReportContent(doc: PDFKit.PDFDocument, data: any) {
    // Section header
    doc.fontSize(16).text('Company Analytics');
    doc.moveDown(1.5);

    // KPI data
    doc.fontSize(14).text(`Active Companies: ${data.activeCompanies || 0}`);
    doc.moveDown(0.5);
    doc.fontSize(14).text(`Inactive Companies: ${data.inactiveCompanies || 0}`);
    doc.moveDown(1.5);

    // Company distribution
    doc.fontSize(14).text('Company Status Distribution');
    doc.moveDown(1);

    const activeCompanies = data.activeCompanies || 0;
    const inactiveCompanies = data.inactiveCompanies || 0;
    const total = activeCompanies + inactiveCompanies;

    if (total > 0) {
      doc
        .fontSize(12)
        .text(
          `Active: ${activeCompanies} (${((activeCompanies / total) * 100).toFixed(1)}%)`,
        );
      doc.moveDown(0.5);
      doc
        .fontSize(12)
        .text(
          `Inactive: ${inactiveCompanies} (${((inactiveCompanies / total) * 100).toFixed(1)}%)`,
        );
    } else {
      doc.fontSize(12).text('No company data available');
    }

    doc.moveDown(2);
  }

  private addUserReportContent(doc: PDFKit.PDFDocument, data: any) {
    // Section header
    doc.fontSize(16).text('User Analytics');
    doc.moveDown(1.5);

    // KPI data
    doc.fontSize(14).text(`Active Users: ${data.activeUsers || 0}`);
    doc.moveDown(1.5);

    if (data.newUsersPerMonth && data.newUsersPerMonth.length > 0) {
      doc.fontSize(14).text('User Growth Trends');
      doc.moveDown(1);

      // Simple table format
      doc.fontSize(12).text('Period\t\tTotal Users');
      doc.fontSize(12).text('-------------------');
      doc.moveDown(0.5);

      data.newUsersPerMonth.forEach((trend: any) => {
        const monthName = new Date(
          trend.year,
          trend.month - 1,
        ).toLocaleDateString('en-US', {
          month: 'short',
          year: 'numeric',
        });
        doc.fontSize(12).text(`${monthName}\t\t${trend.count}`);
      });
    }

    doc.moveDown(2);
  }

  private addComprehensiveReportContent(doc: PDFKit.PDFDocument, data: any) {
    // Executive Summary
    doc.fontSize(16).text('Executive Summary');
    doc.moveDown(1);
    doc
      .fontSize(12)
      .text(
        'This comprehensive report provides detailed insights into franchise performance across jobs, applications, companies, and user engagement metrics.',
      );
    doc.moveDown(2);

    // Jobs section
    this.addJobReportContent(doc, data.jobs);
    doc.moveDown(1);

    // Applications section
    this.addApplicationReportContent(doc, data.applications);
    doc.moveDown(1);

    // Companies section
    this.addCompanyReportContent(doc, data.companies);
    doc.moveDown(1);

    // Users section
    this.addUserReportContent(doc, data.users);

    // Footer
    this.addFooter(doc);
  }

  private addFinanceReportContent(doc: PDFKit.PDFDocument, data: any) {
    this.addComprehensiveReportContent(doc, data);
  }

  private addFooter(doc: PDFKit.PDFDocument) {
    doc.moveDown(3);

    // Footer content
    doc
      .fontSize(12)
      .text('Generated by Jobvumi Analytics Platform', { align: 'center' });

    doc.moveDown(0.5);

    doc.fontSize(10).text(
      `Generated on ${new Date().toLocaleDateString('en-US', {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
      })}`,
      { align: 'center' },
    );

    doc.moveDown(0.5);

    doc
      .fontSize(8)
      .text(
        'This report contains confidential information. Please handle with care.',
        { align: 'center' },
      );
  }

  async getAllReports() {
    try {
      // console.log('Getting all reports from database...');

      // Try simple find first
      // const reportsCount = await this.reportsHistoryRepository.count();
      // console.log('Total reports count:', reportsCount);

      const reports = await this.reportsHistoryRepository.find({
        order: { created_at: 'DESC' },
      });

      // console.log('Found reports:', reports.length);

      const result = {
        success: true,
        data: reports,
      };

      return result;
    } catch (error: any) {
      console.error('Error getting all reports:', error);
      return {
        success: false,
        error: error.message,
      };
    }
  }

  async getReportsByFranchiseId(franchiseId: number) {
    try {
      // console.log('Getting reports for franchise ID:', franchiseId);

      const reports = await this.reportsHistoryRepository.find({
        where: { franchise_id: franchiseId },
        order: { created_at: 'DESC' },
      });

      // console.log('Found reports for franchise:', reports.length);

      const result = {
        success: true,
        data: reports,
      };

      return result;
    } catch (error: any) {
      console.error('Error getting reports by franchise ID:', error);
      return {
        success: false,
        error: error.message,
      };
    }
  }

  async getReportById(id: number, franchiseId?: number) {
    try {
      const whereClause: any = { id };

      // If franchiseId is provided, filter by it to ensure franchise isolation
      if (franchiseId) {
        whereClause.franchise_id = franchiseId;
      }

      const report = await this.reportsHistoryRepository.findOne({
        where: whereClause,
      });

      if (!report) {
        return {
          success: false,
          error: 'Report not found',
        };
      }

      return {
        success: true,
        data: report,
      };
    } catch (error: any) {
      return {
        success: false,
        error: error.message,
      };
    }
  }

  async downloadReport(id: number, franchiseId?: number) {
    try {
      const whereClause: any = { id };

      // If franchiseId is provided, filter by it to ensure franchise isolation
      if (franchiseId) {
        whereClause.franchise_id = franchiseId;
      }

      const report = await this.reportsHistoryRepository.findOne({
        where: whereClause,
      });

      if (!report) {
        return {
          success: false,
          error: 'Report not found',
        };
      }

      // Construct full file path from relative path
      const fullFilePath = path.join(process.cwd(), report.file_path);

      if (!fs.existsSync(fullFilePath)) {
        return {
          success: false,
          error: 'Report file not found',
        };
      }

      const fileBuffer = fs.readFileSync(fullFilePath);

      // Generate a proper filename based on report type and date
      const reportDate = report.created_at
        ? new Date(report.created_at)
        : new Date();
      const dateString = reportDate.toISOString().split('T')[0]; // YYYY-MM-DD format
      const reportType = report.type
        ? report.type.charAt(0).toUpperCase() + report.type.slice(1)
        : 'Report';
      const filename = `${reportType}_Analytics_Report_${dateString}.pdf`;

      return {
        success: true,
        data: {
          fileBuffer,
          filename,
          contentType: 'application/pdf',
        },
      };
    } catch (error: any) {
      return {
        success: false,
        error: error.message,
      };
    }
  }

  async emailReport(data: {
    reportId: number;
    email: string;
    franchiseId?: number;
  }) {
    try {
      const whereClause: any = { id: data.reportId };

      // If franchiseId is provided, filter by it to ensure franchise isolation
      if (data.franchiseId) {
        whereClause.franchise_id = data.franchiseId;
      }

      const report = await this.reportsHistoryRepository.findOne({
        where: whereClause,
      });

      if (!report) {
        return {
          success: false,
          error: 'Report not found',
        };
      }

      // Get the PDF file path
      const pdfPath = report.file_path;
      if (!pdfPath || !fs.existsSync(pdfPath)) {
        return {
          success: false,
          error: 'Report PDF file not found',
        };
      }

      // Read the PDF file
      const pdfBuffer = fs.readFileSync(pdfPath);
      const pdfBase64 = pdfBuffer.toString('base64');

      const templateName = 'franchise_report';
      const toName = data.email.split('@')[0];
      const context = {
        recipient_name: toName,
      };
      
      const attachments = [
        {
          content: pdfBase64,
          name: `franchise_report_${report.id}.pdf`,
        },
      ];

      const success = await this.emailService.sendTemplateEmail(
        templateName,
        data.email,
        toName,
        context,
        attachments
      );

      if (success) {
        // Update report status to 'emailed'
        await this.reportsHistoryRepository.update(report.id, {
          status: 'emailed',
        });

        return {
          success: true,
          message: 'Report email sent successfully',
        };
      } else {
        return {
          success: false,
          error: 'Failed to send report email',
        };
      }
    } catch (error: any) {
      return {
        success: false,
        error: error.message,
      };
    }
  }
}
