"""
Invoice PDF generation service
Generates PDF invoices for billing records
"""
from decimal import Decimal
from datetime import datetime
from io import BytesIO
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER
from django.conf import settings
import logging

logger = logging.getLogger(__name__)


class InvoicePDFGenerator:
    """Generate PDF invoices"""
    
    @staticmethod
    def generate_invoice_pdf(invoice):
        """
        Generate PDF for an invoice
        
        Args:
            invoice: Invoice model instance
            
        Returns:
            BytesIO: PDF file buffer
        """
        buffer = BytesIO()
        
        # Create PDF document
        doc = SimpleDocTemplate(
            buffer,
            pagesize=letter,
            rightMargin=0.75*inch,
            leftMargin=0.75*inch,
            topMargin=0.75*inch,
            bottomMargin=0.75*inch
        )
        
        # Container for PDF elements
        elements = []
        styles = getSampleStyleSheet()
        
        # Custom styles
        title_style = ParagraphStyle(
            'CustomTitle',
            parent=styles['Heading1'],
            fontSize=24,
            textColor=colors.HexColor('#1f2937'),
            spaceAfter=30,
        )
        
        heading_style = ParagraphStyle(
            'CustomHeading',
            parent=styles['Heading2'],
            fontSize=14,
            textColor=colors.HexColor('#374151'),
            spaceAfter=12,
        )
        
        normal_style = ParagraphStyle(
            'CustomNormal',
            parent=styles['Normal'],
            fontSize=10,
            textColor=colors.HexColor('#4b5563'),
        )
        
        # Header
        elements.append(Paragraph('INVOICE', title_style))
        elements.append(Spacer(1, 0.2*inch))
        
        # Company info and invoice details side by side
        company_data = [
            ['<b>From:</b>', f'<b>Invoice #:</b> {invoice.invoice_number}'],
            [getattr(settings, 'COMPANY_NAME', 'Igny8'), f'<b>Date:</b> {invoice.created_at.strftime("%B %d, %Y")}'],
            [getattr(settings, 'COMPANY_ADDRESS', ''), f'<b>Due Date:</b> {invoice.due_date.strftime("%B %d, %Y")}'],
            [getattr(settings, 'COMPANY_EMAIL', settings.DEFAULT_FROM_EMAIL), f'<b>Status:</b> {invoice.status.upper()}'],
        ]
        
        company_table = Table(company_data, colWidths=[3.5*inch, 3*inch])
        company_table.setStyle(TableStyle([
            ('FONTNAME', (0, 0), (-1, -1), 'Helvetica'),
            ('FONTSIZE', (0, 0), (-1, -1), 10),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.HexColor('#4b5563')),
            ('VALIGN', (0, 0), (-1, -1), 'TOP'),
            ('ALIGN', (1, 0), (1, -1), 'RIGHT'),
        ]))
        elements.append(company_table)
        elements.append(Spacer(1, 0.3*inch))
        
        # Bill to section
        elements.append(Paragraph('<b>Bill To:</b>', heading_style))
        bill_to_data = [
            [invoice.account.name],
            [invoice.account.owner.email],
        ]
        
        if hasattr(invoice.account, 'billing_email') and invoice.account.billing_email:
            bill_to_data.append([f'Billing: {invoice.account.billing_email}'])
        
        for line in bill_to_data:
            elements.append(Paragraph(line[0], normal_style))
        
        elements.append(Spacer(1, 0.3*inch))
        
        # Line items table
        elements.append(Paragraph('<b>Items:</b>', heading_style))
        
        # Table header
        line_items_data = [
            ['Description', 'Quantity', 'Unit Price', 'Amount']
        ]
        
        # Get line items
        for item in invoice.line_items.all():
            line_items_data.append([
                item.description,
                str(item.quantity),
                f'{invoice.currency} {item.unit_price:.2f}',
                f'{invoice.currency} {item.total_price:.2f}'
            ])
        
        # Add subtotal, tax, total rows
        line_items_data.append(['', '', '<b>Subtotal:</b>', f'<b>{invoice.currency} {invoice.subtotal:.2f}</b>'])
        
        if invoice.tax_amount and invoice.tax_amount > 0:
            line_items_data.append(['', '', f'Tax ({invoice.tax_rate}%):', f'{invoice.currency} {invoice.tax_amount:.2f}'])
        
        if invoice.discount_amount and invoice.discount_amount > 0:
            line_items_data.append(['', '', 'Discount:', f'-{invoice.currency} {invoice.discount_amount:.2f}'])
        
        line_items_data.append(['', '', '<b>Total:</b>', f'<b>{invoice.currency} {invoice.total_amount:.2f}</b>'])
        
        # Create table
        line_items_table = Table(
            line_items_data,
            colWidths=[3*inch, 1*inch, 1.25*inch, 1.25*inch]
        )
        
        line_items_table.setStyle(TableStyle([
            # Header row
            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#f3f4f6')),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.HexColor('#1f2937')),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, 0), 10),
            ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
            
            # Body rows
            ('FONTNAME', (0, 1), (-1, -4), 'Helvetica'),
            ('FONTSIZE', (0, 1), (-1, -4), 9),
            ('TEXTCOLOR', (0, 1), (-1, -4), colors.HexColor('#4b5563')),
            ('ROWBACKGROUNDS', (0, 1), (-1, -4), [colors.white, colors.HexColor('#f9fafb')]),
            
            # Summary rows (last 3-4 rows)
            ('FONTNAME', (0, -4), (-1, -1), 'Helvetica'),
            ('FONTSIZE', (0, -4), (-1, -1), 9),
            ('ALIGN', (2, 0), (2, -1), 'RIGHT'),
            ('ALIGN', (3, 0), (3, -1), 'RIGHT'),
            
            # Grid
            ('GRID', (0, 0), (-1, -4), 0.5, colors.HexColor('#e5e7eb')),
            ('LINEABOVE', (2, -4), (-1, -4), 1, colors.HexColor('#d1d5db')),
            ('LINEABOVE', (2, -1), (-1, -1), 2, colors.HexColor('#1f2937')),
            
            # 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),
        ]))
        
        elements.append(line_items_table)
        elements.append(Spacer(1, 0.4*inch))
        
        # Payment information
        if invoice.status == 'paid':
            elements.append(Paragraph('<b>Payment Information:</b>', heading_style))
            
            payment = invoice.payments.filter(status='succeeded').first()
            if payment:
                payment_info = [
                    f'Payment Method: {payment.get_payment_method_display()}',
                    f'Paid On: {payment.processed_at.strftime("%B %d, %Y")}',
                ]
                
                if payment.manual_reference:
                    payment_info.append(f'Reference: {payment.manual_reference}')
                
                for line in payment_info:
                    elements.append(Paragraph(line, normal_style))
                
                elements.append(Spacer(1, 0.2*inch))
        
        # Footer / Notes
        if invoice.notes:
            elements.append(Spacer(1, 0.2*inch))
            elements.append(Paragraph('<b>Notes:</b>', heading_style))
            elements.append(Paragraph(invoice.notes, normal_style))
        
        # Terms
        elements.append(Spacer(1, 0.3*inch))
        elements.append(Paragraph('<b>Terms & Conditions:</b>', heading_style))
        terms = getattr(settings, 'INVOICE_TERMS', 'Payment is due within 7 days of invoice date.')
        elements.append(Paragraph(terms, normal_style))
        
        # Build PDF
        doc.build(elements)
        
        # Get PDF content
        buffer.seek(0)
        return buffer
    
    @staticmethod
    def save_invoice_pdf(invoice, file_path=None):
        """
        Generate and save invoice PDF to file
        
        Args:
            invoice: Invoice model instance
            file_path: Optional file path, defaults to media/invoices/
            
        Returns:
            str: File path where PDF was saved
        """
        import os
        from django.core.files.base import ContentFile
        from django.core.files.storage import default_storage
        
        # Generate PDF
        pdf_buffer = InvoicePDFGenerator.generate_invoice_pdf(invoice)
        
        # Determine file path
        if not file_path:
            file_path = f'invoices/{invoice.invoice_number}.pdf'
        
        # Save to storage
        saved_path = default_storage.save(file_path, ContentFile(pdf_buffer.read()))
        
        logger.info(f'Invoice PDF saved: {saved_path}')
        return saved_path
