from typing import Dict, Union, List
from imprint.page import Page
from .engine import Engine
from .img_engine import ImgEngine, ImageBuild

class BuilderMixin:
    """
    Mixin class providing building capabilities for pages in a model.

    This mixin allows converting page data into images, PDFs, or GIFs using different engines.
    """

    def _make(self, forms: Union[Dict, List[Dict]], engine: Engine):
        """
        Internal method to generate page contexts using the specified engine and form data.

        Args:
            forms (Union[Dict, List[Dict]]): A single form dictionary or a list of form dictionaries.
            engine (Engine): The engine used to generate the page contexts.

        Returns:
            List: A flat list of context instances generated by the engine for each page and form.

        Raises:
            RuntimeError: If no pages exist in `self.pages`.
            Exception: If a required form field is missing.
        """
        if isinstance(forms, Dict):
            forms = [forms]

        all_instances = []
        pages: List[Page] = list(self.pages.values())
        if not pages:
            raise RuntimeError("No pages created")
        for form in forms:
            instances = []

            for page in pages:
                ctx = engine.new_page(page.options)
                for field in getattr(page, "fields", {}).values():
                    if getattr(field, "form_key", None):
                        value_field = form.get(field.form_key, None)
                        if not value_field:
                            raise Exception("Required form field missing")
                        field.component.set_value(value_field)
                    engine.make_component(ctx, field.component)
                instances.append(ctx)
            
            all_instances.append(instances)

        # Flatten the list of lists
        return [inst for instance in all_instances for inst in instance]
    
    def build_pdf(self):
        """
        Generate a PDF representation of the pages.

        Returns:
            str: A placeholder string indicating the number of pages included in the PDF.

        Notes:
            - Actual PDF generation is not implemented in this method.
        """
        return f"Gerando PDF com {len(self.pages)} páginas"

    def build_img(self, forms: Union[Dict, List[Dict]]):
        """
        Build images for the provided form data using the Pillow engine.

        Args:
            forms (Union[Dict, List[Dict]]): A single form dictionary or a list of form dictionaries.

        Returns:
            ImageBuildResult: An object containing the generated image contexts and helper methods.
        """
        instances = self._make(forms, ImgEngine())
        return ImageBuild(instances)

    def buid_gif(self):
        """
        Generate a GIF representation of the pages.

        Returns:
            str: A placeholder string indicating the number of pages included in the GIF.

        Notes:
            - Actual GIF generation is not implemented in this method.
        """
        return f"Gerando gif com {len(self.pages)} páginas"
