"""
Enhanced PDF Generator with Beautiful Layouts and Charts
Professional PDF reports with modern styling and embedded visualizations
"""

import io
import base64
from datetime import datetime
from decimal import Decimal
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter, A4
from reportlab.platypus import (
    SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, 
    PageBreak, Image, KeepTogether, Frame, PageTemplate
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, mm
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY
from reportlab.graphics.shapes import Drawing, Rect, String
from reportlab.graphics.charts.linecharts import HorizontalLineChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.widgets.markers import makeMarker
from reportlab.graphics import renderPDF
from django.utils import timezone
import logging

logger = logging.getLogger(__name__)

class EnhancedPDFGenerator:
    """Generate beautiful, professional PDF reports with modern styling"""
    
    # Color scheme
    COLORS = {
        'primary': colors.HexColor('#3B82F6'),
        'secondary': colors.HexColor('#10B981'),
        'accent': colors.HexColor('#F59E0B'),
        'danger': colors.HexColor('#EF4444'),
        'dark': colors.HexColor('#1F2937'),
        'light_gray': colors.HexColor('#F3F4F6'),
        'medium_gray': colors.HexColor('#9CA3AF'),
        'white': colors.white,
        'black': colors.black
    }
    
    def __init__(self):
        self.styles = self._create_custom_styles()
    
    def _create_custom_styles(self):
        """Create custom paragraph styles for professional appearance"""
        styles = getSampleStyleSheet()
        
        # Title style
        styles.add(ParagraphStyle(
            name='CustomTitle',
            parent=styles['Title'],
            fontSize=24,
            textColor=self.COLORS['primary'],
            alignment=TA_CENTER,
            spaceAfter=30,
            fontName='Helvetica-Bold'
        ))
        
        # Subtitle style
        styles.add(ParagraphStyle(
            name='CustomSubtitle',
            parent=styles['Heading1'],
            fontSize=18,
            textColor=self.COLORS['dark'],
            alignment=TA_LEFT,
            spaceAfter=20,
            spaceBefore=20,
            fontName='Helvetica-Bold'
        ))
        
        # Section header style
        styles.add(ParagraphStyle(
            name='SectionHeader',
            parent=styles['Heading2'],
            fontSize=14,
            textColor=self.COLORS['primary'],
            alignment=TA_LEFT,
            spaceAfter=12,
            spaceBefore=15,
            fontName='Helvetica-Bold',
            borderWidth=0,
            borderColor=self.COLORS['primary'],
            borderPadding=5
        ))
        
        # Body text with better spacing
        styles.add(ParagraphStyle(
            name='CustomBody',
            parent=styles['Normal'],
            fontSize=11,
            textColor=self.COLORS['dark'],
            alignment=TA_JUSTIFY,
            spaceAfter=8,
            leading=14
        ))
        
        # Highlight style for important info
        styles.add(ParagraphStyle(
            name='Highlight',
            parent=styles['Normal'],
            fontSize=12,
            textColor=self.COLORS['primary'],
            alignment=TA_LEFT,
            fontName='Helvetica-Bold',
            backColor=self.COLORS['light_gray'],
            borderWidth=1,
            borderColor=self.COLORS['primary'],
            borderPadding=8,
            spaceAfter=10
        ))
        
        # Footer style
        styles.add(ParagraphStyle(
            name='Footer',
            parent=styles['Normal'],
            fontSize=9,
            textColor=self.COLORS['medium_gray'],
            alignment=TA_CENTER,
            spaceAfter=0
        ))
        
        return styles
    
    def _create_header_footer(self, canvas, doc, title="Report", subtitle=""):
        """Create professional header and footer"""
        canvas.saveState()
        
        # Header
        canvas.setFillColor(self.COLORS['primary'])
        canvas.rect(0, doc.height + doc.topMargin - 40, doc.width + doc.leftMargin + doc.rightMargin, 40, fill=1)
        
        canvas.setFillColor(self.COLORS['white'])
        canvas.setFont('Helvetica-Bold', 16)
        canvas.drawString(doc.leftMargin, doc.height + doc.topMargin - 25, title)
        
        if subtitle:
            canvas.setFont('Helvetica', 10)
            canvas.drawString(doc.leftMargin, doc.height + doc.topMargin - 40, subtitle)
        
        # Add logo placeholder (if logo exists)
        canvas.setFillColor(self.COLORS['white'])
        canvas.rect(doc.width - 60, doc.height + doc.topMargin - 35, 50, 30, fill=1, stroke=0)
        canvas.setFillColor(self.COLORS['primary'])
        canvas.setFont('Helvetica-Bold', 8)
        canvas.drawCentredText(doc.width - 35, doc.height + doc.topMargin - 25, "LOGO")
        
        # Footer
        canvas.setFillColor(self.COLORS['light_gray'])
        canvas.rect(0, 0, doc.width + doc.leftMargin + doc.rightMargin, 30, fill=1)
        
        canvas.setFillColor(self.COLORS['medium_gray'])
        canvas.setFont('Helvetica', 9)
        canvas.drawString(doc.leftMargin, 10, f"Generated on {datetime.now().strftime('%B %d, %Y at %I:%M %p')}")
        canvas.drawRightString(doc.width + doc.leftMargin, 10, f"Page {canvas.getPageNumber()}")
        
        canvas.restoreState()
    
    def _create_summary_table(self, data, title="Summary"):
        """Create a beautiful summary table"""
        table_data = [["Metric", "Value"]]
        
        for key, value in data.items():
            # Format the key (convert snake_case to Title Case)
            formatted_key = key.replace('_', ' ').title()
            
            # Format the value based on type
            if isinstance(value, (int, float)):
                if 'amount' in key.lower() or 'disbursed' in key.lower() or 'collected' in key.lower():
                    formatted_value = f"KES {value:,.2f}"
                elif 'rate' in key.lower() or 'percent' in key.lower():
                    formatted_value = f"{value:.1f}%"
                else:
                    formatted_value = f"{value:,}"
            else:
                formatted_value = str(value)
            
            table_data.append([formatted_key, formatted_value])
        
        table = Table(table_data, colWidths=[80*mm, 60*mm])
        table.setStyle(TableStyle([
            # Header styling
            ('BACKGROUND', (0, 0), (-1, 0), self.COLORS['primary']),
            ('TEXTCOLOR', (0, 0), (-1, 0), self.COLORS['white']),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, 0), 12),
            ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
            
            # Data styling
            ('BACKGROUND', (0, 1), (-1, -1), self.COLORS['white']),
            ('TEXTCOLOR', (0, 1), (-1, -1), self.COLORS['dark']),
            ('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
            ('FONTSIZE', (0, 1), (-1, -1), 10),
            ('ALIGN', (0, 0), (0, -1), 'LEFT'),
            ('ALIGN', (1, 1), (1, -1), 'RIGHT'),
            
            # Alternating row colors
            ('ROWBACKGROUNDS', (0, 1), (-1, -1), [self.COLORS['white'], self.COLORS['light_gray']]),
            
            # Borders
            ('GRID', (0, 0), (-1, -1), 1, self.COLORS['medium_gray']),
            ('LINEBELOW', (0, 0), (-1, 0), 2, self.COLORS['primary']),
            
            # Padding
            ('TOPPADDING', (0, 0), (-1, -1), 8),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
            ('LEFTPADDING', (0, 0), (-1, -1), 10),
            ('RIGHTPADDING', (0, 0), (-1, -1), 10),
        ]))
        
        return table
    
    def _create_data_table(self, data, headers, title="Data Table"):
        """Create a professional data table"""
        if not data:
            return Paragraph("No data available", self.styles['CustomBody'])
        
        # Prepare table data
        table_data = [headers]
        for row in data:
            formatted_row = []
            for item in row:
                if isinstance(item, (int, float)):
                    if item > 1000:
                        formatted_row.append(f"{item:,.0f}")
                    else:
                        formatted_row.append(f"{item:.2f}")
                else:
                    formatted_row.append(str(item))
            table_data.append(formatted_row)
        
        # Calculate column widths
        num_cols = len(headers)
        col_width = (180 * mm) / num_cols
        
        table = Table(table_data, colWidths=[col_width] * num_cols)
        table.setStyle(TableStyle([
            # Header styling
            ('BACKGROUND', (0, 0), (-1, 0), self.COLORS['primary']),
            ('TEXTCOLOR', (0, 0), (-1, 0), self.COLORS['white']),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, 0), 10),
            ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
            
            # Data styling
            ('BACKGROUND', (0, 1), (-1, -1), self.COLORS['white']),
            ('TEXTCOLOR', (0, 1), (-1, -1), self.COLORS['dark']),
            ('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
            ('FONTSIZE', (0, 1), (-1, -1), 9),
            ('ALIGN', (0, 1), (-1, -1), 'LEFT'),
            
            # Alternating row colors
            ('ROWBACKGROUNDS', (0, 1), (-1, -1), [self.COLORS['white'], self.COLORS['light_gray']]),
            
            # Borders
            ('GRID', (0, 0), (-1, -1), 0.5, self.COLORS['medium_gray']),
            ('LINEBELOW', (0, 0), (-1, 0), 2, self.COLORS['primary']),
            
            # Padding
            ('TOPPADDING', (0, 0), (-1, -1), 6),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
            ('LEFTPADDING', (0, 0), (-1, -1), 8),
            ('RIGHTPADDING', (0, 0), (-1, -1), 8),
        ]))
        
        return table
    
    def _create_chart_placeholder(self, chart_data, chart_type="bar"):
        """Create a chart using ReportLab graphics"""
        try:
            drawing = Drawing(400, 200)
            
            if chart_type == "pie" and 'labels' in chart_data and 'values' in chart_data:
                pie = Pie()
                pie.x = 50
                pie.y = 50
                pie.width = 100
                pie.height = 100
                pie.data = chart_data['values']
                pie.labels = chart_data['labels']
                pie.slices.strokeWidth = 0.5
                drawing.add(pie)
                
            elif chart_type == "bar" and 'categories' in chart_data and 'values' in chart_data:
                bar_chart = VerticalBarChart()
                bar_chart.x = 50
                bar_chart.y = 50
                bar_chart.height = 125
                bar_chart.width = 300
                bar_chart.data = [chart_data['values']]
                bar_chart.categoryAxis.categoryNames = chart_data['categories']
                bar_chart.bars[0].fillColor = self.COLORS['primary']
                drawing.add(bar_chart)
            
            return drawing
            
        except Exception as e:
            logger.error(f"Chart creation failed: {e}")
            # Return a placeholder rectangle
            drawing = Drawing(400, 200)
            drawing.add(Rect(0, 0, 400, 200, fillColor=self.COLORS['light_gray']))
            drawing.add(String(200, 100, "Chart Placeholder", textAnchor='middle'))
            return drawing
    
    def generate_dashboard_report(self, data):
        """Generate comprehensive dashboard report PDF"""
        try:
            buffer = io.BytesIO()
            doc = SimpleDocTemplate(
                buffer, 
                pagesize=A4,
                topMargin=60*mm,
                bottomMargin=40*mm,
                leftMargin=20*mm,
                rightMargin=20*mm
            )
            
            elements = []
            
            # Title page
            elements.append(Paragraph("Dashboard Report", self.styles['CustomTitle']))
            elements.append(Paragraph(
                f"Comprehensive Business Analytics", 
                self.styles['CustomSubtitle']
            ))
            elements.append(Spacer(1, 20))
            
            # Executive Summary
            if 'summary' in data:
                elements.append(Paragraph("Executive Summary", self.styles['SectionHeader']))
                summary_table = self._create_summary_table(data['summary'])
                elements.append(summary_table)
                elements.append(Spacer(1, 20))
            
            # Portfolio Overview
            if 'portfolio' in data:
                elements.append(Paragraph("Portfolio Overview", self.styles['SectionHeader']))
                portfolio_table = self._create_summary_table(data['portfolio'])
                elements.append(portfolio_table)
                elements.append(Spacer(1, 15))
                
                # Add chart if data available
                if 'chart_data' in data['portfolio']:
                    chart = self._create_chart_placeholder(data['portfolio']['chart_data'], 'pie')
                    elements.append(chart)
                elements.append(Spacer(1, 20))
            
            # Loan Performance
            if 'loans' in data:
                elements.append(Paragraph("Loan Performance", self.styles['SectionHeader']))
                
                if 'summary' in data['loans']:
                    loan_summary = self._create_summary_table(data['loans']['summary'])
                    elements.append(loan_summary)
                    elements.append(Spacer(1, 15))
                
                if 'details' in data['loans']:
                    headers = ["Loan #", "Borrower", "Amount", "Status", "Due Date"]
                    loan_table = self._create_data_table(data['loans']['details'], headers)
                    elements.append(loan_table)
                elements.append(Spacer(1, 20))
            
            # Risk Analysis
            if 'risk' in data:
                elements.append(PageBreak())
                elements.append(Paragraph("Risk Analysis", self.styles['SectionHeader']))
                
                if 'summary' in data['risk']:
                    risk_summary = self._create_summary_table(data['risk']['summary'])
                    elements.append(risk_summary)
                    elements.append(Spacer(1, 15))
                
                if 'high_risk_loans' in data['risk']:
                    headers = ["Loan #", "Borrower", "Days Overdue", "Amount", "Risk Level"]
                    risk_table = self._create_data_table(data['risk']['high_risk_loans'], headers)
                    elements.append(risk_table)
            
            # Financial Summary
            if 'financial' in data:
                elements.append(Spacer(1, 20))
                elements.append(Paragraph("Financial Summary", self.styles['SectionHeader']))
                financial_table = self._create_summary_table(data['financial'])
                elements.append(financial_table)
            
            # Build PDF with custom header/footer
            def add_header_footer(canvas, doc):
                self._create_header_footer(canvas, doc, "Dashboard Report", "Business Analytics")
            
            doc.build(elements, onFirstPage=add_header_footer, onLaterPages=add_header_footer)
            buffer.seek(0)
            return buffer
            
        except Exception as e:
            logger.error(f"Dashboard PDF generation failed: {e}")
            return None
    
    def generate_loan_statement_pdf(self, loan_data):
        """Generate beautiful loan statement PDF"""
        try:
            buffer = io.BytesIO()
            doc = SimpleDocTemplate(
                buffer, 
                pagesize=A4,
                topMargin=60*mm,
                bottomMargin=40*mm,
                leftMargin=20*mm,
                rightMargin=20*mm
            )
            
            elements = []
            
            # Title
            elements.append(Paragraph("LOAN STATEMENT", self.styles['CustomTitle']))
            elements.append(Spacer(1, 20))
            
            # Loan Information
            elements.append(Paragraph("Loan Information", self.styles['SectionHeader']))
            
            loan_info = {
                'loan_number': loan_data.get('loan_number', 'N/A'),
                'borrower_name': loan_data.get('borrower_name', 'N/A'),
                'principal_amount': loan_data.get('principal_amount', 0),
                'disbursement_date': loan_data.get('disbursement_date', 'N/A'),
                'due_date': loan_data.get('due_date', 'N/A'),
                'status': loan_data.get('status', 'N/A'),
                'outstanding_balance': loan_data.get('outstanding_balance', 0)
            }
            
            loan_table = self._create_summary_table(loan_info)
            elements.append(loan_table)
            elements.append(Spacer(1, 20))
            
            # Repayment History
            if 'repayments' in loan_data and loan_data['repayments']:
                elements.append(Paragraph("Repayment History", self.styles['SectionHeader']))
                
                headers = ["Date", "Amount", "Method", "Reference", "Balance After"]
                repayment_data = []
                
                for repayment in loan_data['repayments']:
                    repayment_data.append([
                        repayment.get('date', ''),
                        f"KES {repayment.get('amount', 0):,.2f}",
                        repayment.get('method', ''),
                        repayment.get('reference', ''),
                        f"KES {repayment.get('balance_after', 0):,.2f}"
                    ])
                
                repayment_table = self._create_data_table(repayment_data, headers)
                elements.append(repayment_table)
            else:
                elements.append(Paragraph("No repayments recorded", self.styles['CustomBody']))
            
            elements.append(Spacer(1, 20))
            
            # Summary
            if 'summary' in loan_data:
                elements.append(Paragraph("Summary", self.styles['SectionHeader']))
                summary_table = self._create_summary_table(loan_data['summary'])
                elements.append(summary_table)
            
            # Build PDF
            def add_header_footer(canvas, doc):
                self._create_header_footer(canvas, doc, "Loan Statement", f"Loan #{loan_data.get('loan_number', 'N/A')}")
            
            doc.build(elements, onFirstPage=add_header_footer, onLaterPages=add_header_footer)
            buffer.seek(0)
            return buffer
            
        except Exception as e:
            logger.error(f"Loan statement PDF generation failed: {e}")
            return None
    
    def generate_client_report_pdf(self, client_data):
        """Generate comprehensive client report PDF"""
        try:
            buffer = io.BytesIO()
            doc = SimpleDocTemplate(
                buffer, 
                pagesize=A4,
                topMargin=60*mm,
                bottomMargin=40*mm,
                leftMargin=20*mm,
                rightMargin=20*mm
            )
            
            elements = []
            
            # Title
            elements.append(Paragraph("CLIENT REPORT", self.styles['CustomTitle']))
            elements.append(Spacer(1, 20))
            
            # Client Information
            elements.append(Paragraph("Client Information", self.styles['SectionHeader']))
            
            client_info = {
                'name': client_data.get('name', 'N/A'),
                'phone': client_data.get('phone', 'N/A'),
                'email': client_data.get('email', 'N/A'),
                'id_number': client_data.get('id_number', 'N/A'),
                'member_since': client_data.get('member_since', 'N/A'),
                'credit_score': client_data.get('credit_score', 0)
            }
            
            client_table = self._create_summary_table(client_info)
            elements.append(client_table)
            elements.append(Spacer(1, 20))
            
            # Loan Summary
            if 'summary' in client_data:
                elements.append(Paragraph("Loan Summary", self.styles['SectionHeader']))
                summary_table = self._create_summary_table(client_data['summary'])
                elements.append(summary_table)
                elements.append(Spacer(1, 20))
            
            # Loan History
            if 'loans' in client_data and client_data['loans']:
                elements.append(Paragraph("Loan History", self.styles['SectionHeader']))
                
                headers = ["Loan #", "Amount", "Disbursed", "Due Date", "Status", "Balance"]
                loan_data = []
                
                for loan in client_data['loans']:
                    loan_data.append([
                        loan.get('loan_number', ''),
                        f"KES {loan.get('principal_amount', 0):,.2f}",
                        loan.get('disbursement_date', ''),
                        loan.get('due_date', ''),
                        loan.get('status', ''),
                        f"KES {loan.get('balance', 0):,.2f}"
                    ])
                
                loan_table = self._create_data_table(loan_data, headers)
                elements.append(loan_table)
            else:
                elements.append(Paragraph("No loans recorded", self.styles['CustomBody']))
            
            # Build PDF
            def add_header_footer(canvas, doc):
                self._create_header_footer(canvas, doc, "Client Report", client_data.get('name', 'N/A'))
            
            doc.build(elements, onFirstPage=add_header_footer, onLaterPages=add_header_footer)
            buffer.seek(0)
            return buffer
            
        except Exception as e:
            logger.error(f"Client report PDF generation failed: {e}")
            return None