"""
Organization Settings Router — per-org IAM enforcement configuration.

Endpoints:
- GET  /api/v1/organization/settings                — get settings
- PUT  /api/v1/organization/settings                — upsert settings
- POST /api/v1/organization/settings/initialize-enforcement — first-time setup
"""

from fastapi import APIRouter, Depends, HTTPException, status, Request
import structlog
from sqlalchemy.orm import Session

from control_plane_api.app.database import get_db
from control_plane_api.app.middleware.auth import get_current_organization
from control_plane_api.app.services.settings_service import SettingsService
from control_plane_api.app.schemas.organization_settings import (
    OrganizationSettingsResponse,
    OrganizationSettingsUpdate,
    InitializeEnforcementResponse,
)

logger = structlog.get_logger()

router = APIRouter(tags=["Organization Settings"])


def get_settings_service(
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
) -> SettingsService:
    return SettingsService(organization_id=organization["id"], db=db)


def _settings_to_response(settings) -> OrganizationSettingsResponse:
    """Convert ORM model to response, handling datetime serialization."""
    return OrganizationSettingsResponse(
        organization_id=settings.organization_id,
        enforcement_enabled=settings.enforcement_enabled,
        enforcement_mode=settings.enforcement_mode,
        default_policy_id=settings.default_policy_id,
        created_at=settings.created_at.isoformat() if settings.created_at else None,
        updated_at=settings.updated_at.isoformat() if settings.updated_at else None,
    )


@router.get("/settings", response_model=OrganizationSettingsResponse)
async def get_organization_settings(
    service: SettingsService = Depends(get_settings_service),
):
    """Get IAM enforcement settings for the current organization."""
    settings = await service.get_settings()
    if not settings:
        # Return defaults if no settings exist yet
        return OrganizationSettingsResponse(
            organization_id=service.organization_id,
            enforcement_enabled=False,
            enforcement_mode="monitoring",
        )
    return _settings_to_response(settings)


@router.put("/settings", response_model=OrganizationSettingsResponse)
async def update_organization_settings(
    update: OrganizationSettingsUpdate,
    service: SettingsService = Depends(get_settings_service),
):
    """Update IAM enforcement settings for the current organization."""
    settings = service.upsert_settings(
        enforcement_enabled=update.enforcement_enabled,
        enforcement_mode=update.enforcement_mode,
    )
    return _settings_to_response(settings)


@router.post(
    "/settings/initialize-enforcement",
    response_model=InitializeEnforcementResponse,
    status_code=status.HTTP_201_CREATED,
)
async def initialize_enforcement(
    request: Request,
    service: SettingsService = Depends(get_settings_service),
    organization: dict = Depends(get_current_organization),
):
    """
    First-time enforcement setup.

    Creates the default "Administrator Access" policy, binds it to the Admin role,
    and enables enforcement in monitoring mode.
    """
    # Check if already initialized
    existing = await service.get_settings()
    if existing and existing.default_policy_id:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Enforcement already initialized for this organization",
        )

    # Create default admin policy via enforcer client
    auth_token = getattr(request.state, "kubiya_token", None)
    auth_type = getattr(request.state, "kubiya_auth_type", "UserKey")

    default_policy_id = None
    default_policy_name = "Administrator Access"

    try:
        from control_plane_api.app.lib.policy_enforcer_client import (
            create_policy_enforcer_client,
            PolicyCreate,
        )
        from control_plane_api.app.services.policy_service import PolicyService

        async with create_policy_enforcer_client(api_key=auth_token, auth_type=auth_type) as enforcer_client:
            # Create the admin policy
            admin_policy = PolicyCreate(
                name=default_policy_name,
                description="System policy: grants full tool access to Administrators",
                policy_content='package administrator_access\ndefault allow = true',
                enabled=True,
                tags=["system", "administrator"],
            )

            created = await enforcer_client.policies.create(admin_policy)
            default_policy_id = created.id

            # Create role-based association
            policy_service = PolicyService(
                organization_id=organization["id"],
                enforcer_client=enforcer_client,
                db=service.db,
            )
            from control_plane_api.app.services.policy_service import PolicyAssociationCreate
            # Use a well-known sentinel UUID for the "Admin" role association.
            # The role name is stored in metadata for display / resolution.
            ADMIN_ROLE_SENTINEL = "00000000-0000-0000-0000-000000000001"

            await policy_service.create_association(
                PolicyAssociationCreate(
                    policy_id=default_policy_id,
                    policy_name=default_policy_name,
                    entity_type="role",
                    entity_id=ADMIN_ROLE_SENTINEL,
                    enabled=True,
                    metadata={"role_name": "Admin", "system": True},
                ),
                created_by="system",
            )

    except Exception as e:
        logger.error("enforcement_initialization_failed", error=str(e))
        # Continue without the policy — settings can still be saved
        default_policy_id = f"pending-{organization['id']}"

    # Save settings
    settings = service.upsert_settings(
        enforcement_enabled=True,
        enforcement_mode="monitoring",
        default_policy_id=default_policy_id,
    )

    return InitializeEnforcementResponse(
        organization_id=settings.organization_id,
        enforcement_enabled=settings.enforcement_enabled,
        enforcement_mode=settings.enforcement_mode,
        default_policy_id=default_policy_id or "",
        default_policy_name=default_policy_name,
        message="Enforcement initialized. Admin Access policy created and bound to Admin role.",
    )
