# app/modules/tenancy/routes/pages/admin.py """ Tenancy Admin Page Routes (HTML rendering). Admin pages for multi-tenant management: - Merchants - Stores - Store domains - Store themes - Admin users - Platforms """ from fastapi import APIRouter, Depends, Path, Request from fastapi.responses import HTMLResponse, RedirectResponse from sqlalchemy.orm import Session from app.api.deps import get_db, require_menu_access from app.modules.core.utils.page_context import get_admin_context from app.modules.enums import FrontendType from app.modules.tenancy.models import User from app.templates_config import templates router = APIRouter() # ============================================================================ # MY ACCOUNT (Self-Service) # ============================================================================ @router.get("/my-account", response_class=HTMLResponse, include_in_schema=False) async def admin_my_account_page( request: Request, current_user: User = Depends(require_menu_access("my_account", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """Render the admin user's personal account page.""" return templates.TemplateResponse( "tenancy/admin/my-account.html", get_admin_context(request, db, current_user), ) # ============================================================================ # MERCHANT MANAGEMENT ROUTES # ============================================================================ @router.get("/merchants", response_class=HTMLResponse, include_in_schema=False) async def admin_merchants_list_page( request: Request, current_user: User = Depends(require_menu_access("merchants", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render merchants management page. Shows list of all merchants with stats. """ return templates.TemplateResponse( "tenancy/admin/merchants.html", get_admin_context(request, db, current_user), ) @router.get("/merchants/create", response_class=HTMLResponse, include_in_schema=False) async def admin_merchant_create_page( request: Request, current_user: User = Depends(require_menu_access("merchants", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render merchant creation form. """ return templates.TemplateResponse( "tenancy/admin/merchant-create.html", get_admin_context(request, db, current_user), ) @router.get( "/merchants/{merchant_id}", response_class=HTMLResponse, include_in_schema=False ) async def admin_merchant_detail_page( request: Request, merchant_id: int = Path(..., description="Merchant ID"), current_user: User = Depends(require_menu_access("merchants", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render merchant detail view. """ return templates.TemplateResponse( "tenancy/admin/merchant-detail.html", get_admin_context(request, db, current_user, merchant_id=merchant_id), ) @router.get( "/merchants/{merchant_id}/edit", response_class=HTMLResponse, include_in_schema=False, ) async def admin_merchant_edit_page( request: Request, merchant_id: int = Path(..., description="Merchant ID"), current_user: User = Depends(require_menu_access("merchants", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render merchant edit form. """ return templates.TemplateResponse( "tenancy/admin/merchant-edit.html", get_admin_context(request, db, current_user, merchant_id=merchant_id), ) # ============================================================================ # STORE MANAGEMENT ROUTES # ============================================================================ @router.get("/stores", response_class=HTMLResponse, include_in_schema=False) async def admin_stores_list_page( request: Request, current_user: User = Depends(require_menu_access("stores", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render stores management page. Shows list of all stores with stats. """ return templates.TemplateResponse( "tenancy/admin/stores.html", get_admin_context(request, db, current_user), ) @router.get("/stores/create", response_class=HTMLResponse, include_in_schema=False) async def admin_store_create_page( request: Request, current_user: User = Depends(require_menu_access("stores", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render store creation form. """ return templates.TemplateResponse( "tenancy/admin/store-create.html", get_admin_context(request, db, current_user), ) @router.get( "/stores/{store_code}", response_class=HTMLResponse, include_in_schema=False ) async def admin_store_detail_page( request: Request, store_code: str = Path(..., description="Store code"), current_user: User = Depends(require_menu_access("stores", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render store detail page. Shows full store information. """ return templates.TemplateResponse( "tenancy/admin/store-detail.html", get_admin_context(request, db, current_user, store_code=store_code), ) @router.get( "/stores/{store_code}/edit", response_class=HTMLResponse, include_in_schema=False ) async def admin_store_edit_page( request: Request, store_code: str = Path(..., description="Store code"), current_user: User = Depends(require_menu_access("stores", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render store edit form. """ return templates.TemplateResponse( "tenancy/admin/store-edit.html", get_admin_context(request, db, current_user, store_code=store_code), ) # ============================================================================ # STORE DOMAINS ROUTES # ============================================================================ @router.get( "/stores/{store_code}/domains", response_class=HTMLResponse, include_in_schema=False, ) async def admin_store_domains_page( request: Request, store_code: str = Path(..., description="Store code"), current_user: User = Depends(require_menu_access("stores", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render store domains management page. Shows custom domains, verification status, and DNS configuration. """ return templates.TemplateResponse( "tenancy/admin/store-domains.html", get_admin_context(request, db, current_user, store_code=store_code), ) # ============================================================================ # STORE ROLES ROUTES # ============================================================================ @router.get("/store-roles", response_class=HTMLResponse, include_in_schema=False) async def admin_store_roles_page( request: Request, current_user: User = Depends( require_menu_access("store-roles", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render store roles management page. Allows admins to select a store and manage its roles and permissions. Super admins see merchant → store cascading selection. Platform admins see store selection scoped to their platforms. """ is_super_admin = current_user.role == "super_admin" return templates.TemplateResponse( "tenancy/admin/store-roles.html", get_admin_context( request, db, current_user, is_super_admin=is_super_admin ), ) # ============================================================================ # STORE THEMES ROUTES # ============================================================================ @router.get("/store-themes", response_class=HTMLResponse, include_in_schema=False) async def admin_store_themes_page( request: Request, current_user: User = Depends( require_menu_access("store-themes", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render store themes selection page. Allows admins to select a store to customize their theme. """ return templates.TemplateResponse( "tenancy/admin/store-themes.html", get_admin_context(request, db, current_user), ) @router.get( "/stores/{store_code}/theme", response_class=HTMLResponse, include_in_schema=False, ) async def admin_store_theme_page( request: Request, store_code: str = Path(..., description="Store code"), current_user: User = Depends( require_menu_access("store-themes", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render store theme customization page. Allows admins to customize colors, fonts, layout, and branding. """ return templates.TemplateResponse( "tenancy/admin/store-theme.html", get_admin_context(request, db, current_user, store_code=store_code), ) # ============================================================================ # MERCHANT USER MANAGEMENT ROUTES (All Admins) # ============================================================================ @router.get("/merchant-users", response_class=HTMLResponse, include_in_schema=False) async def admin_merchant_users_list_page( request: Request, current_user: User = Depends( require_menu_access("merchant-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render merchant users management page. Shows list of all merchant users (owners and store team members). Visible to all admins. """ return templates.TemplateResponse( "tenancy/admin/merchant-users.html", get_admin_context(request, db, current_user), ) @router.get( "/merchant-users/{user_id}", response_class=HTMLResponse, include_in_schema=False ) async def admin_merchant_user_detail_page( request: Request, user_id: int = Path(..., description="User ID"), current_user: User = Depends( require_menu_access("merchant-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render merchant user detail view. Shows details for a merchant owner or store team member. """ return templates.TemplateResponse( "tenancy/admin/merchant-user-detail.html", get_admin_context(request, db, current_user, user_id=user_id), ) @router.get( "/merchant-users/{user_id}/edit", response_class=HTMLResponse, include_in_schema=False, ) async def admin_merchant_user_edit_page( request: Request, user_id: int = Path(..., description="User ID"), current_user: User = Depends( require_menu_access("merchant-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render merchant user edit form. Allows editing merchant owner or store team member details. """ return templates.TemplateResponse( "tenancy/admin/merchant-user-edit.html", get_admin_context(request, db, current_user, user_id=user_id), ) # ============================================================================ # ADMIN USER MANAGEMENT ROUTES (Super Admin Only) # ============================================================================ @router.get("/admin-users", response_class=HTMLResponse, include_in_schema=False) async def admin_users_list_page( request: Request, current_user: User = Depends( require_menu_access("admin-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render admin users management page. Shows list of all admin users (super admins and platform admins). Super admin only (menu is in super_admin_only section). """ return templates.TemplateResponse( "tenancy/admin/admin-users.html", get_admin_context(request, db, current_user), ) @router.get( "/admin-users/create", response_class=HTMLResponse, include_in_schema=False ) async def admin_user_create_page( request: Request, current_user: User = Depends( require_menu_access("admin-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render admin user creation form. Super admin only (menu is in super_admin_only section). """ return templates.TemplateResponse( "tenancy/admin/user-create.html", get_admin_context(request, db, current_user), ) @router.get( "/admin-users/{user_id}", response_class=HTMLResponse, include_in_schema=False ) async def admin_user_detail_page( request: Request, user_id: int = Path(..., description="User ID"), current_user: User = Depends( require_menu_access("admin-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render admin user detail view. Super admin only (menu is in super_admin_only section). """ return templates.TemplateResponse( "tenancy/admin/admin-user-detail.html", get_admin_context(request, db, current_user, user_id=user_id), ) @router.get( "/admin-users/{user_id}/edit", response_class=HTMLResponse, include_in_schema=False ) async def admin_user_edit_page( request: Request, user_id: int = Path(..., description="User ID"), current_user: User = Depends( require_menu_access("admin-users", FrontendType.ADMIN) ), db: Session = Depends(get_db), ): """ Render admin user edit form. Super admin only (menu is in super_admin_only section). """ return templates.TemplateResponse( "tenancy/admin/admin-user-edit.html", get_admin_context(request, db, current_user, user_id=user_id), ) # ============================================================================ # USER MANAGEMENT ROUTES (Legacy - Redirects) # ============================================================================ @router.get("/users", response_class=RedirectResponse, include_in_schema=False) async def admin_users_page_redirect(): """ Redirect old /admin/users to /admin/admin-users. """ return RedirectResponse(url="/admin/admin-users", status_code=302) @router.get("/users/create", response_class=RedirectResponse, include_in_schema=False) async def admin_user_create_page_redirect(): """ Redirect old /admin/users/create to /admin/admin-users/create. """ return RedirectResponse(url="/admin/admin-users/create", status_code=302) @router.get( "/users/{user_id}", response_class=RedirectResponse, include_in_schema=False ) async def admin_user_detail_page_redirect( user_id: int = Path(..., description="User ID"), ): """ Redirect old /admin/users/{id} to /admin/admin-users/{id}. """ return RedirectResponse(url=f"/admin/admin-users/{user_id}", status_code=302) @router.get( "/users/{user_id}/edit", response_class=RedirectResponse, include_in_schema=False ) async def admin_user_edit_page_redirect( user_id: int = Path(..., description="User ID"), ): """ Redirect old /admin/users/{id}/edit to /admin/admin-users/{id}/edit. """ return RedirectResponse(url=f"/admin/admin-users/{user_id}/edit", status_code=302) # ============================================================================ # PLATFORM MANAGEMENT ROUTES (Multi-Platform Support) # ============================================================================ @router.get("/platforms", response_class=HTMLResponse, include_in_schema=False) async def admin_platforms_list( request: Request, current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render platforms management page. Shows all platforms (OMS, Loyalty, etc.) with their configuration. """ return templates.TemplateResponse( "tenancy/admin/platforms.html", get_admin_context(request, db, current_user), ) @router.get( "/platforms/create", response_class=HTMLResponse, include_in_schema=False ) async def admin_platform_create( request: Request, current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render platform creation form. Allows creating a new platform with basic settings. """ return templates.TemplateResponse( "tenancy/admin/platform-create.html", get_admin_context(request, db, current_user), ) @router.get( "/platforms/{platform_code}", response_class=HTMLResponse, include_in_schema=False ) async def admin_platform_detail( request: Request, platform_code: str = Path(..., description="Platform code (oms, loyalty, etc.)"), current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render platform detail page. Shows platform configuration, marketing pages, and store defaults. """ return templates.TemplateResponse( "tenancy/admin/platform-detail.html", get_admin_context(request, db, current_user, platform_code=platform_code), ) @router.get( "/platforms/{platform_code}/edit", response_class=HTMLResponse, include_in_schema=False, ) async def admin_platform_edit( request: Request, platform_code: str = Path(..., description="Platform code"), current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render platform edit form. Allows editing platform settings, branding, and configuration. """ return templates.TemplateResponse( "tenancy/admin/platform-edit.html", get_admin_context(request, db, current_user, platform_code=platform_code), ) @router.get( "/platforms/{platform_code}/menu-config", response_class=HTMLResponse, include_in_schema=False, ) async def admin_platform_menu_config( request: Request, platform_code: str = Path(..., description="Platform code"), current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render platform menu configuration page. Super admin only - allows configuring which menu items are visible for the platform's admin and store frontends. """ if not current_user.is_super_admin: return RedirectResponse( url=f"/admin/platforms/{platform_code}", status_code=302 ) return templates.TemplateResponse( "tenancy/admin/platform-menu-config.html", get_admin_context(request, db, current_user, platform_code=platform_code), ) @router.get( "/platforms/{platform_code}/modules", response_class=HTMLResponse, include_in_schema=False, ) async def admin_platform_modules( request: Request, platform_code: str = Path(..., description="Platform code"), current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render platform module configuration page. Super admin only - allows enabling/disabling feature modules for the platform. """ if not current_user.is_super_admin: return RedirectResponse( url=f"/admin/platforms/{platform_code}", status_code=302 ) return templates.TemplateResponse( "tenancy/admin/platform-modules.html", get_admin_context(request, db, current_user, platform_code=platform_code), ) @router.get( "/platforms/{platform_code}/modules/{module_code}", response_class=HTMLResponse, include_in_schema=False, ) async def admin_module_info( request: Request, platform_code: str = Path(..., description="Platform code"), module_code: str = Path(..., description="Module code"), current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render module info/detail page. Shows module details including features, menu items, dependencies, and self-contained module information. """ if not current_user.is_super_admin: return RedirectResponse( url=f"/admin/platforms/{platform_code}", status_code=302 ) return templates.TemplateResponse( "tenancy/admin/module-info.html", get_admin_context( request, current_user, platform_code=platform_code, module_code=module_code ), ) @router.get( "/platforms/{platform_code}/modules/{module_code}/config", response_class=HTMLResponse, include_in_schema=False, ) async def admin_module_config( request: Request, platform_code: str = Path(..., description="Platform code"), module_code: str = Path(..., description="Module code"), current_user: User = Depends(require_menu_access("platforms", FrontendType.ADMIN)), db: Session = Depends(get_db), ): """ Render module configuration page. Allows configuring module-specific settings. """ if not current_user.is_super_admin: return RedirectResponse( url=f"/admin/platforms/{platform_code}", status_code=302 ) return templates.TemplateResponse( "tenancy/admin/module-config.html", get_admin_context( request, current_user, platform_code=platform_code, module_code=module_code ), )