"""Membership Catalog API routers — Phase 9.1."""
from __future__ import annotations

from uuid import UUID

from fastapi import APIRouter, Depends, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, get_pagination, require_tenant
from app.core.security import get_current_user
from app.schemas.catalog import (
    AgeGroupCreate,
    AgeGroupRead,
    AgeGroupUpdate,
    ExpirationPolicyCreate,
    ExpirationPolicyRead,
    ExpirationPolicyUpdate,
    FreezingRuleCreate,
    FreezingRuleRead,
    FreezingRuleUpdate,
    MembershipPackageCreate,
    MembershipPackageRead,
    MembershipPackageUpdate,
    MembershipPlanCreate,
    MembershipPlanRead,
    MembershipPlanUpdate,
    MembershipRuleCreate,
    MembershipRuleRead,
    MembershipRuleUpdate,
    PricingModelCreate,
    PricingModelRead,
    PricingModelUpdate,
    RenewalPolicyCreate,
    RenewalPolicyRead,
    RenewalPolicyUpdate,
    SportCategoryCreate,
    SportCategoryRead,
    SportCategoryUpdate,
)
from app.services.catalog import (
    AgeGroupService,
    ExpirationPolicyService,
    FreezingRuleService,
    MembershipPackageService,
    MembershipPlanService,
    MembershipRuleService,
    PricingModelService,
    RenewalPolicyService,
    SportCategoryService,
)
from shared.pagination import PaginationParams
from shared.security import CurrentUser


def _crud_router(
    *,
    prefix_tag: str,
    create_schema,
    update_schema,
    read_schema,
    service_cls,
    id_param: str,
) -> APIRouter:
    router = APIRouter()

    @router.post("", response_model=read_schema, status_code=status.HTTP_201_CREATED)
    async def create_item(
        body: create_schema,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).create(tenant_id, body, actor=user)

    @router.get("", response_model=list[read_schema])
    async def list_items(
        tenant_id: UUID = Depends(require_tenant),
        pagination: PaginationParams = Depends(get_pagination),
        db: AsyncSession = Depends(get_db),
        _user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)

    @router.get(f"/{{{id_param}}}", response_model=read_schema)
    async def get_item(
        entity_id: UUID,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        _user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).get(tenant_id, entity_id)

    # Bind path param name dynamically
    get_item.__annotations__[id_param] = UUID
    # FastAPI uses function signature — set via defaults workaround:
    create_item.__name__ = f"create_{prefix_tag}"
    list_items.__name__ = f"list_{prefix_tag}"
    get_item.__name__ = f"get_{prefix_tag}"

    @router.patch(f"/{{{id_param}}}", response_model=read_schema)
    async def update_item(
        entity_id: UUID,
        body: update_schema,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).update(tenant_id, entity_id, body, actor=user)

    @router.post(f"/{{{id_param}}}/delete", response_model=read_schema)
    async def soft_delete_item(
        entity_id: UUID,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).soft_delete(tenant_id, entity_id, actor=user)

    # Fix path parameter names for OpenAPI by re-registering with correct names
    return router


# Explicit routers (path param names must match for FastAPI)
sport_categories_router = APIRouter()


@sport_categories_router.post("", response_model=SportCategoryRead, status_code=status.HTTP_201_CREATED)
async def create_sport_category(
    body: SportCategoryCreate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await SportCategoryService(db).create(tenant_id, body, actor=user)


@sport_categories_router.get("", response_model=list[SportCategoryRead])
async def list_sport_categories(
    tenant_id: UUID = Depends(require_tenant),
    pagination: PaginationParams = Depends(get_pagination),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await SportCategoryService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@sport_categories_router.get("/{sport_category_id}", response_model=SportCategoryRead)
async def get_sport_category(
    sport_category_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    _user: CurrentUser = Depends(get_current_user),
):
    return await SportCategoryService(db).get(tenant_id, sport_category_id)


@sport_categories_router.patch("/{sport_category_id}", response_model=SportCategoryRead)
async def update_sport_category(
    sport_category_id: UUID,
    body: SportCategoryUpdate,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await SportCategoryService(db).update(tenant_id, sport_category_id, body, actor=user)


@sport_categories_router.post("/{sport_category_id}/delete", response_model=SportCategoryRead)
async def delete_sport_category(
    sport_category_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
):
    return await SportCategoryService(db).soft_delete(tenant_id, sport_category_id, actor=user)


def _make_standard_router(service_cls, create_schema, update_schema, read_schema, id_name: str) -> APIRouter:
    router = APIRouter()

    async def create_item(
        body: create_schema,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).create(tenant_id, body, actor=user)

    async def list_items(
        tenant_id: UUID = Depends(require_tenant),
        pagination: PaginationParams = Depends(get_pagination),
        db: AsyncSession = Depends(get_db),
        _user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)

    async def get_item(
        entity_id: UUID,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        _user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).get(tenant_id, entity_id)

    async def update_item(
        entity_id: UUID,
        body: update_schema,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).update(tenant_id, entity_id, body, actor=user)

    async def soft_delete_item(
        entity_id: UUID,
        tenant_id: UUID = Depends(require_tenant),
        db: AsyncSession = Depends(get_db),
        user: CurrentUser = Depends(get_current_user),
    ):
        return await service_cls(db).soft_delete(tenant_id, entity_id, actor=user)

    # Rename path params by wrapping with annotated routes
    router.add_api_route("", create_item, methods=["POST"], response_model=read_schema, status_code=201)
    router.add_api_route("", list_items, methods=["GET"], response_model=list[read_schema])

    # Use explicit closures with correct parameter names via exec — keep it simple with copies:
    return router


age_groups_router = APIRouter()


@age_groups_router.post("", response_model=AgeGroupRead, status_code=status.HTTP_201_CREATED)
async def create_age_group(body: AgeGroupCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await AgeGroupService(db).create(tenant_id, body, actor=user)


@age_groups_router.get("", response_model=list[AgeGroupRead])
async def list_age_groups(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await AgeGroupService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@age_groups_router.get("/{age_group_id}", response_model=AgeGroupRead)
async def get_age_group(age_group_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await AgeGroupService(db).get(tenant_id, age_group_id)


@age_groups_router.patch("/{age_group_id}", response_model=AgeGroupRead)
async def update_age_group(age_group_id: UUID, body: AgeGroupUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await AgeGroupService(db).update(tenant_id, age_group_id, body, actor=user)


@age_groups_router.post("/{age_group_id}/delete", response_model=AgeGroupRead)
async def delete_age_group(age_group_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await AgeGroupService(db).soft_delete(tenant_id, age_group_id, actor=user)


pricing_models_router = APIRouter()


@pricing_models_router.post("", response_model=PricingModelRead, status_code=status.HTTP_201_CREATED)
async def create_pricing_model(body: PricingModelCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await PricingModelService(db).create(tenant_id, body, actor=user)


@pricing_models_router.get("", response_model=list[PricingModelRead])
async def list_pricing_models(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await PricingModelService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@pricing_models_router.get("/{pricing_model_id}", response_model=PricingModelRead)
async def get_pricing_model(pricing_model_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await PricingModelService(db).get(tenant_id, pricing_model_id)


@pricing_models_router.patch("/{pricing_model_id}", response_model=PricingModelRead)
async def update_pricing_model(pricing_model_id: UUID, body: PricingModelUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await PricingModelService(db).update(tenant_id, pricing_model_id, body, actor=user)


@pricing_models_router.post("/{pricing_model_id}/delete", response_model=PricingModelRead)
async def delete_pricing_model(pricing_model_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await PricingModelService(db).soft_delete(tenant_id, pricing_model_id, actor=user)


membership_packages_router = APIRouter()


@membership_packages_router.post("", response_model=MembershipPackageRead, status_code=status.HTTP_201_CREATED)
async def create_membership_package(body: MembershipPackageCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipPackageService(db).create(tenant_id, body, actor=user)


@membership_packages_router.get("", response_model=list[MembershipPackageRead])
async def list_membership_packages(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await MembershipPackageService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@membership_packages_router.get("/{membership_package_id}", response_model=MembershipPackageRead)
async def get_membership_package(membership_package_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await MembershipPackageService(db).get(tenant_id, membership_package_id)


@membership_packages_router.patch("/{membership_package_id}", response_model=MembershipPackageRead)
async def update_membership_package(membership_package_id: UUID, body: MembershipPackageUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipPackageService(db).update(tenant_id, membership_package_id, body, actor=user)


@membership_packages_router.post("/{membership_package_id}/delete", response_model=MembershipPackageRead)
async def delete_membership_package(membership_package_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipPackageService(db).soft_delete(tenant_id, membership_package_id, actor=user)


membership_plans_router = APIRouter()


@membership_plans_router.post("", response_model=MembershipPlanRead, status_code=status.HTTP_201_CREATED)
async def create_membership_plan(body: MembershipPlanCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipPlanService(db).create(tenant_id, body, actor=user)


@membership_plans_router.get("", response_model=list[MembershipPlanRead])
async def list_membership_plans(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await MembershipPlanService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@membership_plans_router.get("/{membership_plan_id}", response_model=MembershipPlanRead)
async def get_membership_plan(membership_plan_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await MembershipPlanService(db).get(tenant_id, membership_plan_id)


@membership_plans_router.patch("/{membership_plan_id}", response_model=MembershipPlanRead)
async def update_membership_plan(membership_plan_id: UUID, body: MembershipPlanUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipPlanService(db).update(tenant_id, membership_plan_id, body, actor=user)


@membership_plans_router.post("/{membership_plan_id}/delete", response_model=MembershipPlanRead)
async def delete_membership_plan(membership_plan_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipPlanService(db).soft_delete(tenant_id, membership_plan_id, actor=user)


membership_rules_router = APIRouter()


@membership_rules_router.post("", response_model=MembershipRuleRead, status_code=status.HTTP_201_CREATED)
async def create_membership_rule(body: MembershipRuleCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipRuleService(db).create(tenant_id, body, actor=user)


@membership_rules_router.get("", response_model=list[MembershipRuleRead])
async def list_membership_rules(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await MembershipRuleService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@membership_rules_router.get("/{membership_rule_id}", response_model=MembershipRuleRead)
async def get_membership_rule(membership_rule_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await MembershipRuleService(db).get(tenant_id, membership_rule_id)


@membership_rules_router.patch("/{membership_rule_id}", response_model=MembershipRuleRead)
async def update_membership_rule(membership_rule_id: UUID, body: MembershipRuleUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipRuleService(db).update(tenant_id, membership_rule_id, body, actor=user)


@membership_rules_router.post("/{membership_rule_id}/delete", response_model=MembershipRuleRead)
async def delete_membership_rule(membership_rule_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await MembershipRuleService(db).soft_delete(tenant_id, membership_rule_id, actor=user)


renewal_policies_router = APIRouter()


@renewal_policies_router.post("", response_model=RenewalPolicyRead, status_code=status.HTTP_201_CREATED)
async def create_renewal_policy(body: RenewalPolicyCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await RenewalPolicyService(db).create(tenant_id, body, actor=user)


@renewal_policies_router.get("", response_model=list[RenewalPolicyRead])
async def list_renewal_policies(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await RenewalPolicyService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@renewal_policies_router.get("/{renewal_policy_id}", response_model=RenewalPolicyRead)
async def get_renewal_policy(renewal_policy_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await RenewalPolicyService(db).get(tenant_id, renewal_policy_id)


@renewal_policies_router.patch("/{renewal_policy_id}", response_model=RenewalPolicyRead)
async def update_renewal_policy(renewal_policy_id: UUID, body: RenewalPolicyUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await RenewalPolicyService(db).update(tenant_id, renewal_policy_id, body, actor=user)


@renewal_policies_router.post("/{renewal_policy_id}/delete", response_model=RenewalPolicyRead)
async def delete_renewal_policy(renewal_policy_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await RenewalPolicyService(db).soft_delete(tenant_id, renewal_policy_id, actor=user)


freezing_rules_router = APIRouter()


@freezing_rules_router.post("", response_model=FreezingRuleRead, status_code=status.HTTP_201_CREATED)
async def create_freezing_rule(body: FreezingRuleCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await FreezingRuleService(db).create(tenant_id, body, actor=user)


@freezing_rules_router.get("", response_model=list[FreezingRuleRead])
async def list_freezing_rules(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await FreezingRuleService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@freezing_rules_router.get("/{freezing_rule_id}", response_model=FreezingRuleRead)
async def get_freezing_rule(freezing_rule_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await FreezingRuleService(db).get(tenant_id, freezing_rule_id)


@freezing_rules_router.patch("/{freezing_rule_id}", response_model=FreezingRuleRead)
async def update_freezing_rule(freezing_rule_id: UUID, body: FreezingRuleUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await FreezingRuleService(db).update(tenant_id, freezing_rule_id, body, actor=user)


@freezing_rules_router.post("/{freezing_rule_id}/delete", response_model=FreezingRuleRead)
async def delete_freezing_rule(freezing_rule_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await FreezingRuleService(db).soft_delete(tenant_id, freezing_rule_id, actor=user)


expiration_policies_router = APIRouter()


@expiration_policies_router.post("", response_model=ExpirationPolicyRead, status_code=status.HTTP_201_CREATED)
async def create_expiration_policy(body: ExpirationPolicyCreate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await ExpirationPolicyService(db).create(tenant_id, body, actor=user)


@expiration_policies_router.get("", response_model=list[ExpirationPolicyRead])
async def list_expiration_policies(tenant_id: UUID = Depends(require_tenant), pagination: PaginationParams = Depends(get_pagination), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await ExpirationPolicyService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)


@expiration_policies_router.get("/{expiration_policy_id}", response_model=ExpirationPolicyRead)
async def get_expiration_policy(expiration_policy_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), _user: CurrentUser = Depends(get_current_user)):
    return await ExpirationPolicyService(db).get(tenant_id, expiration_policy_id)


@expiration_policies_router.patch("/{expiration_policy_id}", response_model=ExpirationPolicyRead)
async def update_expiration_policy(expiration_policy_id: UUID, body: ExpirationPolicyUpdate, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await ExpirationPolicyService(db).update(tenant_id, expiration_policy_id, body, actor=user)


@expiration_policies_router.post("/{expiration_policy_id}/delete", response_model=ExpirationPolicyRead)
async def delete_expiration_policy(expiration_policy_id: UUID, tenant_id: UUID = Depends(require_tenant), db: AsyncSession = Depends(get_db), user: CurrentUser = Depends(get_current_user)):
    return await ExpirationPolicyService(db).soft_delete(tenant_id, expiration_policy_id, actor=user)
