from typing import Any, Optional

import tmt.base.core
import tmt.base.plan
import tmt.export
import tmt.log
import tmt.utils
import tmt.utils.templates
from tmt.utils import Path


@tmt.base.core.FmfId.provides_export('template')
@tmt.base.core.Test.provides_export('template')
@tmt.base.plan.Plan.provides_export('template')
@tmt.base.core.Story.provides_export('template')
class TemplateExporter(tmt.export.ExportPlugin):
    @classmethod
    def render_template(
        cls,
        *,
        template_filepath: Optional[Path] = None,
        default_template_filename: str,
        keys: Optional[list[str]] = None,
        **variables: Any,
    ) -> str:
        template_filepath = template_filepath or tmt.utils.resource_files(
            f"{tmt.export.TEMPLATES_RESOURCE}/{default_template_filename}",
            logger=tmt.log.Logger.get_bootstrap_logger(),
            assert_file=True,
        )
        assert isinstance(template_filepath, Path)  # Narrow type
        return tmt.utils.templates.render_template_file(
            template_filepath,
            KEYS=keys,
            **variables,
        )

    @classmethod
    def export_fmfid_collection(
        cls,
        fmf_ids: list[tmt.base.core.FmfId],
        keys: Optional[list[str]] = None,
        template: Optional[Path] = None,
        **kwargs: Any,
    ) -> str:
        return '\n\n'.join(
            [
                cls.render_template(
                    template_filepath=template,
                    default_template_filename='default-fmfid.j2',
                    keys=keys,
                    FMF_ID=fmf_id,
                )
                for fmf_id in fmf_ids
            ]
        )

    @classmethod
    def export_test_collection(
        cls,
        tests: list[tmt.base.core.Test],
        keys: Optional[list[str]] = None,
        template: Optional[Path] = None,
        **kwargs: Any,
    ) -> str:
        return '\n\n'.join(
            [
                cls.render_template(
                    template_filepath=template,
                    default_template_filename='default-test.j2',
                    keys=keys,
                    TEST=test,
                )
                for test in tests
            ]
        )

    @classmethod
    def export_plan_collection(
        cls,
        plans: list[tmt.base.plan.Plan],
        keys: Optional[list[str]] = None,
        template: Optional[Path] = None,
        **kwargs: Any,
    ) -> str:
        return '\n\n'.join(
            [
                cls.render_template(
                    template_filepath=template,
                    default_template_filename='default-plan.j2',
                    keys=keys,
                    PLAN=plan,
                )
                for plan in plans
            ]
        )

    @classmethod
    def export_story_collection(
        cls,
        stories: list[tmt.base.core.Story],
        keys: Optional[list[str]] = None,
        template: Optional[Path] = None,
        include_title: bool = True,
        **kwargs: Any,
    ) -> str:
        return '\n\n'.join(
            [
                cls.render_template(
                    template_filepath=template,
                    default_template_filename='default-story.j2',
                    keys=keys,
                    STORY=story,
                    INCLUDE_TITLE=include_title,
                )
                for story in stories
            ]
        )
