"""Unit tests for OUManager."""

import boto3
import pytest
from moto import mock_aws

from ai_org.core.ou_manager import OUManager


def _setup_org():
    """Create a mock organization with OUs.

    Returns:
        Tuple of (client, root_id, workloads_ou_id, sandbox_ou_id).
    """
    client = boto3.client("organizations", region_name="us-east-1")
    client.create_organization(FeatureSet="ALL")
    root_id = client.list_roots()["Roots"][0]["Id"]
    workloads = client.create_organizational_unit(ParentId=root_id, Name="Workloads")
    sandbox = client.create_organizational_unit(ParentId=root_id, Name="Sandbox")
    return (
        client,
        root_id,
        workloads["OrganizationalUnit"]["Id"],
        sandbox["OrganizationalUnit"]["Id"],
    )


@pytest.mark.unit
@mock_aws
def test_get_ou_tree():
    """get_ou_tree() should return a tree with Root at the top and child OUs."""
    _setup_org()
    mgr = OUManager(profile=None)
    tree = mgr.get_ou_tree()

    assert tree["Type"] == "ROOT"
    child_names = [c["Name"] for c in tree["Children"]]
    assert "Workloads" in child_names
    assert "Sandbox" in child_names


@pytest.mark.unit
@mock_aws
def test_list_ous():
    """list_ous() should return a flat list that includes OUs with their paths."""
    _setup_org()
    mgr = OUManager(profile=None)
    ous = mgr.list_ous()

    names = [ou["Name"] for ou in ous]
    assert "Workloads" in names
    assert "Sandbox" in names
    # Every entry should have a Path key
    for ou in ous:
        assert "Path" in ou


@pytest.mark.unit
@mock_aws
def test_get_ou_details():
    """get_ou_details() should return details for a specific OU."""
    _client, _root_id, workloads_id, _sandbox_id = _setup_org()
    mgr = OUManager(profile=None)
    details = mgr.get_ou_details(workloads_id)

    assert details["Id"] == workloads_id
    assert details["Name"] == "Workloads"
    assert "Arn" in details
    assert "AccountCount" in details
    assert "ChildOUCount" in details


@pytest.mark.unit
@mock_aws
def test_get_ou_by_name_found():
    """get_ou_by_name() should return the OU ID when the name matches."""
    _client, _root_id, workloads_id, _sandbox_id = _setup_org()
    mgr = OUManager(profile=None)
    result = mgr.get_ou_by_name("Workloads")
    assert result == workloads_id


@pytest.mark.unit
@mock_aws
def test_get_ou_by_name_not_found():
    """get_ou_by_name() should return None for a nonexistent OU name."""
    _setup_org()
    mgr = OUManager(profile=None)
    result = mgr.get_ou_by_name("DoesNotExist")
    assert result is None


@pytest.mark.unit
@mock_aws
def test_get_ou_by_name_case_insensitive():
    """get_ou_by_name() should match names case-insensitively."""
    _client, _root_id, workloads_id, _sandbox_id = _setup_org()
    mgr = OUManager(profile=None)
    result = mgr.get_ou_by_name("workloads")
    assert result == workloads_id


@pytest.mark.unit
@mock_aws
def test_format_ou_tree():
    """format_ou_tree() should produce a string containing OU names."""
    _setup_org()
    mgr = OUManager(profile=None)
    formatted = mgr.format_ou_tree()
    assert "Workloads" in formatted
    assert "Sandbox" in formatted


@pytest.mark.unit
@mock_aws
def test_flatten_ou_tree_includes_root():
    """The flattened OU list should include the root node."""
    _setup_org()
    mgr = OUManager(profile=None)
    ous = mgr.list_ous()
    types = [ou["Type"] for ou in ous]
    assert "ROOT" in types
