"""Tests for frontend organization management generator."""

import pytest

from prisme.generators import GeneratorContext
from prisme.generators.frontend.organization import FrontendOrgGenerator
from prisme.spec import (
    AuthConfig,
    FieldSpec,
    FieldType,
    ModelSpec,
    StackSpec,
)
from prisme.spec.auth import OrganizationConfig, OrgRole
from prisme.spec.project import ProjectSpec
from prisme.spec.stack import FileStrategy


@pytest.fixture
def org_enabled_spec() -> StackSpec:
    """Stack spec with organization enabled."""
    return StackSpec(
        name="test-org-app",
        models=[
            ModelSpec(
                name="User",
                fields=[
                    FieldSpec(name="email", type=FieldType.STRING, required=True, unique=True),
                    FieldSpec(
                        name="password_hash", type=FieldType.STRING, required=True, hidden=True
                    ),
                    FieldSpec(name="is_active", type=FieldType.BOOLEAN, default=True),
                    FieldSpec(name="roles", type=FieldType.JSON, default=["user"]),
                ],
            )
        ],
    )


@pytest.fixture
def org_enabled_project() -> ProjectSpec:
    """Project spec with organization enabled."""
    return ProjectSpec(
        name="test-org-app",
        auth=AuthConfig(
            enabled=True,
            secret_key="${JWT_SECRET}",
            user_model="User",
            username_field="email",
            organization=OrganizationConfig(
                enabled=True,
                roles=[
                    OrgRole(name="owner", permissions=["*"]),
                    OrgRole(name="member", permissions=["content.view"]),
                ],
                default_role="member",
            ),
        ),
    )


@pytest.fixture
def org_disabled_project() -> ProjectSpec:
    """Project spec with organization disabled."""
    return ProjectSpec(
        name="test-app",
        auth=AuthConfig(enabled=True, secret_key="${JWT_SECRET}"),
    )


class TestFrontendOrgGenerator:
    """Tests for FrontendOrgGenerator."""

    def test_skips_when_org_disabled(self, org_enabled_spec, org_disabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_disabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()
        assert files == []
        assert generator.skip_generation is True

    def test_skips_when_auth_disabled(self, org_enabled_spec, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=ProjectSpec(name="test-app"),
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()
        assert files == []
        assert generator.skip_generation is True

    def test_generates_correct_file_count(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()
        # orgApi.ts, OrgList, OrgCreate, OrgSettings, OrgMembers, OrgSwitcher, OrgInviteAccept, OrgLayout
        assert len(files) == 8

    def test_generates_correct_paths(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()
        file_paths = [str(f.path) for f in files]

        assert any("orgApi.ts" in p for p in file_paths)
        assert any("OrgList.tsx" in p for p in file_paths)
        assert any("OrgCreate.tsx" in p for p in file_paths)
        assert any("OrgSettings.tsx" in p for p in file_paths)
        assert any("OrgMembers.tsx" in p for p in file_paths)
        assert any("OrgSwitcher.tsx" in p for p in file_paths)
        assert any("OrgInviteAccept.tsx" in p for p in file_paths)
        assert any("OrgLayout.tsx" in p for p in file_paths)

    def test_api_client_has_all_functions(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()

        api_file = next(f for f in files if "orgApi.ts" in str(f.path))
        content = api_file.content

        assert "createOrganization" in content
        assert "listMyOrganizations" in content
        assert "getOrganization" in content
        assert "updateOrganization" in content
        assert "deleteOrganization" in content
        assert "listMembers" in content
        assert "addMember" in content
        assert "updateMemberRole" in content
        assert "removeMember" in content
        assert "inviteMember" in content
        assert "acceptInvitation" in content
        assert "leaveOrganization" in content
        assert "listOrgRoles" in content

    def test_api_client_is_always_overwrite(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()

        api_file = next(f for f in files if "orgApi.ts" in str(f.path))
        assert api_file.strategy == FileStrategy.ALWAYS_OVERWRITE

    def test_pages_are_generate_once(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()

        page_files = [f for f in files if ".tsx" in str(f.path)]
        for page_file in page_files:
            assert page_file.strategy == FileStrategy.GENERATE_ONCE

    def test_org_list_page_has_create_button(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()

        list_file = next(f for f in files if "OrgList.tsx" in str(f.path))
        content = list_file.content

        assert "Create Organization" in content
        assert "/organizations/new" in content

    def test_members_page_has_invite_form(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()

        members_file = next(f for f in files if "OrgMembers.tsx" in str(f.path))
        content = members_file.content

        assert "Invite Member" in content
        assert "inviteMember" in content
        assert "owner" in content
        assert "member" in content

    def test_switcher_component_exists(self, org_enabled_spec, org_enabled_project, tmp_path):
        context = GeneratorContext(
            domain_spec=org_enabled_spec,
            output_dir=tmp_path,
            dry_run=True,
            project_spec=org_enabled_project,
        )
        generator = FrontendOrgGenerator(context)
        files = generator.generate_files()

        switcher_file = next(f for f in files if "OrgSwitcher.tsx" in str(f.path))
        content = switcher_file.content

        assert "OrgSwitcher" in content
        assert "listMyOrganizations" in content
