from unittest.mock import patch

import flask

from abstra_internals.repositories.project.project import PathConflictError
from tests.fixtures import BaseTest


class TestEditorSpaFallback(BaseTest):
    def test_api_url_that_falls_through_routing_404s(self):
        # A double slash (e.g. an absolute path concatenated onto files/)
        # doesn't match the codebase files route, so the request lands on the
        # SPA catch-all — it must 404 instead of serving editor.html, which
        # would render a nested editor inside <embed>/fetch consumers.
        client = self.get_editor_flask_client()
        with patch("abstra_internals.server.blueprints.editor.send_from_dist") as send:
            res = client.get("/_editor/api/codebase/files//files/dir/doc.pdf")
        self.assertEqual(res.status_code, 404)
        send.assert_not_called()

    def test_spa_route_still_falls_back_to_editor_html(self):
        client = self.get_editor_flask_client()
        with patch(
            "abstra_internals.server.blueprints.editor.send_from_dist",
            return_value=flask.Response("editor html", status=200),
        ) as send:
            res = client.get("/_editor/some/spa/route")
        self.assertEqual(res.status_code, 200)
        send.assert_called_once_with("some/spa/route", "editor.html")

    def test_path_conflict_returns_a_structured_client_error(self):
        client = self.get_editor_flask_client()
        with patch.object(
            self.controller,
            "update_stage",
            side_effect=PathConflictError("Path duplicate already exists"),
        ):
            res = client.put("/_editor/api/pages/page-1", json={"path": "duplicate"})

        self.assertEqual(res.status_code, 409)
        self.assertEqual(
            res.json,
            {"error": "path_conflict", "message": "Path duplicate already exists"},
        )
