# Copyright (c) 2026 Luigi Paone <ppc.luigi.paone@gmail.com>
# SPDX-License-Identifier: BSD-3-Clause

"""Full document generation tests for markdown reports."""

import json
from pathlib import Path

from pycivil.EXAStructural.codes import Code
from pycivil.EXAStructural.loads import ForcesOnSection
from pycivil.EXAStructural.loads import Frequency_Enum as Fr
from pycivil.EXAStructural.loads import LimiteState_Enum as Ls
from pycivil.EXAStructural.materials import Concrete, ConcreteSteel
from pycivil.EXAStructural.rcrecsolver.srvRcSecCheck import ModelInputRcSecCheck
from pycivil.EXAUtils.markdownReportMakers import (
    ConcreteMdFB,
    ConcreteSectionMdFB,
    ForcesOnSectionListMdFB,
    SteelConcreteMdFB,
)
from pycivil.EXAUtils.report import (
    EnumFBSection,
    MarkdownReporter,
    ReportProperties,
    ReportTemplateEnum,
    getMarkdownTemplatesPath,
)


def test_report_markdown_full_document(tmp_path: Path):
    """Test full engineering calculation document generation."""
    code = Code("NTC2018")
    markdownTemplatePath = getMarkdownTemplatesPath()

    # Materials
    concrete = Concrete()
    concrete.setByCode(codeObj=code, catstr="C25/30")
    concreteFB = ConcreteMdFB(markdownTemplatePath, concrete)
    concreteFB.setFragmentOptions({
        "section_title": "Materiale: Calcestruzzo",
        "section_level": EnumFBSection.SEC_SECTION
    })
    f_concrete = concreteFB.buildFragment()

    steel = ConcreteSteel()
    steel.setByCode(code, "B450C")
    steelFB = SteelConcreteMdFB(markdownTemplatePath, steel)
    steelFB.setFragmentOptions({
        "section_title": "Materiale: Acciaio",
        "section_level": EnumFBSection.SEC_SECTION
    })
    f_steel = steelFB.buildFragment()

    # Section
    with open(Path(__file__).parent / "test_report_latex_sections_01.json") as jsonFile:
        jsonObject = json.load(jsonFile)
    iData = ModelInputRcSecCheck(**jsonObject)
    section = iData.buildRcsRectangular()

    f_section = None
    if section is not None:
        sectionFB = ConcreteSectionMdFB(markdownTemplatePath, rcs=section)
        sectionFB.setFragmentOptions({
            "section_title": "Geometria della sezione",
            "section_level": EnumFBSection.SEC_SECTION
        })
        f_section = sectionFB.buildFragment()

    # Loads
    loadsFB = ForcesOnSectionListMdFB(markdownTemplatePath)
    loadsFB.setFragmentOptions({
        "section_title": "Combinazioni di carico",
        "section_level": EnumFBSection.SEC_SECTION
    })
    listOfForces = loadsFB.forces()
    listOfForces.append(
        ForcesOnSection(
            Fx=0, Fy=0, Fz=1e3 * 500,
            Mx=0, My=1e3 * 150000, Mz=0,
            descr="SLU - Combinazione 1",
            id=1,
            limitState=Ls.ULTIMATE,
            frequency=Fr.FREQUENCY_ND,
        )
    )
    listOfForces.append(
        ForcesOnSection(
            Fx=0, Fy=0, Fz=1e3 * 350,
            Mx=0, My=1e3 * 100000, Mz=0,
            descr="SLE - Rara",
            id=2,
            limitState=Ls.SERVICEABILITY,
            frequency=Fr.CHARACTERISTIC,
        )
    )
    listOfForces.append(
        ForcesOnSection(
            Fx=0, Fy=0, Fz=1e3 * 300,
            Mx=0, My=1e3 * 80000, Mz=0,
            descr="SLE - Frequente",
            id=3,
            limitState=Ls.SERVICEABILITY,
            frequency=Fr.FREQUENT,
        )
    )
    f_loads = loadsFB.buildFragment()

    # Assemble fragments
    fragments = [f_concrete, f_steel]
    if f_section is not None:
        fragments.append(f_section)
    fragments.append(f_loads)

    # Create reporter with properties
    reporter = MarkdownReporter(markdownTemplatePath)
    reporter.setProperties(ReportProperties(
        project_brief="Test Project - RC Beam Analysis",
        module_name="PyCivil",
        module_version="0.2.16",
        report_designer="Test Engineer",
        report_date="2026-02-02",
        report_time="10:30",
        report_token="TEST-001",
    ))
    reporter.linkFragments(
        template=ReportTemplateEnum.MD_ENG_CAL,
        fragments=fragments
    )
    reporter.compileDocument(path=str(tmp_path), fileName="full_report", output_format="md")

    print(f"Temporary path for test is {tmp_path}")
    assert tmp_path.joinpath("full_report.md").exists()

    # Verify content
    content = tmp_path.joinpath("full_report.md").read_text(encoding="utf-8")
    assert "Test Project" in content
    assert "C25/30" in content or "25.0" in content
    assert "B450" in content or "450" in content


def test_report_markdown_full_document_html(tmp_path: Path):
    """Test full engineering calculation document with HTML output."""
    code = Code("NTC2018")
    markdownTemplatePath = getMarkdownTemplatesPath()

    # Concrete
    concrete = Concrete()
    concrete.setByCode(codeObj=code, catstr="C25/30")
    concreteFB = ConcreteMdFB(markdownTemplatePath, concrete)
    f_concrete = concreteFB.buildFragment()

    # Steel
    steel = ConcreteSteel()
    steel.setByCode(code, "B450C")
    steelFB = SteelConcreteMdFB(markdownTemplatePath, steel)
    f_steel = steelFB.buildFragment()

    # Create reporter
    reporter = MarkdownReporter(markdownTemplatePath)
    reporter.setProperties(ReportProperties(
        project_brief="HTML Output Test",
        module_name="PyCivil",
        module_version="0.2.16",
        report_designer="Test Engineer",
        report_date="2026-02-02",
        report_time="11:00",
        report_token="HTML-001",
    ))
    reporter.linkFragments(
        template=ReportTemplateEnum.MD_ENG_CAL,
        fragments=[f_concrete, f_steel]
    )
    reporter.compileDocument(path=str(tmp_path), fileName="html_report", output_format="html")

    print(f"Temporary path for test is {tmp_path}")
    assert tmp_path.joinpath("html_report.md").exists()
    assert tmp_path.joinpath("html_report.html").exists()

    # Verify HTML content
    html_content = tmp_path.joinpath("html_report.html").read_text(encoding="utf-8")
    assert "<html>" in html_content
    assert "<table>" in html_content or "<th>" in html_content


def test_report_markdown_builder_api(tmp_path: Path):
    """Test using builder API instead of fragments list."""
    code = Code("NTC2018")
    markdownTemplatePath = getMarkdownTemplatesPath()

    concrete = Concrete()
    concrete.setByCode(codeObj=code, catstr="C25/30")
    concreteFB = ConcreteMdFB(markdownTemplatePath, concrete)

    steel = ConcreteSteel()
    steel.setByCode(code, "B450C")
    steelFB = SteelConcreteMdFB(markdownTemplatePath, steel)

    reporter = MarkdownReporter(markdownTemplatePath)
    reporter.linkFragments(
        template=ReportTemplateEnum.MD_ENG_CAL,
        builder=[concreteFB, steelFB]
    )
    reporter.compileDocument(path=str(tmp_path), fileName="builder_report", output_format="md")

    assert tmp_path.joinpath("builder_report.md").exists()
