"""Standalone measured storage and quota checks."""

from __future__ import annotations

import sys
import tempfile
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.storage import service
from platform.tenants.models import App, Tenant, TenantLimit


class StorageChecks(unittest.TestCase):
    def setUp(self):
        self.temp_dir = tempfile.TemporaryDirectory()
        self.engine = create_engine(
            "sqlite://", connect_args={"check_same_thread": False},
            poolclass=StaticPool, future=True,
        )
        Base.metadata.create_all(self.engine)
        self.original_factory = service.get_control_plane_session
        self.original_root = service.STORAGE_ROOT
        service.get_control_plane_session = lambda: Session(self.engine, future=True)
        service.STORAGE_ROOT = Path(self.temp_dir.name)
        with Session(self.engine, future=True) as session:
            session.add(Tenant(
                tenant_id="tenant-a", slug="tenant-a", name="Tenant A",
                storage_key="tenant-a", status="active", is_active=True,
            ))
            session.add(App(
                app_id="app-a", display_name="App A",
                module_path="apps.app_a", route_prefix="/app-a", is_active=True,
            ))
            session.add(TenantLimit(
                tenant_id="tenant-a", app_id=None, limit_name="storage_mb",
                limit_value=1, overage_policy="block",
            ))
            session.commit()

    def tearDown(self):
        service.get_control_plane_session = self.original_factory
        service.STORAGE_ROOT = self.original_root
        self.engine.dispose()
        self.temp_dir.cleanup()

    def test_write_is_measured_and_replacement_uses_size_delta(self):
        service.write_bytes(
            tenant_id="tenant-a", app_id="app-a",
            relative_path="invoices/a.pdf", data=b"a" * 100,
        )
        service.write_bytes(
            tenant_id="tenant-a", app_id="app-a",
            relative_path="invoices/a.pdf", data=b"b" * 80,
        )
        snapshot = service.get_storage_snapshot("tenant-a")
        self.assertEqual(80, snapshot.used_bytes)
        self.assertEqual("available", snapshot.status)

    def test_over_limit_write_is_blocked_and_not_created(self):
        with self.assertRaises(service.StorageQuotaExceeded):
            service.write_bytes(
                tenant_id="tenant-a", app_id="app-a",
                relative_path="large.bin", data=b"x" * (1024 * 1024 + 1),
            )
        self.assertFalse((Path(self.temp_dir.name) / "tenant-a" / "app-a" / "large.bin").exists())

    def test_path_traversal_is_rejected(self):
        with self.assertRaises(ValueError):
            service.write_bytes(
                tenant_id="tenant-a", app_id="app-a",
                relative_path="../../outside.bin", data=b"x",
            )


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