﻿# app/services/pdf_service.py
# IMPORTANT: This service requires xhtml2pdf and its dependencies
# If ImportError occurs, ensure these are in requirements.txt:
# - xhtml2pdf, reportlab, Pillow, html5lib
# See docs/SIGNATURE_PAD_FIX.md for troubleshooting
from xhtml2pdf import pisa
import os
from flask import current_app
from datetime import datetime
import io
import base64


class ContractPDFService:
    """PDF generation service using existing contract data and templates"""
    
    def __init__(self):
        self.contracts_dir = 'contracts'
        self.ensure_contracts_directory()
    
    def ensure_contracts_directory(self):
        """Ensure contracts directory exists"""
        if not os.path.exists(self.contracts_dir):
            os.makedirs(self.contracts_dir, exist_ok=True)
    
    def generate_contract_pdf(self, contract, signature_data=None):
        """Generate PDF from contract using existing contract generator
        
        Args:
            contract: Contract object or contract data dict
            signature_data: Base64 encoded signature image or file path
            
        Returns:
            str: Path to generated PDF file
        """
        try:
            # Import here to avoid circular imports
            from app.contract_generator import ContractGenerator
            
            generator = ContractGenerator()
            
            # Handle both contract objects and contract data
            if hasattr(contract, 'id'):
                # It's a contract object - generate HTML from contract data
                html_content = generator.render_contract_html(contract)
                contract_id = contract.get('contract_id', contract.id)
            else:
                # It's contract data dict - use directly
                html_content = generator.render_contract_html(contract)
                contract_id = contract.get('contract_id', 'unknown')
            
            # Add signature if provided
            if signature_data:
                html_content = self._add_signature_to_html(html_content, signature_data)
            
            # Generate PDF filename
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            pdf_filename = f"contract_{contract_id}_signed_{timestamp}.pdf"
            pdf_path = os.path.join(self.contracts_dir, pdf_filename)
            
            # Generate PDF with enhanced styling
            self._generate_pdf_from_html(html_content, pdf_path)
            
            return pdf_path
            
        except Exception as e:
            current_app.logger.error(f"PDF generation failed: {e}")
            raise Exception(f"Failed to generate PDF: {str(e)}")
    
    def _add_signature_to_html(self, html_content, signature_data):
        """Add signature to HTML content"""
        try:
            # Handle different signature data formats
            if signature_data.startswith('data:image'):
                # Base64 data URL
                signature_img = f'<img src="{signature_data}" style="max-width:200px; max-height:100px; border: 1px solid #ccc;" alt="Digital Signature">'
            elif signature_data.startswith('/') or signature_data.startswith('http'):
                # File path or URL
                signature_img = f'<img src="{signature_data}" style="max-width:200px; max-height:100px; border: 1px solid #ccc;" alt="Digital Signature">'
            elif signature_data:
                # Assume it's base64 encoded image data
                signature_img = f'<img src="data:image/png;base64,{signature_data}" style="max-width:200px; max-height:100px; border: 1px solid #ccc;" alt="Digital Signature">'
            else:
                signature_img = '<p style="color: #666; font-style: italic;">Digital signature pending</p>'
            
            # Replace placeholder or add to signature section
            if '{{SIGNATURE_PLACEHOLDER}}' in html_content:
                html_content = html_content.replace('{{SIGNATURE_PLACEHOLDER}}', signature_img)
            else:
                # Add signature to the signature section
                signature_section = f'''
                <div style="margin-top: 20px; padding: 15px; border: 1px solid #ddd; background: #f9f9f9;">
                    <h4>Digital Signature:</h4>
                    {signature_img}
                    <p style="font-size: 0.9em; color: #666;">Signed electronically via RateRight Platform on {datetime.now().strftime('%d %B %Y at %H:%M:%S')}</p>
                </div>
                '''
                # Insert before closing body tag
                html_content = html_content.replace('</body>', signature_section + '</body>')
            
            return html_content
            
        except Exception as e:
            current_app.logger.warning(f"Failed to add signature: {e}")
            return html_content
    
    def _generate_pdf_from_html(self, html_content, pdf_path):
        """Generate PDF from HTML content with enhanced styling"""
        
        # Enhanced CSS for better PDF rendering with xhtml2pdf
        pdf_css = """
            @page {
                size: A4;
                margin: 2cm;
            }
            
            body {
                font-family: Georgia, serif;
                font-size: 11pt;
                line-height: 1.4;
                color: #333;
            }
            
            h1 {
                font-size: 18pt;
                color: #2c3e50;
                border-bottom: 2pt solid #3498db;
                padding-bottom: 8pt;
                margin-bottom: 15pt;
                page-break-after: avoid;
            }
            
            h2 {
                font-size: 14pt;
                color: #2c3e50;
                border-bottom: 1pt solid #3498db;
                padding-bottom: 4pt;
                margin-top: 20pt;
                margin-bottom: 10pt;
                page-break-after: avoid;
            }
            
            h3 {
                font-size: 12pt;
                color: #34495e;
                margin-top: 15pt;
                margin-bottom: 8pt;
                page-break-after: avoid;
            }
            
            .legal-content {
                background: #fff;
                padding: 0;
            }
            
            .scope, .parties {
                background: #f8f9fa;
                padding: 12pt;
                border-left: 3pt solid #3498db;
                margin: 15pt 0;
            }
            
            .highlight {
                background: #fff3cd;
                padding: 10pt;
                border: 1pt solid #ffeaa7;
                margin: 10pt 0;
            }
            
            .signature {
                margin-top: 30pt;
                border-top: 1pt solid #ddd;
                padding-top: 15pt;
            }
            
            .template-notice {
                background: #fff3cd;
                padding: 10pt;
                border: 1pt solid #ffeaa7;
                margin-top: 15pt;
                font-size: 10pt;
            }
            
            ul {
                padding-left: 20pt;
                margin-bottom: 10pt;
            }
            
            ul li {
                margin-bottom: 4pt;
            }
            
            p {
                margin-bottom: 8pt;
            }
            
            .signature-section {
                margin-top: 20pt;
            }
        """
        
        # Embed CSS in HTML for xhtml2pdf
        full_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <style type="text/css">
            {pdf_css}
            </style>
        </head>
        <body>
        {html_content}
        </body>
        </html>
        """
        
        try:
            # Generate PDF using xhtml2pdf
            with open(pdf_path, "w+b") as result_file:
                pisa_status = pisa.CreatePDF(
                    full_html,
                    dest=result_file,
                    encoding='UTF-8'
                )
            
            if pisa_status.err:
                raise Exception(f"PDF generation had errors: {pisa_status.err}")
                
            if current_app:
                current_app.logger.info(f"PDF generated successfully: {pdf_path}")
            else:
                print(f"PDF generated successfully: {pdf_path}")
            
        except Exception as e:
            error_msg = f"PDF generation error: {e}"
            if current_app:
                current_app.logger.error(error_msg)
            else:
                print(error_msg)
            raise Exception(f"Failed to generate PDF file: {str(e)}")
    
    def generate_pdf_from_job_application(self, job, hirer, worker, application, signature_data=None):
        """Generate PDF for a specific job application
        
        Args:
            job: Job object
            hirer: User object (contractor/hirer)
            worker: User object (worker)
            application: Application object or ID
            signature_data: Optional signature data
            
        Returns:
            str: Path to generated PDF
        """
        try:
            from app.contract_generator import ContractGenerator
            
            generator = ContractGenerator()
            
            # Generate contract data from job and users
            contract_data = generator.generate_contract_data(job, hirer, worker, application)
            
            # Generate PDF
            return self.generate_contract_pdf(contract_data, signature_data)
            
        except Exception as e:
            current_app.logger.error(f"Job application PDF generation failed: {e}")
            raise Exception(f"Failed to generate PDF from job application: {str(e)}")
    
    def get_contract_pdf_path(self, contract_id):
        """Get path to existing contract PDF"""
        try:
            # Look for existing PDF files for this contract
            for filename in os.listdir(self.contracts_dir):
                if filename.startswith(f"contract_{contract_id}_") and filename.endswith('.pdf'):
                    return os.path.join(self.contracts_dir, filename)
            return None
        except Exception:
            return None
    
    def list_contract_pdfs(self):
        """List all contract PDF files"""
        try:
            pdf_files = []
            if os.path.exists(self.contracts_dir):
                for filename in os.listdir(self.contracts_dir):
                    if filename.endswith('.pdf') and filename.startswith('contract_'):
                        file_path = os.path.join(self.contracts_dir, filename)
                        file_info = {
                            'filename': filename,
                            'path': file_path,
                            'size': os.path.getsize(file_path),
                            'created': datetime.fromtimestamp(os.path.getctime(file_path))
                        }
                        pdf_files.append(file_info)
            return sorted(pdf_files, key=lambda x: x['created'], reverse=True)
        except Exception as e:
            current_app.logger.error(f"Failed to list PDF files: {e}")
            return []


# Utility functions for easy integration
def generate_contract_pdf(contract_data, signature_data=None):
    """Convenience function to generate contract PDF"""
    service = ContractPDFService()
    return service.generate_contract_pdf(contract_data, signature_data)


def generate_job_application_pdf(job, hirer, worker, application, signature_data=None):
    """Convenience function to generate PDF from job application"""
    service = ContractPDFService()
    return service.generate_pdf_from_job_application(job, hirer, worker, application, signature_data)


# Test function
def test_pdf_generation():
    """Test PDF generation with dummy data"""
    
    print("ðŸ§ª Testing PDF Generation Service...")
    
    # Create dummy contract data (matching ContractGenerator format)
    dummy_contract = {
        'date': datetime.now().strftime('%d %B %Y'),
        'job_title': 'Test Carpentry Job',
        'job_description': 'Build custom kitchen cabinets for residential project',
        'job_location': 'Parramatta, NSW',
        'hourly_rate': '45.00',
        'gst_note': 'plus GST if applicable',
        'hirer_name': 'John Smith',
        'hirer_abn': '12 345 678 901',
        'contractor_name': 'Mike Johnson',
        'contractor_abn': '98 765 432 109',
        'risk_level': 'MEDIUM',
        'insurance_amount': '$2,000,000',
        'white_card_required': 'Required',
        'safety_controls': 'PPE, SWMS review, toolbox talks',
        'hirer_signature_date': 'Pending',
        'contractor_signature_date': 'Pending',
        'contract_id': f'TEST-{datetime.now().strftime("%Y%m%d-%H%M%S")}'
    }
    
    try:
        # Test basic PDF generation
        service = ContractPDFService()
        pdf_path = service.generate_contract_pdf(dummy_contract)
        
        print(f"âœ… PDF generated successfully: {pdf_path}")
        print(f"ðŸ“„ Contract ID: {dummy_contract['contract_id']}")
        
        # Check if file exists and has content
        if os.path.exists(pdf_path) and os.path.getsize(pdf_path) > 0:
            file_size = os.path.getsize(pdf_path)
            print(f"ðŸ“Š File size: {file_size:,} bytes")
            print(f"ðŸ“… Created: {datetime.fromtimestamp(os.path.getctime(pdf_path))}")
            
            # Test with signature
            print("\nðŸ–‹ï¸ Testing with signature...")
            dummy_signature = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="
            signed_pdf_path = service.generate_contract_pdf(dummy_contract, dummy_signature)
            
            print(f"âœ… Signed PDF generated: {signed_pdf_path}")
            
            return pdf_path
            
        else:
            print("âŒ PDF file was not created or is empty")
            return None
            
    except Exception as e:
        print(f"âŒ PDF generation failed: {e}")
        return None


if __name__ == "__main__":
    test_pdf_generation()

