import json
import os
import sqlite3
import tempfile
import unittest
import uuid
from pathlib import Path

import web_sentinel.license.runtime_bridge as runtime_bridge
from web_sentinel.subscription import SubscriptionTier


class TestLicenseSysOpBootstrap(unittest.TestCase):
    def setUp(self) -> None:
        self._tmpdir_obj = tempfile.TemporaryDirectory()
        self.temp_home = Path(self._tmpdir_obj.name)
        os.environ["HOME"] = str(self.temp_home)
        os.environ["USERPROFILE"] = str(self.temp_home)
        runtime_bridge._GLOBAL_BRIDGE = None

        self._prepare_sysop_account()

    def tearDown(self) -> None:
        # Fermer explicitement toutes les connexions de base de données
        import gc
        from web_sentinel.auth import AuthManager
        from web_sentinel.license.runtime_bridge import get_license_bridge
        
        # Forcer la fermeture des gestionnaires
        try:
            bridge = get_license_bridge()
            if hasattr(bridge, '_auth_manager') and bridge._auth_manager:
                auth_manager = bridge._auth_manager
                if hasattr(auth_manager, '_db_path') and hasattr(auth_manager, '_connection'):
                    if auth_manager._connection:
                        auth_manager._connection.close()
                        auth_manager._connection = None
        except:
            pass
        
        # Forcer le garbage collection
        gc.collect()
        
        runtime_bridge._GLOBAL_BRIDGE = None
        
        # Essayer de nettoyer avec retry sur Windows
        import time
        for i in range(3):
            try:
                self._tmpdir_obj.cleanup()
                break
            except PermissionError:
                if i < 2:
                    time.sleep(0.1)
                    gc.collect()
                else:
                    # Dernière chance, ignorer l'erreur
                    pass
        
        os.environ.pop("HOME", None)
        os.environ.pop("USERPROFILE", None)

    def _prepare_sysop_account(self) -> None:
        db_path = Path.home() / ".web-sentinel" / "auth.db"
        db_path.parent.mkdir(parents=True, exist_ok=True)
        with sqlite3.connect(db_path) as conn:
            conn.execute("CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, email TEXT, data TEXT)")
            user_payload = {
                "id": str(uuid.uuid4()),
                "email": "bruno@taaazzz-prog.fr",
                "role": "sysop",
                "is_active": True,
                "preferences": {"is_developer": True},
            }
            conn.execute(
                "INSERT INTO users (id, email, data) VALUES (?, ?, ?)",
                (user_payload["id"], user_payload["email"], json.dumps(user_payload)),
            )

        session_path = Path.home() / ".web-sentinel" / "auth-config.json"
        session_path.write_text(
            json.dumps(
                {
                    "session_id": str(uuid.uuid4()),
                    "user_data": user_payload,
                    "access_token": "local-token",
                    "remember_me": True,
                }
            ),
            encoding="utf-8",
        )

    def test_initialize_promotes_sysop_license(self) -> None:
        result = runtime_bridge.initialize_license_system()
        self.assertTrue(result)

        bridge = runtime_bridge.get_license_bridge()
        manager = bridge.subscription_manager

        self.assertEqual(manager.tier, SubscriptionTier.SYSOP)
        self.assertTrue(manager.can_use_invasive_tests())
        self.assertTrue(manager.can_export_html())
        self.assertTrue(manager.can_manage_users())
        self.assertTrue(manager.can_use_api())

        licence_path = Path.home() / ".web-sentinel" / "license.lic"
        self.assertTrue(licence_path.exists())
        data = json.loads(licence_path.read_text(encoding="utf-8"))
        self.assertEqual(data["config"]["subscription"]["tier"], "SYSOP")

    def test_logout_falls_back_to_free(self) -> None:
        runtime_bridge.initialize_license_system()
        bridge = runtime_bridge.get_license_bridge()
        self.assertEqual(bridge.subscription_manager.tier, SubscriptionTier.SYSOP)

        session_path = Path.home() / ".web-sentinel" / "auth-config.json"
        if session_path.exists():
            session_path.unlink()

        runtime_bridge._GLOBAL_BRIDGE = None
        result = runtime_bridge.initialize_license_system()
        self.assertTrue(result)
        bridge = runtime_bridge.get_license_bridge()
        self.assertEqual(bridge.subscription_manager.tier, SubscriptionTier.FREE)

        licence_path = Path.home() / ".web-sentinel" / "license.lic"
        data = json.loads(licence_path.read_text(encoding="utf-8"))
        self.assertEqual(data["config"]["subscription"]["tier"], "FREE")

    def test_member_without_subscription_keeps_free(self) -> None:
        session_path = Path.home() / ".web-sentinel" / "auth-config.json"
        session_payload = {
            "session_id": str(uuid.uuid4()),
            "user_data": {
                "id": str(uuid.uuid4()),
                "email": "member@example.com",
                "role": "member",
                "is_active": True,
            },
            "access_token": "local-token",
            "remember_me": True,
        }
        session_path.write_text(json.dumps(session_payload), encoding="utf-8")

        runtime_bridge._GLOBAL_BRIDGE = None
        self.assertTrue(runtime_bridge.initialize_license_system())
        bridge = runtime_bridge.get_license_bridge()
        self.assertEqual(bridge.subscription_manager.tier, SubscriptionTier.FREE)

    def test_pro_subscription_enables_pro_license(self) -> None:
        session_path = Path.home() / ".web-sentinel" / "auth-config.json"
        user_id = str(uuid.uuid4())
        email = "comptePro@sentinel.fr"
        session_path.write_text(
            json.dumps(
                {
                    "session_id": str(uuid.uuid4()),
                    "user_data": {
                        "id": user_id,
                        "email": email,
                        "role": "member",
                        "is_active": True,
                    },
                    "access_token": "local-token",
                    "remember_me": True,
                }
            ),
            encoding="utf-8",
        )

        db_path = Path.home() / ".web-sentinel" / "auth.db"
        db_path.parent.mkdir(parents=True, exist_ok=True)
        with sqlite3.connect(db_path) as conn:
            conn.execute(
                "CREATE TABLE IF NOT EXISTS user_subscriptions (user_id TEXT, email TEXT, tier TEXT, expires_at TEXT, updated_at TEXT)"
            )
            conn.execute("DELETE FROM user_subscriptions")
            conn.execute(
                "INSERT INTO user_subscriptions (user_id, email, tier, expires_at, updated_at) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)",
                (user_id, email, "pro", "2099-12-31T00:00:00+00:00"),
            )

        runtime_bridge._GLOBAL_BRIDGE = None
        self.assertTrue(runtime_bridge.initialize_license_system())
        bridge = runtime_bridge.get_license_bridge()
        self.assertEqual(bridge.subscription_manager.tier, SubscriptionTier.PRO)
        self.assertTrue(bridge.subscription_manager.can_use_invasive_tests())
        self.assertTrue(bridge.subscription_manager.can_export_html())
        self.assertFalse(bridge.subscription_manager.can_manage_users())
        self.assertFalse(bridge.subscription_manager.can_use_api())

        licence_path = Path.home() / ".web-sentinel" / "license.lic"
        data = json.loads(licence_path.read_text(encoding="utf-8"))
        self.assertEqual(data["config"]["subscription"]["tier"], "PRO")

    def test_enterprise_subscription_enables_enterprise_license(self) -> None:
        session_path = Path.home() / ".web-sentinel" / "auth-config.json"
        user_id = str(uuid.uuid4())
        email = "compteEntreprise@sentinel.fr"
        session_path.write_text(
            json.dumps(
                {
                    "session_id": str(uuid.uuid4()),
                    "user_data": {
                        "id": user_id,
                        "email": email,
                        "role": "member",
                        "is_active": True,
                    },
                    "access_token": "local-token",
                    "remember_me": True,
                }
            ),
            encoding="utf-8",
        )

        db_path = Path.home() / ".web-sentinel" / "auth.db"
        db_path.parent.mkdir(parents=True, exist_ok=True)
        with sqlite3.connect(db_path) as conn:
            conn.execute(
                "CREATE TABLE IF NOT EXISTS user_subscriptions (user_id TEXT, email TEXT, tier TEXT, expires_at TEXT, updated_at TEXT)"
            )
            conn.execute("DELETE FROM user_subscriptions")
            conn.execute(
                "INSERT INTO user_subscriptions (user_id, email, tier, expires_at, updated_at) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)",
                (user_id, email, "enterprise", "2099-12-31T00:00:00+00:00"),
            )

        runtime_bridge._GLOBAL_BRIDGE = None
        self.assertTrue(runtime_bridge.initialize_license_system())
        bridge = runtime_bridge.get_license_bridge()
        self.assertEqual(bridge.subscription_manager.tier, SubscriptionTier.ENTERPRISE)
        self.assertTrue(bridge.subscription_manager.can_use_invasive_tests())
        self.assertTrue(bridge.subscription_manager.can_export_html())
        self.assertTrue(bridge.subscription_manager.can_manage_users())
        self.assertTrue(bridge.subscription_manager.can_use_api())

        licence_path = Path.home() / ".web-sentinel" / "license.lic"
        data = json.loads(licence_path.read_text(encoding="utf-8"))
        self.assertEqual(data["config"]["subscription"]["tier"], "ENTERPRISE")


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