"""Report engine — renders Jinja2 HTML templates to PDF, DOCX, and HTML.

Uses WeasyPrint for PDF generation and docxtpl for DOCX.
"""

# Import logging
import logging

# Import os
import os

# Import uuid
import uuid

# Import datetime from datetime
from datetime import datetime

# Import Environment, FileSystemLoader from jinja2
from jinja2 import Environment, FileSystemLoader

# Import settings from app.config
from app.config import settings

# Assign logger = logging.getLogger(__name__)
logger = logging.getLogger(__name__)


# Define class ReportEngine
class ReportEngine:
    """Template-based report generator supporting PDF, DOCX, and HTML output."""

    # Define function __init__
    def __init__(self) -> None:
        """Initialise the Jinja2 environment."""
        # Assign self.jinja_env = Environment(
        self.jinja_env = Environment(
            # Keyword argument: loader
            loader=FileSystemLoader(settings.REPORT_TEMPLATES_DIR),
            # Keyword argument: autoescape
            autoescape=True,
        )

    def _ensure_output_dir(self) -> None:
        os.makedirs(settings.REPORT_OUTPUT_DIR, exist_ok=True)

    # Define function render_html
    def render_html(self, template_name: str, context: dict) -> str:
        """Render a Jinja2 template to an HTML string."""
        # Assign template = self.jinja_env.get_template(f"{template_name}.html")
        template = self.jinja_env.get_template(f"{template_name}.html")
        # Call context.setdefault()
        context.setdefault("company_name", settings.COMPANY_NAME)
        # Call context.setdefault()
        context.setdefault("generated_at", datetime.utcnow().strftime("%B %d, %Y %H:%M UTC"))
        # Return template.render(context)
        return template.render(context)

    # Define function generate_pdf
    def generate_pdf(self, template_name: str, context: dict) -> str:
        """Render HTML and convert to PDF with WeasyPrint."""
        self._ensure_output_dir()
        # Import CSS, HTML from weasyprint
        from weasyprint import CSS, HTML

        # Assign html_content = self.render_html(template_name, context)
        html_content = self.render_html(template_name, context)
        # Assign css_path = os.path.join(settings.REPORT_TEMPLATES_DIR, "styles", "report.css")
        css_path = os.path.join(settings.REPORT_TEMPLATES_DIR, "styles", "report.css")
        # Assign output_path = os.path.join(
        output_path = os.path.join(
            settings.REPORT_OUTPUT_DIR,
            f"{template_name}_{uuid.uuid4().hex[:8]}.pdf",
        )

        # Assign stylesheets = []
        stylesheets = []
        # Check: os.path.exists(css_path)
        if os.path.exists(css_path):
            # Call stylesheets.append()
            stylesheets.append(CSS(filename=css_path))

        # Call HTML()
        HTML(
            # Keyword argument: string
            string=html_content,
            # Keyword argument: base_url
            base_url=settings.REPORT_TEMPLATES_DIR,
        ).write_pdf(output_path, stylesheets=stylesheets)

        # Log info: "PDF generated: %s", output_path
        logger.info("PDF generated: %s", output_path)
        # Return output_path
        return output_path

    # Define function generate_docx
    def generate_docx(self, template_name: str, context: dict) -> str:
        """Render a .docx template with docxtpl."""
        self._ensure_output_dir()
        # Import DocxTemplate from docxtpl
        from docxtpl import DocxTemplate

        # Assign template_path = os.path.join(
        template_path = os.path.join(
            settings.REPORT_TEMPLATES_DIR, f"{template_name}.docx"
        )
        # Assign output_path = os.path.join(
        output_path = os.path.join(
            settings.REPORT_OUTPUT_DIR,
            f"{template_name}_{uuid.uuid4().hex[:8]}.docx",
        )

        # Assign doc = DocxTemplate(template_path)
        doc = DocxTemplate(template_path)
        # Call context.setdefault()
        context.setdefault("company_name", settings.COMPANY_NAME)
        # Call context.setdefault()
        context.setdefault("generated_at", datetime.utcnow().strftime("%B %d, %Y"))
        # Call doc.render()
        doc.render(context)
        # Call doc.save()
        doc.save(output_path)

        # Log info: "DOCX generated: %s", output_path
        logger.info("DOCX generated: %s", output_path)
        # Return output_path
        return output_path

    # Define function generate_html
    def generate_html(self, template_name: str, context: dict) -> str:
        """Render and save a standalone HTML report (alias for spec compatibility)."""
        # Return self.generate_html_file(template_name, context)
        return self.generate_html_file(template_name, context)

    # Define function generate_html_file
    def generate_html_file(self, template_name: str, context: dict) -> str:
        """Render and save a standalone HTML report."""
        self._ensure_output_dir()
        # Assign html_content = self.render_html(template_name, context)
        html_content = self.render_html(template_name, context)
        # Assign output_path = os.path.join(
        output_path = os.path.join(
            settings.REPORT_OUTPUT_DIR,
            f"{template_name}_{uuid.uuid4().hex[:8]}.html",
        )
        # Open context manager
        with open(output_path, "w", encoding="utf-8") as f:
            # Call f.write()
            f.write(html_content)

        # Log info: "HTML report generated: %s", output_path
        logger.info("HTML report generated: %s", output_path)
        # Return output_path
        return output_path


# Assign report_engine = ReportEngine()
report_engine = ReportEngine()
