from typing import List, Optional

from fastapi import APIRouter, Depends, HTTPException, Path, Query, status
from sqlalchemy.orm.session import Session

from src.apps.role_permission.guard import PermissionGuard
from src.apps.role_permission.schemas.common import PermissionSchema, RoleSchema
from src.apps.role_permission.schemas.requests import (
    RoleAssignRequestSchema,
    RoleCreateRequestSchema,
    RoleListFilterSchema,
    RoleUpdateRequestSchema,
)
from src.apps.role_permission.schemas.responses import (
    DeleteRoleResponse,
    PermissionsListResponse,
    ResponseData,
    RoleResponse,
    RolesListResponse,
)
from src.apps.role_permission.services import role_service
from src.core.dependencies import get_db
from src.utils.constants import DEFAULT_PER_PAGE, MAX_PER_PAGE
from src.utils.guard import get_current_user
from src.apps.base.schemas.response_model import ResponseModel

router = APIRouter()


@router.get("/", response_model=ResponseModel)
async def list_roles(
    filters: RoleListFilterSchema = Depends(),
    sort_by: str = Query(
        default="-created_at",
        description="Sort column name with direction. Prepend '-' to sort descending. E.g: ?sort_by=-created_at",
    ),
    fields: str = Query(default=None, description="Additional related fields that are requested."),
    page: int = Query(default=1, ge=1, description="Page number"),
    per_page: int = Query(
        default=DEFAULT_PER_PAGE,
        ge=1,
        le=MAX_PER_PAGE,
        description="Items per page",
    ),
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
    # is_permitted: bool = Depends(PermissionGuard(permissions=['role_view']))
):
    """
    List all available roles

    This API supports page number pagination style
    """
    response = await role_service.list_roles(
        db=db,
        filters=filters,
        sort_by=sort_by.split(",") if sort_by else [],
        fields=fields,
        page=page,
        per_page=per_page,
        current_user=current_user,
    )
    return ResponseModel(
        data=response, status_code=status.HTTP_200_OK, message="Record fetched successfully"
    )


@router.get("/permissions", response_model=ResponseModel)
async def list_permissions(
    db: Session = Depends(get_db),
    filters: RoleListFilterSchema = Depends(),
    sort_by: str = Query(
        default="display_order",
        description="Sort column name with direction. Prepend '-' to sort descending. E.g: ?sort_by=-module",
    ),
    current_user: dict = Depends(get_current_user),
    is_permitted: bool = Depends(PermissionGuard(permissions=["role_create", "role_edit"])),
):
    """
    List all available permissions
    """
    response = await role_service.list_permissions(db=db, filters=filters, sort_by=sort_by, current_user=current_user)
    return ResponseModel(
        data=response, status_code=status.HTTP_200_OK, message="Record fetched successfully"
    )


@router.get("/{slug}", response_model=ResponseModel)
async def fetch_role_by_slug(
    db: Session = Depends(get_db),
    slug: str = Path(..., description="Slug of the role to fetch"),
    is_permitted: bool = Depends(PermissionGuard(permissions=["role_view"])),
):
    """
    Fetch a role by its slug
    """
    response = await role_service.fetch_role_by_slug(db=db, slug=slug)
    return ResponseModel(
        data=response, status_code=status.HTTP_200_OK, message="Record fetched successfully"
    )


@router.post("/", response_model=ResponseModel)
async def create_role(
    payload: RoleCreateRequestSchema,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
    is_permitted: bool = Depends(PermissionGuard(permissions=["role_create"])),
):
    """
    Create a new role
    """
    response = await role_service.create_role(
        db=db,
        payload=payload,
        current_user=current_user,
    )
    return ResponseModel(
        data=response, status_code=status.HTTP_201_CREATED, message="Record creaed successfully"
    )


@router.put("/{slug}", response_model=ResponseModel)
async def update_role(
    payload: RoleUpdateRequestSchema,
    slug: str = Path(..., description="Slug of the role to edit"),
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
    is_permitted: bool = Depends(PermissionGuard(permissions=["role_edit"])),
):
    """
    Update a role
    """
    response = await role_service.update_role(db=db, slug=slug, payload=payload, current_user=current_user)
    return ResponseModel(
        data=response, status_code=status.HTTP_200_OK, message="Record updated successfully"
    )


@router.delete("/", response_model=ResponseModel)
async def remove_role_by_id(
    slugs: str = Query(
        ...,
        description="Comma separated list of the role ids to remove. E.g: .../?ids=1,2,3",
    ),
    db: Session = Depends(get_db),
    is_permitted: bool = Depends(PermissionGuard(permissions=["role_delete"])),
):
    """
    Remove a role resource by its id
    """
    response = await role_service.remove_role(db=db, slugs=slugs)
    return ResponseModel(
        data=response, status_code=status.HTTP_200_OK, message="Record deleted successfully"
    )


@router.post(
    "/run-map-role-permission",
    response_model=ResponseModel,
)
async def run_role_permissions(
    db: Session = Depends(get_db),
    keys: str = Query(
        default=None,
        description="Specific setting to be reset by its key as a comma separated list. Eg: ?keys=branding,info",
    ),
    is_permitted: bool = Depends(PermissionGuard(permissions=["role_edit"])),
):
    """
    Reset role permissions to default
    """
    response = await role_service.run_map_role_permissions(
        db=db,
        keys=keys,
    )
    return ResponseModel(
        data=response, status_code=status.HTTP_200_OK, message="Record fetched successfully"
    )

@router.post(
    "/seed",
    summary="Seed templates",
    description="Seed the database with initial template data.",
)
def seed_templates(
    db: Session = Depends(get_db),
):
    """
    Seed the database with initial template data.
    """

    result = role_service.seed_default_roles(db)
    return result