from __future__ import annotations

import json
import unittest
from pathlib import Path

from mais_humana.catalog import HUMAN_PROFILES, get_platform
from mais_humana.matrix import build_matrix, build_platform_report, score_cell
from mais_humana.models import EvidenceKind
from mais_humana.scanner import ScanOptions, scan_platform
from tests.helpers import make_tmp


class ScannerMatrixTests(unittest.TestCase):
    def make_repo(self, root: Path, repo_name: str) -> Path:
        repo = root / repo_name
        repo.mkdir()
        (repo / "src").mkdir()
        (repo / "tests").mkdir()
        (repo / "README.md").write_text(
            "# Identity\n\nhealth readiness openapi RBAC credentialRef audit trace panelReady sameSource",
            encoding="utf-8",
        )
        (repo / "package.json").write_text(
            json.dumps(
                {
                    "scripts": {
                        "test": "node --test",
                        "build": "tsc",
                        "smoke:local": "node src/index.js",
                    }
                }
            ),
            encoding="utf-8",
        )
        (repo / "src" / "index.ts").write_text(
            """
export function health() { return { ok: true, readiness: "ready" }; }
export const openapi = { path: "/openapi" };
export const routes = [{ path: "/identity/health" }, { path: "/identity/contracts" }];
export const security = { rbac: true, credentialRef: "safe" };
""",
            encoding="utf-8",
        )
        (repo / "tests" / "identity.test.ts").write_text("test('health', () => true)\n", encoding="utf-8")
        return repo

    def test_scan_platform_collects_scripts_metrics_and_evidence(self) -> None:
        root = make_tmp()
        self.make_repo(root, "tudo-para-ia-identity-platform")
        scan = scan_platform(root, get_platform("identity"), ScanOptions(max_file_bytes=50_000))
        self.assertTrue(scan.exists)
        self.assertFalse(scan.git_present)
        self.assertGreater(scan.code_lines, 0)
        self.assertGreaterEqual(len(scan.scripts), 3)
        kinds = {evidence.kind for evidence in scan.evidence}
        self.assertIn(EvidenceKind.TEST, kinds)
        self.assertIn(EvidenceKind.OPENAPI, kinds)
        self.assertIn(EvidenceKind.SECURITY, kinds)
        self.assertIn(EvidenceKind.OBSERVABILITY, kinds)

    def test_matrix_scores_expected_profile_above_unrelated_baseline(self) -> None:
        root = make_tmp()
        self.make_repo(root, "tudo-para-ia-identity-platform")
        scan = scan_platform(root, get_platform("identity"))
        admin = next(profile for profile in HUMAN_PROFILES if profile.profile_id == "administrador_empresa")
        financeiro = next(profile for profile in HUMAN_PROFILES if profile.profile_id == "financeiro")
        admin_cell = score_cell(scan, admin)
        finance_cell = score_cell(scan, financeiro)
        self.assertGreater(admin_cell.score, finance_cell.score)
        self.assertTrue(admin_cell.strengths)
        self.assertTrue(admin_cell.gaps)

    def test_platform_report_contains_recommendations_for_missing_git(self) -> None:
        root = make_tmp()
        self.make_repo(root, "tudo-para-ia-identity-platform")
        scan = scan_platform(root, get_platform("identity"))
        cells = build_matrix((scan,))
        report = build_platform_report(scan, cells)
        titles = [item.title for item in report.recommendations]
        self.assertIn("Inicializar Git e configurar origin correto", titles)
        self.assertGreater(report.average_score, 0)


if __name__ == "__main__":
    unittest.main()
