"""
Tests for JSON file storage layer.

Tests the new json_store module that replaced SQLite.
"""

import pytest
import json
import tempfile
import shutil
from pathlib import Path
from datetime import datetime

# Temporarily override DATA_DIR for tests
import tools.storage.json_store as json_store


@pytest.fixture
def temp_storage(tmp_path):
    """Create temporary storage directory for tests."""
    # Save original paths
    original_data_dir = json_store.DATA_DIR
    original_system_dir = json_store.SYSTEM_DIR
    original_projects_dir = json_store.PROJECTS_DIR
    original_teams_dir = json_store.TEAMS_DIR

    # Override with temp paths
    json_store.DATA_DIR = tmp_path / "data"
    json_store.SYSTEM_DIR = json_store.DATA_DIR / "_system"
    json_store.PROJECTS_DIR = json_store.DATA_DIR / "projects"
    json_store.TEAMS_DIR = json_store.DATA_DIR / "teams"
    json_store.Cache.CACHE_DIR = json_store.SYSTEM_DIR / "cache"

    # Initialize directories
    json_store.init_storage()

    yield tmp_path

    # Restore original paths
    json_store.DATA_DIR = original_data_dir
    json_store.SYSTEM_DIR = original_system_dir
    json_store.PROJECTS_DIR = original_projects_dir
    json_store.TEAMS_DIR = original_teams_dir
    json_store.Cache.CACHE_DIR = original_system_dir / "cache"


class TestCache:
    """Tests for TTL-based cache."""

    def test_cache_set_and_get(self, temp_storage):
        """Test basic cache operations."""
        json_store.Cache.set("test_key", {"foo": "bar"}, ttl=60)
        result = json_store.Cache.get("test_key")

        assert result == {"foo": "bar"}

    def test_cache_expiry(self, temp_storage):
        """Test that expired cache returns None."""
        import time
        json_store.Cache.set("expired_key", "value", ttl=1)
        time.sleep(1.1)  # Wait for expiry
        result = json_store.Cache.get("expired_key")

        assert result is None

    def test_cache_delete(self, temp_storage):
        """Test cache deletion."""
        json_store.Cache.set("delete_me", "value")
        json_store.Cache.delete("delete_me")
        result = json_store.Cache.get("delete_me")

        assert result is None

    def test_cache_clear_all(self, temp_storage):
        """Test clearing all cache."""
        json_store.Cache.set("key1", "value1")
        json_store.Cache.set("key2", "value2")
        json_store.Cache.clear_all()

        assert json_store.Cache.get("key1") is None
        assert json_store.Cache.get("key2") is None


class TestProjects:
    """Tests for project operations."""

    def test_create_project(self, temp_storage):
        """Test project creation."""
        project = json_store.Projects.create(
            id="test-project",
            name="Test Project",
            description="A test project"
        )

        assert project["id"] == "test-project"
        assert project["name"] == "Test Project"
        assert project["status"] == "active"

    def test_get_project(self, temp_storage):
        """Test project retrieval."""
        json_store.Projects.create(id="get-test", name="Get Test")
        project = json_store.Projects.get("get-test")

        assert project is not None
        assert project["name"] == "Get Test"

    def test_list_projects(self, temp_storage):
        """Test listing projects."""
        json_store.Projects.create(id="proj1", name="Project 1")
        json_store.Projects.create(id="proj2", name="Project 2")

        projects = json_store.Projects.list()

        assert len(projects) == 2

    def test_update_project(self, temp_storage):
        """Test project update."""
        json_store.Projects.create(id="update-test", name="Original")
        updated = json_store.Projects.update("update-test", name="Updated")

        assert updated["name"] == "Updated"

    def test_delete_project(self, temp_storage):
        """Test project deletion (archives)."""
        json_store.Projects.create(id="delete-test", name="Delete Me")
        result = json_store.Projects.delete("delete-test")

        assert result is True
        assert json_store.Projects.get("delete-test") is None

    def test_project_creates_token_structure(self, temp_storage):
        """Test that project creation initializes token folders."""
        json_store.Projects.create(id="token-test", name="Token Test")

        tokens_dir = json_store.PROJECTS_DIR / "token-test" / "tokens"
        assert tokens_dir.exists()
        assert (tokens_dir / "colors.json").exists()
        assert (tokens_dir / "spacing.json").exists()


class TestTokens:
    """Tests for token operations."""

    def test_get_all_tokens(self, temp_storage):
        """Test getting all tokens for a project."""
        json_store.Projects.create(id="tokens-proj", name="Tokens Project")
        tokens = json_store.Tokens.get_all("tokens-proj")

        assert "colors" in tokens
        assert "spacing" in tokens
        assert "typography" in tokens

    def test_set_and_get_tokens(self, temp_storage):
        """Test setting and getting tokens by type."""
        json_store.Projects.create(id="set-tokens", name="Set Tokens")

        json_store.Tokens.set_by_type("set-tokens", "colors", {
            "primary": "#3B82F6",
            "secondary": "#10B981"
        })

        colors = json_store.Tokens.get_by_type("set-tokens", "colors")

        assert colors["primary"] == "#3B82F6"
        assert colors["secondary"] == "#10B981"

    def test_merge_tokens_last_strategy(self, temp_storage):
        """Test merging tokens with LAST strategy."""
        json_store.Projects.create(id="merge-test", name="Merge Test")

        json_store.Tokens.set_by_type("merge-test", "colors", {
            "primary": "#old",
            "secondary": "#keep"
        })

        merged = json_store.Tokens.merge("merge-test", "colors", {
            "primary": "#new",
            "tertiary": "#added"
        }, strategy="LAST")

        assert merged["primary"] == "#new"
        assert merged["secondary"] == "#keep"
        assert merged["tertiary"] == "#added"


class TestComponents:
    """Tests for component operations."""

    def test_upsert_components(self, temp_storage):
        """Test bulk component upsert."""
        json_store.Projects.create(id="comp-proj", name="Component Project")

        count = json_store.Components.upsert("comp-proj", [
            {"name": "Button", "properties": {"variant": "primary"}},
            {"name": "Card", "properties": {"shadow": "md"}}
        ])

        assert count == 2

    def test_list_components(self, temp_storage):
        """Test listing components."""
        json_store.Projects.create(id="list-comp", name="List Components")
        json_store.Components.upsert("list-comp", [
            {"name": "Button"},
            {"name": "Input"}
        ])

        components = json_store.Components.list("list-comp")

        assert len(components) == 2
        names = [c["name"] for c in components]
        assert "Button" in names
        assert "Input" in names


class TestActivityLog:
    """Tests for activity logging."""

    def test_log_activity(self, temp_storage):
        """Test logging an activity."""
        json_store.ActivityLog.log(
            action="test_action",
            entity_type="test",
            entity_name="Test Entity",
            project_id="test-proj"
        )

        recent = json_store.ActivityLog.recent(limit=1)

        assert len(recent) == 1
        assert recent[0]["action"] == "test_action"

    def test_activity_auto_category(self, temp_storage):
        """Test that activity auto-detects category."""
        json_store.ActivityLog.log(action="extract_tokens")

        recent = json_store.ActivityLog.recent(limit=1)

        assert recent[0]["category"] == "design_system"


class TestTeams:
    """Tests for team operations."""

    def test_create_team(self, temp_storage):
        """Test team creation."""
        team = json_store.Teams.create(
            id="test-team",
            name="Test Team",
            description="A test team"
        )

        assert team["id"] == "test-team"
        assert team["name"] == "Test Team"

    def test_add_member(self, temp_storage):
        """Test adding team member."""
        json_store.Teams.create(id="member-team", name="Member Team")
        json_store.Teams.add_member("member-team", "user-123", "DEVELOPER")

        members = json_store.Teams.get_members("member-team")

        assert len(members) == 1
        assert members[0]["user_id"] == "user-123"
        assert members[0]["role"] == "DEVELOPER"

    def test_get_user_role(self, temp_storage):
        """Test getting user role in team."""
        json_store.Teams.create(id="role-team", name="Role Team")
        json_store.Teams.add_member("role-team", "admin-user", "SUPER_ADMIN")

        role = json_store.Teams.get_user_role("role-team", "admin-user")

        assert role == "SUPER_ADMIN"


class TestSyncHistory:
    """Tests for sync history."""

    def test_sync_lifecycle(self, temp_storage):
        """Test sync start and complete."""
        json_store.Projects.create(id="sync-proj", name="Sync Project")

        sync_id = json_store.SyncHistory.start("sync-proj", "tokens")
        json_store.SyncHistory.complete("sync-proj", sync_id, "success", items_synced=10)

        recent = json_store.SyncHistory.recent("sync-proj", limit=5)

        # Should have both start and complete records
        completed = [r for r in recent if r.get("status") == "success"]
        assert len(completed) >= 1


class TestStats:
    """Tests for storage statistics."""

    def test_get_stats(self, temp_storage):
        """Test getting storage stats."""
        json_store.Projects.create(id="stats-proj", name="Stats Project")
        json_store.Teams.create(id="stats-team", name="Stats Team")

        stats = json_store.get_stats()

        # Stats count directories, verify basic structure
        assert "projects" in stats
        assert "teams" in stats
        assert "total_size_mb" in stats
        assert stats["total_size_mb"] >= 0
