import jsPDF from 'jspdf';
import { autoTable } from 'jspdf-autotable'
import ScanModel from '../models/Scan';
import QRCodeModel from '../models/QrCode';
import UserModel from '../models/User';
import AuditLogModel from '../models/AuditLog';

export class PDFGenerationService {

    /**
     * Generate admin business report PDF
     */
    static async generateAdminBusinessReport(data: any): Promise<Buffer> {
        const doc = new jsPDF();

        // Color scheme - using 3-element tuples for proper spread operations
        const colors = {
            primary: [30, 58, 138] as [number, number, number],      // Dark blue
            secondary: [59, 130, 246] as [number, number, number],   // Light blue
            accent: [16, 185, 129] as [number, number, number],      // Green
            text: [31, 41, 55] as [number, number, number],          // Dark gray
            lightGray: [243, 244, 246] as [number, number, number],  // Light gray
            white: [255, 255, 255] as [number, number, number]
        };

        let currentY = 20;

        // ===== HEADER SECTION =====
        // Header background
        doc.setFillColor(colors.primary[0], colors.primary[1], colors.primary[2]);
        doc.rect(0, 0, doc.internal.pageSize.width, 60, 'F');

        // Accent bar
        doc.setFillColor(colors.accent[0], colors.accent[1], colors.accent[2]);
        doc.rect(0, 60, doc.internal.pageSize.width, 3, 'F');

        // Title
        doc.setFontSize(24);
        doc.setFont('helvetica', 'bold');
        doc.setTextColor(colors.white[0], colors.white[1], colors.white[2]);
        doc.text('Quick Connect', 20, 30);

        doc.setFontSize(16);
        doc.setFont('helvetica', 'normal');
        doc.text('Business Performance Report', 20, 42);

        // Metadata
        doc.setFontSize(9);
        doc.setTextColor(220, 220, 220);
        doc.text(`Generated: ${data.generatedAt}`, 20, 52);
        doc.text(`Period: ${data.dateRange}`, doc.internal.pageSize.width - 20, 52, { align: 'right' });

        currentY = 75;

        // ===== KEY METRICS SECTION =====
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(14);
        doc.setTextColor(colors.primary[0], colors.primary[1], colors.primary[2]);
        doc.text('Key Performance Metrics', 20, currentY);

        currentY += 10;

        // Metrics cards layout (2x2 grid)
        const metrics = [
            { label: 'Total Scans', value: data.totalScans.toString(), icon: '📊' },
            { label: 'Active Users', value: data.activeUsers.toString(), icon: '👥' },
            { label: 'QR Codes Created', value: data.qrCodes.toString(), icon: '🔲' },
            { label: 'Avg Daily Scans', value: data.averageDailyScans.toString(), icon: '📈' }
        ];

        const cardWidth = 85;
        const cardHeight = 28;
        const cardSpacing = 5;

        metrics.forEach((metric, index) => {
            const col = index % 2;
            const row = Math.floor(index / 2);
            const x = 20 + (col * (cardWidth + cardSpacing));
            const y = currentY + (row * (cardHeight + cardSpacing));

            // Card background
            doc.setFillColor(colors.lightGray[0], colors.lightGray[1], colors.lightGray[2]);
            doc.roundedRect(x, y, cardWidth, cardHeight, 3, 3, 'F');

            // Card border
            doc.setDrawColor(colors.secondary[0], colors.secondary[1], colors.secondary[2]);
            doc.setLineWidth(0.5);
            doc.roundedRect(x, y, cardWidth, cardHeight, 3, 3, 'S');

            // Metric label
            doc.setFontSize(9);
            doc.setFont('helvetica', 'normal');
            doc.setTextColor(colors.text[0], colors.text[1], colors.text[2]);
            doc.text(metric.label, x + 5, y + 8);

            // Metric value
            doc.setFontSize(18);
            doc.setFont('helvetica', 'bold');
            doc.setTextColor(colors.primary[0], colors.primary[1], colors.primary[2]);
            doc.text(metric.value, x + 5, y + 21);
        });

        currentY += (2 * (cardHeight + cardSpacing)) + 15;

        // Section divider
        doc.setDrawColor(colors.lightGray[0], colors.lightGray[1], colors.lightGray[2]);
        doc.setLineWidth(1);
        doc.line(20, currentY, doc.internal.pageSize.width - 20, currentY);
        currentY += 10;

        // ===== TOP QR CODE SECTION =====
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(14);
        doc.setTextColor(colors.primary[0], colors.primary[1], colors.primary[2]);
        doc.text('Top Performing QR Code', 20, currentY);

        currentY += 5;

        // Highlight box for top QR code
        doc.setFillColor(252, 247, 255); // Light purple background
        doc.roundedRect(20, currentY, doc.internal.pageSize.width - 40, 45, 3, 3, 'F');

        // Border
        doc.setDrawColor(colors.secondary[0], colors.secondary[1], colors.secondary[2]);
        doc.setLineWidth(0.5);
        doc.roundedRect(20, currentY, doc.internal.pageSize.width - 40, 45, 3, 3, 'S');

        currentY += 10;

        // Top QR Code details
        doc.setFontSize(11);
        doc.setFont('helvetica', 'bold');
        doc.setTextColor(colors.text[0], colors.text[1], colors.text[2]);
        doc.text('Title:', 25, currentY);
        doc.setFont('helvetica', 'normal');
        doc.text(data.topQRCode.title, 60, currentY);

        currentY += 8;
        doc.setFont('helvetica', 'bold');
        doc.text('ID:', 25, currentY);
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(9);
        doc.text(data.topQRCode.id.substring(0, 24) + '...', 60, currentY);

        currentY += 8;
        doc.setFontSize(11);
        doc.setFont('helvetica', 'bold');
        doc.text('Scans:', 25, currentY);
        doc.setFont('helvetica', 'normal');
        doc.setTextColor(colors.accent[0], colors.accent[1], colors.accent[2]);
        doc.text(data.topQRCode.scanCount.toString(), 60, currentY);

        // Trend indicator
        const trendColor = data.topQRCode.trend.direction.toLowerCase() === 'up'
            ? colors.accent
            : [239, 68, 68]; // Red
        const trendSymbol = data.topQRCode.trend.direction.toLowerCase() === 'up' ? '↑' : '↓';

        doc.setTextColor(trendColor[0], trendColor[1], trendColor[2]);
        doc.setFont('helvetica', 'bold');
        doc.text(`${trendSymbol} ${data.topQRCode.trend.percentage}%`, 100, currentY);

        currentY += 20;

        // Section divider
        doc.setDrawColor(colors.lightGray[0], colors.lightGray[1], colors.lightGray[2]);
        doc.setLineWidth(1);
        doc.line(20, currentY, doc.internal.pageSize.width - 20, currentY);
        currentY += 10;

        // ===== TOTAL SCANS BREAKDOWN =====
        if (data.totalScansBreakdown && data.totalScansBreakdown.length > 0) {
            doc.setFont('helvetica', 'bold');
            doc.setFontSize(14);
            doc.setTextColor(colors.primary[0], colors.primary[1], colors.primary[2]);
            doc.text('Scans Breakdown', 20, currentY);

            currentY += 5;

            const breakdownData = data.totalScansBreakdown.map((item: any) => [
                item.period,
                item.count.toString(),
                `${item.percentage}%`
            ]);

            autoTable(doc, {
                startY: currentY,
                head: [['Period', 'Count', 'Percentage']],
                body: breakdownData,
                theme: 'striped',
                styles: {
                    fontSize: 10,
                    cellPadding: 5,
                    textColor: colors.text as [number, number, number]
                },
                headStyles: {
                    fillColor: colors.primary as [number, number, number],
                    textColor: colors.white as [number, number, number],
                    fontStyle: 'bold',
                    halign: 'left'
                },
                alternateRowStyles: {
                    fillColor: colors.lightGray as [number, number, number]
                },
                margin: { left: 20, right: 20 },
                columnStyles: {
                    0: { cellWidth: 60 },
                    1: { halign: 'center', cellWidth: 50 },
                    2: { halign: 'center', cellWidth: 50, textColor: colors.accent as [number, number, number] }
                }
            });

            currentY = (doc as any).lastAutoTable.finalY + 10;
        }

        // ===== FOOTER =====
        const pageCount = doc.getNumberOfPages();
        for (let i = 1; i <= pageCount; i++) {
            doc.setPage(i);

            // Footer line
            doc.setDrawColor(colors.lightGray[0], colors.lightGray[1], colors.lightGray[2]);
            doc.setLineWidth(0.5);
            doc.line(20, doc.internal.pageSize.height - 20, doc.internal.pageSize.width - 20, doc.internal.pageSize.height - 20);

            // Page number
            doc.setFontSize(9);
            doc.setFont('helvetica', 'normal');
            doc.setTextColor(150, 150, 150);
            doc.text(
                `Page ${i} of ${pageCount}`,
                doc.internal.pageSize.width / 2,
                doc.internal.pageSize.height - 12,
                { align: 'center' }
            );

            // Company name
            doc.text(
                'Quick Connect © 2025',
                20,
                doc.internal.pageSize.height - 12
            );

            // Confidential tag
            doc.text(
                'Confidential',
                doc.internal.pageSize.width - 20,
                doc.internal.pageSize.height - 12,
                { align: 'right' }
            );
        }

        return Buffer.from(doc.output('arraybuffer'));
    }

    /**
     * Generate user behavior report PDF
     */
    static async generateUserBehaviorReport(data: any): Promise<Buffer> {
        const doc = new jsPDF();

        // Header
        doc.setFontSize(22);
        doc.setTextColor(30, 58, 138); // Dark blue
        doc.text('User Behavior Analytics Report', 20, 20);

        doc.setFontSize(12);
        doc.setTextColor(0, 0, 0);
        doc.text(`Generated on: ${data.generatedAt}`, 20, 35);
        doc.text(`Period: ${data.dateRange}`, 20, 45);

        // User activity metrics
        doc.setFontSize(16);
        doc.text('User Activity Metrics', 20, 65);

        const activityMetrics = [
            ['Login Activity', data.loginActivity.toString()],
            ['User Registrations', data.userRegistrations.toString()],
            ['QR Code Creations', data.qrCodeCreations.toString()],
            ['Scan Activity', data.scanActivity.toString()],
            ['Profile Updates', data.profileUpdates.toString()],
            ['Security Events', data.securityEvents.toString()],
            ['Unique Active Users', data.uniqueActiveUsers.toString()],
            ['Profile Completion Rate', `${data.profileCompletionRate}%`],
            ['Avg Actions Per User', data.avgActionsPerUser.toString()]
        ];

        autoTable(doc, {
            startY: 75,
            head: [['Metric', 'Value']],
            body: activityMetrics,
            theme: 'grid',
            styles: { fontSize: 11 },
            headStyles: { fillColor: [30, 58, 138] },
            margin: { left: 20, right: 20 }
        });

        // Top active users
        if (data.topActiveUsers && data.topActiveUsers.length > 0) {
            doc.setFontSize(16);
            doc.text('Top Active Users', 20, (doc as any).lastAutoTable.finalY + 10);

            const topUserData = data.topActiveUsers.map((user: any) => [
                user.name || user.email || 'N/A',
                user.scanCount ? user.scanCount.toString() : '0'
            ]);

            autoTable(doc, {
                startY: (doc as any).lastAutoTable.finalY + 15,
                head: [['User', 'Scan Count']],
                body: topUserData,
                theme: 'grid',
                styles: { fontSize: 10 },
                headStyles: { fillColor: [30, 58, 138] },
                margin: { left: 20, right: 20 }
            });
        }

        // Daily activity
        if (data.dailyActivity && data.dailyActivity.length > 0) {
            doc.setFontSize(16);
            doc.text('Daily Activity', 20, (doc as any).lastAutoTable.finalY + 10);

            const dailyData = data.dailyActivity.map((day: any) => [
                day._id,
                day.logins ? day.logins.toString() : '0',
                day.qrCreations ? day.qrCreations.toString() : '0',
                day.scans ? day.scans.toString() : '0'
            ]);

            autoTable(doc, {
                startY: (doc as any).lastAutoTable.finalY + 15,
                head: [['Date', 'Logins', 'QR Creations', 'Scans']],
                body: dailyData,
                theme: 'grid',
                styles: { fontSize: 9 },
                headStyles: { fillColor: [30, 58, 138] },
                margin: { left: 20, right: 20 }
            });
        }

        // Footer
        const pageCount = doc.getNumberOfPages();
        for (let i = 1; i <= pageCount; i++) {
            doc.setPage(i);
            doc.text(`Page ${i} of ${pageCount}`, 20, doc.internal.pageSize.height - 10);
        }

        return Buffer.from(doc.output('arraybuffer'));
    }

    /**
     * Generate QR code report PDF
     */
    static async generateQRCodeReport(reportData: any): Promise<Buffer> {
        const doc = new jsPDF();

        // Header
        doc.setFontSize(22);
        doc.setTextColor(30, 58, 138); // Dark blue
        doc.text('QR Code Report', 20, 20);

        doc.setFontSize(12);
        doc.setTextColor(0, 0, 0);
        doc.text(`Generated on: ${new Date().toLocaleString()}`, 20, 35);
        doc.text(`Date Range: ${reportData.dateRange.startDate.toLocaleDateString()} - ${reportData.dateRange.endDate.toLocaleDateString()}`, 20, 45);

        // Summary metrics
        doc.setFontSize(16);
        doc.text('Summary', 20, 65);

        const summaryData = [
            ['Total QR Codes', reportData.totalQrCodes.toString()],
            ['Total Scans', reportData.totalScans.toString()],
            ['Active QR Codes', reportData.activeQrCodes.toString()]
        ];

        autoTable(doc, {
            startY: 75,
            head: [['Metric', 'Value']],
            body: summaryData,
            theme: 'grid',
            styles: { fontSize: 11 },
            headStyles: { fillColor: [30, 58, 138] },
            margin: { left: 20, right: 20 }
        });

        // Top QR Codes
        if (reportData.qrCodes && reportData.qrCodes.length > 0) {
            doc.setFontSize(16);
            doc.text('Top QR Codes by Scan Count', 20, (doc as any).lastAutoTable.finalY + 10);

            const qrCodeData = reportData.qrCodes.map((qr: any) => [
                qr.title || 'Untitled',
                qr.type || 'N/A',
                qr.scan_count ? qr.scan_count.toString() : '0',
                qr.status || 'N/A'
            ]);

            autoTable(doc, {
                startY: (doc as any).lastAutoTable.finalY + 15,
                head: [['Title', 'Type', 'Scans', 'Status']],
                body: qrCodeData,
                theme: 'grid',
                styles: { fontSize: 10 },
                headStyles: { fillColor: [30, 58, 138] },
                margin: { left: 20, right: 20 }
            });
        }

        // Recent scans
        if (reportData.scans && reportData.scans.length > 0) {
            doc.setFontSize(16);
            doc.text('Recent Scans', 20, (doc as any).lastAutoTable.finalY + 10);

            const scanData = reportData.scans.map((scan: any) => [
                scan.qrcode_id?.toString().substring(0, 12) + '...' || 'N/A',
                scan.scanned_by ? (scan.scanned_by.email || 'User') : (scan.is_anonymous ? 'Anonymous' : 'N/A'),
                scan.is_anonymous ? 'Yes' : 'No',
                scan.createdAt ? new Date(scan.createdAt).toLocaleDateString() : 'N/A'
            ]);

            autoTable(doc, {
                startY: (doc as any).lastAutoTable.finalY + 15,
                head: [['QR Code ID', 'Scanned By', 'Anonymous', 'Date']],
                body: scanData,
                theme: 'grid',
                styles: { fontSize: 9 },
                headStyles: { fillColor: [30, 58, 138] },
                margin: { left: 20, right: 20 }
            });
        }

        // Footer
        const pageCount = doc.getNumberOfPages();
        for (let i = 1; i <= pageCount; i++) {
            doc.setPage(i);
            doc.text(`Page ${i} of ${pageCount}`, 20, doc.internal.pageSize.height - 10);
        }

        return Buffer.from(doc.output('arraybuffer'));
    }

    /**
     * Generate contacts export report PDF
     */
    static async generateContactsReport(contacts: any[]): Promise<Buffer> {
        const doc = new jsPDF();

        // Header
        doc.setFontSize(22);
        doc.setTextColor(30, 58, 138); // Dark blue
        doc.text('Contacts Export Report', 20, 20);

        doc.setFontSize(12);
        doc.setTextColor(0, 0, 0);
        doc.text(`Generated on: ${new Date().toLocaleString()}`, 20, 35);
        doc.text(`Total Contacts: ${contacts.length}`, 20, 45);

        // Contacts table
        if (contacts && contacts.length > 0) {
            doc.setFontSize(16);
            doc.text('Contacts', 20, 65);

            const contactData = contacts.map((contact: any) => [
                contact.first_name || contact.last_name ? `${contact.first_name || ''} ${contact.last_name || ''}`.trim() : 'N/A',
                contact.email || 'N/A',
                contact.phone_number || 'N/A',
                contact.contact_status || 'N/A',
                contact.reason || 'N/A',
                new Date(contact.created_at || contact.createdAt).toLocaleDateString() || 'N/A'
            ]);

            autoTable(doc, {
                startY: 75,
                head: [['Name', 'Email', 'Phone', 'Status', 'Reason', 'Created']],
                body: contactData,
                theme: 'grid',
                styles: { fontSize: 9 },
                headStyles: { fillColor: [30, 58, 138] },
                margin: { left: 20, right: 20 }
            });
        }

        // Footer
        const pageCount = doc.getNumberOfPages();
        for (let i = 1; i <= pageCount; i++) {
            doc.setPage(i);
            doc.text(`Page ${i} of ${pageCount}`, 20, doc.internal.pageSize.height - 10);
        }

        return Buffer.from(doc.output('arraybuffer'));
    }
}