"""
Tests for planner route responses.

Regression for:
1. OOB swap for #wizPreview stripping class="wizard-preview", causing the
   flex layout to break and CAPEX/CF/IRR values to stack vertically.
   Fix: calculate_response.html OOB element must include class="wizard-preview".

2. Charts: /calculate must embed valid Chart.js JSON (not raw data dicts).
"""
import json


class TestCalculateEndpoint:
    async def test_returns_200(self, client):
        resp = await client.post("/en/planner/calculate", form={"activeTab": "capex"})
        assert resp.status_code == 200

    async def test_returns_html(self, client):
        resp = await client.post("/en/planner/calculate", form={"activeTab": "capex"})
        assert resp.content_type.startswith("text/html")

    async def test_all_tabs_render(self, client):
        for tab in ("capex", "operating", "cashflow", "returns", "metrics"):
            resp = await client.post(
                "/en/planner/calculate", form={"activeTab": tab}
            )
            assert resp.status_code == 200, f"Tab {tab} returned {resp.status_code}"

    async def test_german_endpoint_works(self, client):
        resp = await client.post("/de/planner/calculate", form={"activeTab": "capex"})
        assert resp.status_code == 200


class TestWizPreviewOOBSwap:
    """
    Regression: HTMX outerHTML OOB swap replaces the entire #wizPreview element.
    If the response element lacks class="wizard-preview", the flex layout is lost
    and the three preview values stack vertically on every recalculation.
    """

    async def test_oob_element_has_wizard_preview_class(self, client):
        resp = await client.post("/en/planner/calculate", form={"activeTab": "capex"})
        body = (await resp.get_data()).decode()
        # The OOB swap element must carry class="wizard-preview" so the flex
        # box layout survives the outerHTML replacement.
        assert 'class="wizard-preview"' in body, (
            "OOB #wizPreview element must include class='wizard-preview' "
            "to preserve flex layout after HTMX outerHTML swap"
        )

    async def test_oob_element_has_correct_id(self, client):
        resp = await client.post("/en/planner/calculate", form={"activeTab": "capex"})
        body = (await resp.get_data()).decode()
        assert 'id="wizPreview"' in body

    async def test_oob_element_has_hx_swap_oob(self, client):
        resp = await client.post("/en/planner/calculate", form={"activeTab": "capex"})
        body = (await resp.get_data()).decode()
        assert 'hx-swap-oob="true"' in body


class TestChartJSONInResponse:
    """
    Regression: augment_d() was embedding raw data dicts instead of full
    Chart.js configs. initCharts() passes the embedded JSON directly to
    new Chart(canvas, config) — which requires {type, data, options}.
    """

    async def _get_chart_json(self, client, chart_id: str, tab: str) -> dict:
        resp = await client.post(
            "/en/planner/calculate", form={"activeTab": tab}
        )
        body = (await resp.get_data()).decode()
        # Charts are embedded as: <script type="application/json" id="chartX-data">...</script>
        marker = f'id="{chart_id}-data">'
        start = body.find(marker)
        assert start != -1, f"Chart script tag '{chart_id}-data' not found in response"
        start += len(marker)
        end = body.find("</script>", start)
        return json.loads(body[start:end])

    async def test_capex_chart_is_valid_chartjs_config(self, client):
        config = await self._get_chart_json(client, "chartCapex", "capex")
        assert config["type"] == "doughnut"
        assert "datasets" in config["data"]
        assert "options" in config

    async def test_cf_chart_is_valid_chartjs_config(self, client):
        config = await self._get_chart_json(client, "chartCF", "cashflow")
        assert config["type"] == "bar"
        assert "datasets" in config["data"]
        assert config["options"]["responsive"] is True
        assert config["options"]["maintainAspectRatio"] is False

    async def test_dscr_chart_is_valid_chartjs_config(self, client):
        config = await self._get_chart_json(client, "chartDSCR", "returns")
        assert config["type"] == "bar"
        assert len(config["data"]["datasets"][0]["data"]) == 5

    async def test_ramp_chart_is_valid_chartjs_config(self, client):
        config = await self._get_chart_json(client, "chartRevRamp", "operating")
        assert config["type"] == "line"
        assert len(config["data"]["datasets"]) == 2

    async def test_pl_chart_is_horizontal_bar(self, client):
        config = await self._get_chart_json(client, "chartPL", "operating")
        assert config["type"] == "bar"
        assert config["options"]["indexAxis"] == "y"


class TestWizSummaryLabel:
    """The wizard preview must include the summary caption."""

    async def test_summary_caption_in_response(self, client):
        resp = await client.post("/en/planner/calculate", form={"activeTab": "capex"})
        body = (await resp.get_data()).decode()
        assert "Live Summary" in body

    async def test_german_summary_caption_in_response(self, client):
        resp = await client.post("/de/planner/calculate", form={"activeTab": "capex"})
        body = (await resp.get_data()).decode()
        assert "Aktuelle Zusammenfassung" in body
