"""
Tests for generate_org_details.py utility module
하누만 (Hanuman), tester on dev4 team
"""

import json
import sys
from pathlib import Path

import pytest

sys.path.insert(0, "/home/jay/workspace/teams/shared")

from generate_org_details import generate_all_sub_team_details  # pyright: ignore[reportMissingImports]


class TestGenerateAllSubTeamDetails:
    """Test suite for generate_all_sub_team_details function"""

    def test_generate_creates_all_sub_teams(self, tmp_path):
        """
        Test that generate_all_sub_team_details() creates files for all 8 dev teams
        (dev1-team.json through dev8-team.json)
        """
        generated = generate_all_sub_team_details(output_dir=tmp_path)

        # Verify 8 dev teams are created
        dev_files = [f for f in generated if "dev" in f and "team.json" in f]
        assert len(dev_files) == 8, f"Expected 8 dev team files, got {len(dev_files)}"

        # Verify each file exists
        for i in range(1, 9):
            expected_file = tmp_path / f"dev{i}-team.json"
            assert expected_file.exists(), f"dev{i}-team.json not created"
            assert str(expected_file) in generated

    def test_output_format(self, tmp_path):
        """
        Test that each generated file has all required keys:
        team_id, team_name, extracted_from, status, type, lead, members_detail
        """
        generate_all_sub_team_details(output_dir=tmp_path)

        required_keys = {
            "team_id",
            "team_name",
            "extracted_from",
            "status",
            "type",
            "lead",
            "members_detail",
        }

        # Check all dev team files
        for i in range(1, 9):
            file_path = tmp_path / f"dev{i}-team.json"
            with open(file_path, "r", encoding="utf-8") as f:
                data = json.load(f)

            # Verify required keys exist
            actual_keys = set(data.keys())
            missing_keys = required_keys - actual_keys
            assert (
                not missing_keys
            ), f"dev{i}-team.json missing keys: {missing_keys}"

            # Verify extracted_from is correct
            assert (
                data["extracted_from"] == "organization-structure.json"
            ), f"dev{i}-team.json has wrong extracted_from value"

            # Verify members_detail is a dict
            assert isinstance(
                data["members_detail"], dict
            ), f"dev{i}-team.json members_detail is not a dict"

    def test_dynamic_no_hardcoding(self, tmp_path):
        """
        Test that the function reads sub_teams dynamically
        The count of dev team files should match the count of sub_teams in org structure
        """
        generated = generate_all_sub_team_details(output_dir=tmp_path)

        # Count created dev team files
        dev_files = [f for f in generated if "dev" in f and "team.json" in f]
        dev_team_count = len(dev_files)

        # Read org structure to verify it has 8 sub_teams
        org_file = Path("/home/jay/workspace/memory/organization-structure.json")
        with open(org_file, "r", encoding="utf-8") as f:
            org_data = json.load(f)

        dev_office = None
        for team in org_data["structure"]["columns"]["teams"]:
            if team["team_id"] == "development-office":
                dev_office = team
                break

        assert dev_office is not None, "development-office not found in org structure"
        expected_sub_teams = len(dev_office.get("sub_teams", []))

        assert (
            dev_team_count == expected_sub_teams
        ), f"Expected {expected_sub_teams} dev teams based on org structure, got {dev_team_count}"

    def test_fallback_to_main_file(self, tmp_path):
        """
        Test that when backup_file points to non-existent path,
        the function still generates files using main data
        """
        # Use non-existent backup path
        non_existent_backup = tmp_path / "non_existent_backup.json"

        generated = generate_all_sub_team_details(
            backup_file=non_existent_backup, output_dir=tmp_path
        )

        # Should still generate 8 dev team files
        dev_files = [f for f in generated if "dev" in f and "team.json" in f]
        assert len(dev_files) == 8, "Failed to generate files when backup doesn't exist"

        # Verify files have expected structure
        for i in range(1, 9):
            file_path = tmp_path / f"dev{i}-team.json"
            assert file_path.exists()
            with open(file_path, "r", encoding="utf-8") as f:
                data = json.load(f)
            assert "team_id" in data
            assert "members_detail" in data

    def test_missing_org_file_raises(self, tmp_path):
        """
        Test that calling with org_file pointing to non-existent path
        raises FileNotFoundError
        """
        non_existent_org = tmp_path / "non_existent_org.json"

        with pytest.raises(FileNotFoundError) as exc_info:
            generate_all_sub_team_details(
                org_file=non_existent_org, output_dir=tmp_path
            )

        assert "메인 조직 파일을 찾을 수 없습니다" in str(exc_info.value) or str(
            non_existent_org
        ) in str(exc_info.value)


class TestSubTeamDetails:
    """Additional tests for specific sub-team file contents"""

    def test_dev1_team_structure(self, tmp_path):
        """Test that dev1-team.json has expected structure and members"""
        generate_all_sub_team_details(output_dir=tmp_path)

        file_path = tmp_path / "dev1-team.json"
        with open(file_path, "r", encoding="utf-8") as f:
            data = json.load(f)

        # Verify team_id and team_name
        assert data["team_id"] == "dev1-team"
        assert data["team_name"] == "개발1팀"
        assert data["status"] == "active"
        assert data["type"] == "physical"

        # Verify lead exists
        assert "lead" in data
        assert isinstance(data["lead"], dict)
        assert data["lead"].get("id") == "hermes"

        # Verify members_detail is populated
        assert len(data["members_detail"]) > 0

    def test_members_detail_structure(self, tmp_path):
        """Test that members_detail has correct structure"""
        generate_all_sub_team_details(output_dir=tmp_path)

        file_path = tmp_path / "dev1-team.json"
        with open(file_path, "r", encoding="utf-8") as f:
            data = json.load(f)

        members = data["members_detail"]
        # dev1-team should have members
        assert isinstance(members, dict)
        assert len(members) > 0

        # Each member entry should have an id as key and member object as value
        for member_id, member_data in members.items():
            assert isinstance(member_id, str)
            assert isinstance(member_data, dict)
            # Member data should have essential fields
            assert "id" in member_data or member_id != "unknown"

    def test_file_count_consistency(self, tmp_path):
        """
        Test that generated file count matches expected output
        (8 dev teams + other teams/centers)
        """
        generated = generate_all_sub_team_details(output_dir=tmp_path)

        # Should generate files for:
        # - 8 dev teams (dev1 through dev8)
        # - marketing, consulting, publishing, design teams
        # - security, genius-thinking teams
        # - qc, devops, gemini, codex, finance, product-strategy, retrospective, publishing centers

        assert len(generated) > 8, "Expected more than 8 files (dev teams + others)"

        # Count by type
        dev_teams = [f for f in generated if "dev" in f and f.endswith("team.json")]

        assert len(dev_teams) == 8, "Expected exactly 8 dev team files"


class TestErrorHandling:
    """Test error handling and edge cases"""

    def test_invalid_org_file_structure(self, tmp_path):
        """Test with malformed org file"""
        bad_org = tmp_path / "bad_org.json"
        bad_org.write_text('{"invalid": "structure"}')

        # Should not raise, but may generate fewer or no files
        # depending on implementation handling of missing structure
        try:
            generated = generate_all_sub_team_details(
                org_file=bad_org, output_dir=tmp_path / "out"
            )
            # If it succeeds, check that output is reasonable
            assert isinstance(generated, list)
        except (FileNotFoundError, KeyError):
            # Both are acceptable error responses
            pass

    def test_output_directory_creation(self, tmp_path):
        """Test that output directory is created if it doesn't exist"""
        output_dir = tmp_path / "nested" / "output" / "dir"
        assert not output_dir.exists()

        generate_all_sub_team_details(output_dir=output_dir)

        assert output_dir.exists(), "Output directory should be created"
        assert any(
            output_dir.glob("*.json")
        ), "Output directory should contain JSON files"

    def test_json_is_valid(self, tmp_path):
        """Test that all generated files are valid JSON"""
        generated = generate_all_sub_team_details(output_dir=tmp_path)

        for file_path in generated:
            path = Path(file_path)
            assert path.exists(), f"{file_path} does not exist"

            # Should be readable and valid JSON
            with open(path, "r", encoding="utf-8") as f:
                data = json.load(f)
            assert isinstance(data, dict), f"{file_path} is not a JSON object"


class TestIntegration:
    """Integration tests with real data"""

    def test_with_real_org_file(self, tmp_path):
        """Test with actual organization-structure.json"""
        result = generate_all_sub_team_details(output_dir=tmp_path)

        assert isinstance(result, list)
        assert len(result) > 0

        # All paths should exist
        for path in result:
            assert Path(path).exists(), f"Generated path {path} does not exist"

    def test_return_value_is_file_paths(self, tmp_path):
        """Test that return value contains valid file paths"""
        result = generate_all_sub_team_details(output_dir=tmp_path)

        assert isinstance(result, list)
        assert all(isinstance(p, str) for p in result), "All returns should be strings"
        assert all(
            Path(p).is_absolute() or Path(p).exists() for p in result
        ), "All paths should be valid"
