"""Tests for data management functionality."""

from __future__ import annotations

import tempfile
from pathlib import Path

import pytest

from pytola_sim.lscsim.datamanage.data_models import (
    MaterialLibrary,
    TemplateLibrary,
)
from pytola_sim.lscsim.datamanage.json_analysis import JsonAnalyzer
from pytola_sim.lscsim.datamanage.project_manager import ProjectManager, ProjectTemplate
from pytola_sim.lscsim.models.project_model import Material, SimulationTemplate


class TestProjectManager:
    """Tests for ProjectManager functionality."""

    def test_create_project_success(self) -> None:
        """Test successful project creation."""
        pm = ProjectManager()
        with tempfile.TemporaryDirectory() as tmp_dir:
            project_path = Path(tmp_dir)
            project = pm.create_project(
                name="Test Project",
                description="A test project",
                author="Test User",
                project_path=project_path,
            )

            assert project is not None
            assert project.info.name == "Test Project"
            assert project.info.description == "A test project"
            assert project.info.author == "Test User"

    def test_create_project_with_template(self) -> None:
        """Test project creation with template."""
        pm = ProjectManager()
        with tempfile.TemporaryDirectory() as tmp_dir:
            project_path = Path(tmp_dir)
            project = pm.create_project(
                name="Template Project",
                template_name="Basic Structural Analysis",
                project_path=project_path,
            )

            assert project is not None
            # Check that template data was applied
            assert "analysis_type" in project.config_data
            assert project.config_data["analysis_type"] == "static"

    def test_invalid_project_name(self) -> None:
        """Test project creation with invalid name."""
        pm = ProjectManager()
        project = pm.create_project(name="")  # Empty name
        assert project is None

    def test_get_templates(self) -> None:
        """Test retrieving project templates."""
        pm = ProjectManager()
        templates = pm.get_templates()

        assert len(templates) > 0
        template_names = [t.name for t in templates]
        assert "Basic Structural Analysis" in template_names
        assert "Dynamic Impact Analysis" in template_names

    def test_add_custom_template(self) -> None:
        """Test adding custom project template."""
        pm = ProjectManager()
        template = ProjectTemplate(
            name="Custom Template",
            description="A custom template",
            template_data={"config": {"custom": "value"}},
        )

        result = pm.add_template(template)
        assert result is True

        retrieved = pm.get_template("Custom Template")
        assert retrieved is not None
        assert retrieved.description == "A custom template"


class TestDataModels:
    """Tests for data models functionality."""

    def test_material_library_operations(self) -> None:
        """Test material library operations."""
        library = MaterialLibrary(name="Test Library")

        steel = Material(
            name="Steel",
            density=7850.0,
            young_modulus=200e9,
            poisson_ratio=0.3,
            yield_strength=250e6,
        )

        # Add material
        result = library.add_material(steel, ["Metals", "Common"])
        assert result is True

        # Retrieve material
        retrieved = library.get_material("Steel")
        assert retrieved is not None
        assert retrieved.density == pytest.approx(7850.0)

        # Get materials by category
        metals = library.get_materials_by_category("Metals")
        assert len(metals) == 1
        assert metals[0].name == "Steel"

        # Get categories
        categories = library.get_categories()
        assert "Metals" in categories
        assert "Common" in categories

    def test_template_library_operations(self) -> None:
        """Test template library operations."""
        library = TemplateLibrary(name="Test Template Library")

        template = SimulationTemplate(
            name="Test Template",
            template_data={"analysis": "static"},
            description="A test template",
        )

        # Add template
        result = library.add_template(template, ["Structural", "Static"])
        assert result is True

        # Retrieve template
        retrieved = library.get_template("Test Template")
        assert retrieved is not None
        assert retrieved.description == "A test template"

        # Get templates by category
        structural = library.get_templates_by_category("Structural")
        assert len(structural) == 1
        assert structural[0].name == "Test Template"


class TestJsonAnalysis:
    """Tests for JSON analysis functionality."""

    def test_analyze_valid_json(self) -> None:
        """Test analyzing valid JSON file."""
        analyzer = JsonAnalyzer()

        # Create temporary JSON file
        with tempfile.NamedTemporaryFile(encoding="utf-8", mode="w", suffix=".json", delete=False) as f:
            f.write('{"name": "test", "value": 42, "nested": {"inner": "data"}}')
            temp_file = Path(f.name)

        try:
            result = analyzer.analyze_file(temp_file)
            assert result is not None
            assert result.is_valid is True
            assert result.structure_depth == 3
            assert result.total_objects == 2  # root object + nested object
            assert result.total_primitives == 3  # name, value, inner
        finally:
            temp_file.unlink()

    def test_analyze_invalid_json(self) -> None:
        """Test analyzing invalid JSON file."""
        analyzer = JsonAnalyzer()

        # Create temporary invalid JSON file
        with tempfile.NamedTemporaryFile(encoding="utf-8", mode="w", suffix=".json", delete=False) as f:
            f.write('{"invalid": json}')  # Invalid JSON
            temp_file = Path(f.name)

        try:
            result = analyzer.analyze_file(temp_file)
            assert result is not None
            assert result.is_valid is False
            assert len(result.errors) > 0
        finally:
            temp_file.unlink()

    def test_json_flattening(self) -> None:
        """Test JSON flattening utility."""
        from pytola_sim.lscsim.datamanage.json_analysis import JsonProcessor

        nested_data = {"level1": {"level2": {"value": "test"}, "array": [1, 2, {"nested": "item"}]}}

        flattened = JsonProcessor.flatten_json(nested_data)
        assert "level1_level2_value" in flattened
        assert flattened["level1_level2_value"] == "test"
        assert "level1_array_0" in flattened
        assert flattened["level1_array_0"] == 1


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
