"""Standalone authenticated tenant-secret checks."""

from __future__ import annotations

import os
import sys
import unittest
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
loaded_platform = sys.modules.get("platform")
if loaded_platform is not None and not hasattr(loaded_platform, "__path__"):
    del sys.modules["platform"]

from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from sqlalchemy.pool import StaticPool

from config.db import Base
from platform.secrets import secrets_manager
from platform.secrets.encryption import SecretIntegrityError, VersionedAESCipher
from platform.tenants.models import App, Tenant


class SecretChecks(unittest.TestCase):
    def setUp(self):
        self.engine = create_engine(
            "sqlite://", connect_args={"check_same_thread": False},
            poolclass=StaticPool, future=True,
        )
        Base.metadata.create_all(self.engine)
        self.original_factory = secrets_manager.get_control_plane_session
        secrets_manager.get_control_plane_session = lambda: Session(self.engine, future=True)
        with Session(self.engine, future=True) as session:
            session.add_all([
                Tenant(tenant_id="tenant-a", slug="tenant-a", name="Tenant A", status="active", is_active=True),
                Tenant(tenant_id="tenant-b", slug="tenant-b", name="Tenant B", status="active", is_active=True),
                App(app_id="app-a", display_name="App A", module_path="apps.app_a", route_prefix="/app-a", is_active=True),
            ])
            session.commit()
        self.cipher = VersionedAESCipher(
            {"key-1": b"1" * 32, "key-2": b"2" * 32}, "key-2",
        )
        self.manager = secrets_manager.SecretsManager(self.cipher)

    def tearDown(self):
        secrets_manager.get_control_plane_session = self.original_factory
        self.engine.dispose()

    def test_secret_round_trip_returns_metadata_without_value(self):
        self.manager.put_secret(
            tenant_id="tenant-a", app_id="app-a",
            secret_name="api_token", secret_value="very-secret", actor_id="admin",
        )
        self.assertEqual("very-secret", self.manager.get_secret(
            tenant_id="tenant-a", app_id="app-a", secret_name="api_token",
        ))
        metadata = self.manager.list_secret_metadata(tenant_id="tenant-a", app_id="app-a")
        self.assertEqual("key-2", metadata[0]["key_version"])
        self.assertNotIn("secret_value", metadata[0])

    def test_ciphertext_cannot_move_between_tenants(self):
        encrypted = self.cipher.encrypt(
            "secret", aad=self.manager._aad("tenant-a", "app-a", "api_token"),
        )
        with self.assertRaises(SecretIntegrityError):
            self.cipher.decrypt(
                encrypted.ciphertext,
                aad=self.manager._aad("tenant-b", "app-a", "api_token"),
            )

    def test_tampering_is_rejected(self):
        encrypted = self.cipher.encrypt(b"secret".decode(), aad=b"scope")
        tampered = encrypted.ciphertext[:-1] + ("A" if encrypted.ciphertext[-1] != "A" else "B")
        with self.assertRaises(SecretIntegrityError):
            self.cipher.decrypt(tampered, aad=b"scope")

    def test_old_key_version_remains_decryptable(self):
        old_cipher = VersionedAESCipher({"key-1": b"1" * 32}, "key-1")
        encrypted = old_cipher.encrypt("legacy", aad=b"scope")
        self.assertEqual("legacy", self.cipher.decrypt(encrypted.ciphertext, aad=b"scope"))


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