from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse, RedirectResponse, Response from admin_app.api.dependencies import get_optional_panel_staff_context from admin_app.core import AdminSettings, AuthenticatedStaffContext, get_admin_settings from admin_app.services import ToolManagementService from admin_app.view.assets import PANEL_STATIC_MOUNT_NAME from admin_app.view.rendering import ( render_bot_monitoring_page, render_collaborator_management_page, render_login_page, render_panel_home, render_rental_reports_page, render_sales_revenue_reports_page, render_system_configuration_page, render_tool_intake_page, render_tool_review_page, ) from admin_app.view.view_models import ( AdminBotMonitoringPageView, AdminCollaboratorManagementPageView, AdminLoginPageView, AdminPanelHomeView, AdminPanelMetric, AdminPanelModuleCard, AdminPanelNavigationItem, AdminPanelQuickAction, AdminPanelRoadmapItem, AdminPanelSurfaceLink, AdminRentalReportsPageView, AdminSalesRevenueReportsPageView, AdminSystemConfigurationPageView, AdminToolIntakeDomainOption, AdminToolIntakePageView, AdminToolIntakeParameterTypeOption, AdminToolReviewPageView, AdminToolReviewWorkflowStep, ) from shared.contracts import AdminPermission, StaffRole, role_has_permission panel_router = APIRouter(tags=["panel"]) @panel_router.get("/panel", name="panel_entry") def panel_entry( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> RedirectResponse: target_route_name = "panel_home" if current_context is not None else "admin_login_view" return _redirect_to_route(request, target_route_name) @panel_router.get("/panel/admin", response_class=HTMLResponse, name="panel_home") def panel_home( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") settings = _resolve_settings(request) view = _build_home_view(request, settings, current_context) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_panel_home(view, css_href=css_href, js_href=js_href)) @panel_router.get("/login", response_class=HTMLResponse, name="admin_login_view") def login_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is not None: return _redirect_to_route(request, "panel_home") settings = _resolve_settings(request) view = _build_login_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_login_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/tools/new", response_class=HTMLResponse, name="admin_tool_intake_view") def tool_intake_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") settings = _resolve_settings(request) view = _build_tool_intake_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_tool_intake_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/tools/review", response_class=HTMLResponse, name="admin_tool_review_view") def tool_review_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") settings = _resolve_settings(request) view = _build_tool_review_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_tool_review_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/colaboradores/gestao", response_class=HTMLResponse, name="admin_collaborator_management_view") def collaborator_management_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") if not role_has_permission(current_context.principal.role, AdminPermission.MANAGE_STAFF_ACCOUNTS): return _redirect_to_route(request, "panel_home") settings = _resolve_settings(request) view = _build_collaborator_management_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_collaborator_management_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/sistema/configuracoes", response_class=HTMLResponse, name="admin_system_configuration_view") def system_configuration_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_SYSTEM): return _redirect_to_route(request, "panel_home") settings = _resolve_settings(request) view = _build_system_configuration_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_system_configuration_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/relatorios/vendas-arrecadacao", response_class=HTMLResponse, name="admin_sales_revenue_reports_view") def sales_revenue_reports_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_REPORTS): return _redirect_to_route(request, "panel_home") settings = _resolve_settings(request) view = _build_sales_revenue_reports_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_sales_revenue_reports_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/relatorios/locacao", response_class=HTMLResponse, name="admin_rental_reports_view") def rental_reports_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_REPORTS): return _redirect_to_route(request, "panel_home") settings = _resolve_settings(request) view = _build_rental_reports_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_rental_reports_page(view, css_href=css_href, js_href=js_href)) @panel_router.get("/panel/monitoramento/bot", response_class=HTMLResponse, name="admin_bot_monitoring_view") def bot_monitoring_page( request: Request, current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context), ) -> Response: if current_context is None: return _redirect_to_route(request, "admin_login_view") if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_REPORTS): return _redirect_to_route(request, "panel_home") settings = _resolve_settings(request) view = _build_bot_monitoring_view(request, settings) css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css")) js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js")) return HTMLResponse(render_bot_monitoring_page(view, css_href=css_href, js_href=js_href)) def _build_home_view( request: Request, settings: AdminSettings, current_context: AuthenticatedStaffContext, ) -> AdminPanelHomeView: panel_href = str(request.url_for("panel_home")) tool_intake_view_href = str(request.url_for("admin_tool_intake_view")) tool_review_view_href = str(request.url_for("admin_tool_review_view")) collaborator_management_view_href = str(request.url_for("admin_collaborator_management_view")) system_configuration_view_href = str(request.url_for("admin_system_configuration_view")) sales_revenue_reports_view_href = str(request.url_for("admin_sales_revenue_reports_view")) rental_reports_view_href = str(request.url_for("admin_rental_reports_view")) bot_monitoring_view_href = str(request.url_for("admin_bot_monitoring_view")) audit_href = _build_prefixed_path(settings.admin_api_prefix, "/audit/events") can_manage_collaborators = role_has_permission( current_context.principal.role, AdminPermission.MANAGE_STAFF_ACCOUNTS, ) navigation = [ AdminPanelNavigationItem( label="Dashboard", href=panel_href, description="Entrada principal do ambiente interno.", badge="Ativo", is_active=True, ), AdminPanelNavigationItem( label="Cadastro de tools", href=tool_intake_view_href, description="Pre-cadastro validado para novas tools antes da revisao.", badge="Novo", ), AdminPanelNavigationItem( label="Revisao de tools", href=tool_review_view_href, description="Fluxo humano de revisao, aprovacao e ativacao.", badge="Operacao", ), AdminPanelNavigationItem( label="Configuracoes do sistema", href=system_configuration_view_href, description="Leitura funcional, runtime e governanca do admin em uma tela dedicada.", badge="Fase 4", ), AdminPanelNavigationItem( label="Relatorios comerciais", href=sales_revenue_reports_view_href, description="Tela combinada para vendas e arrecadacao dentro da sessao do painel.", badge="Relatorios", ), AdminPanelNavigationItem( label="Relatorios de locacao", href=rental_reports_view_href, description="Tela dedicada para frota, contratos e ocupacao na sessao do painel.", badge="Locacao", ), AdminPanelNavigationItem( label="Monitoramento do bot", href=bot_monitoring_view_href, description="Fluxo operacional e telemetria conversacional em uma superficie dedicada.", badge="Bot", ), AdminPanelNavigationItem( label="Areas do sistema", href="#modules", description="Mapa claro dos modulos internos disponiveis.", badge="Painel", ), AdminPanelNavigationItem( label="Fluxo recomendado", href="#workflow", description="Sequencia sugerida para operar o admin.", badge="Guia", ), ] quick_actions = [ AdminPanelQuickAction( label="Cadastrar tool", href=tool_intake_view_href, button_class="btn-dark", ), AdminPanelQuickAction( label="Revisar tools", href=tool_review_view_href, button_class="btn-outline-dark", ), AdminPanelQuickAction( label="Config. sistema", href=system_configuration_view_href, button_class="btn-outline-secondary", ), AdminPanelQuickAction( label="Relatorios", href=sales_revenue_reports_view_href, button_class="btn-outline-dark", ), AdminPanelQuickAction( label="Locacao", href=rental_reports_view_href, button_class="btn-outline-dark", ), AdminPanelQuickAction( label="Monitorar bot", href=bot_monitoring_view_href, button_class="btn-outline-dark", ), ] modules = [ AdminPanelModuleCard( eyebrow="Fluxo de entrada", title="Cadastro de tools", description="Tela real para o colaborador preencher metadados, definir parametros e validar o pre-cadastro antes da revisao humana.", status_label="Tela ativa", status_variant="success", highlights=( "Formulario protegido por sessao web", "Preview validado antes da persistencia", "Direcao clara para revisao de diretor", ), cta_label="Abrir cadastro", href=tool_intake_view_href, is_available=True, ), AdminPanelModuleCard( eyebrow="Fluxo principal", title="Revisao de tools", description="Area operacional do painel para leitura da fila, aprovacao humana e ativacao controlada.", status_label="Tela ativa", status_variant="success", highlights=( "Fila protegida por sessao web", "Catalogo ativo para comparacao", "Leitura clara do workflow de aprovacao", ), cta_label="Abrir revisao", href=tool_review_view_href, is_available=True, ), AdminPanelModuleCard( eyebrow="Acompanhamento", title="Configuracao do sistema", description="Tela dedicada para consultar configuracao funcional, runtime administrativo e governanca do sistema sem sair do painel.", status_label="Tela ativa", status_variant="primary", highlights=( "Catalogo funcional e governanca do bot conectados", "Runtime e seguranca carregados por permissao", "Separacao de modelos visivel na mesma superficie", ), cta_label="Abrir configuracoes", href=system_configuration_view_href, is_available=True, ), AdminPanelModuleCard( eyebrow="Relatorios operacionais", title="Relatorios de vendas e arrecadacao", description="Tela dedicada para acompanhar o bootstrap de vendas e arrecadacao com leitura pronta para sessao web do painel.", status_label="Tela ativa", status_variant="info", highlights=( "Vendas e arrecadacao na mesma superficie", "Leitura protegida por sessao web", "Materializacao e proximos passos visiveis na UI", ), cta_label="Abrir relatorios", href=sales_revenue_reports_view_href, is_available=True, ), AdminPanelModuleCard( eyebrow="Relatorios operacionais", title="Relatorios de locacao", description="Tela dedicada para acompanhar a estrutura inicial de frota e contratos de locacao pela sessao web do painel.", status_label="Tela ativa", status_variant="info", highlights=( "Frota e contratos lidos na mesma superficie", "Leitura protegida por sessao web", "Catalogo inicial e materializacao visiveis na UI", ), cta_label="Abrir locacao", href=rental_reports_view_href, is_available=True, ), AdminPanelModuleCard( eyebrow="Monitoramento operacional", title="Monitoramento do bot", description="Tela dedicada para acompanhar fluxo operacional e telemetria conversacional pela sessao web do painel.", status_label="Tela ativa", status_variant="info", highlights=( "Fluxo do bot e telemetria na mesma superficie", "Leitura protegida por sessao web", "Materializacao e proximos passos visiveis na UI", ), cta_label="Abrir monitoramento", href=bot_monitoring_view_href, is_available=True, ), AdminPanelModuleCard( eyebrow="Governanca", title="Auditoria operacional", description="Eventos de login, logout, aprovacao e publicacao continuam registrados para rastreabilidade.", status_label="Auditavel", status_variant="secondary", highlights=( "Historico de operacao interna", "Base para filtros e timeline", "Suporte a conformidade do fluxo administrativo", ), ), ] surface_links = [ AdminPanelSurfaceLink( method="Acesso", label="Dashboard administrativa", href=panel_href, description="Entrada principal do time interno depois do login.", ), AdminPanelSurfaceLink( method="Cadastro", label="Nova tool", href=tool_intake_view_href, description="Formulario real para validar o pre-cadastro de uma nova tool.", ), AdminPanelSurfaceLink( method="Operacao", label="Revisao de tools", href=tool_review_view_href, description="Area com fila, contrato e catalogo ativo para tomada de decisao.", ), AdminPanelSurfaceLink( method="Sistema", label="Configuracoes do sistema", href=system_configuration_view_href, description="Tela dedicada para leitura funcional, runtime e governanca administrativa.", ), AdminPanelSurfaceLink( method="Relatorios", label="Vendas e arrecadacao", href=sales_revenue_reports_view_href, description="Tela combinada para a primeira camada visual dos relatorios comerciais da fase 4.", ), AdminPanelSurfaceLink( method="Relatorios", label="Locacao", href=rental_reports_view_href, description="Tela dedicada para a estrutura inicial de frota, contratos e ocupacao da fase 4.", ), AdminPanelSurfaceLink( method="Monitoramento", label="Bot operacional", href=bot_monitoring_view_href, description="Tela dedicada para fluxo operacional e telemetria conversacional do bot na fase 4.", ), AdminPanelSurfaceLink( method="Auditoria", label="Eventos administrativos", href=audit_href, description="Consulta de eventos internos para rastrear operacoes sensiveis.", ), ] roadmap = [ AdminPanelRoadmapItem( step="01", title="Entrar pelo login administrativo", description="A sessao web libera o ambiente interno e evita navegacao confusa antes da autenticacao.", status_label="Obrigatorio", ), AdminPanelRoadmapItem( step="02", title="Passar pela dashboard", description="A home protegida organiza os modulos e mostra por onde comecar a operacao.", status_label="Entrada", ), AdminPanelRoadmapItem( step="03", title="Cadastrar ou validar o pre-draft", description="Use a nova tela para descrever a tool, seus parametros e o objetivo operacional antes da revisao.", status_label="Cadastro", ), AdminPanelRoadmapItem( step="04", title="Abrir revisao de tools", description="Encaminhe a ferramenta para analise humana, aprovacao e ativacao controlada.", status_label="Principal", ), AdminPanelRoadmapItem( step="05", title="Consultar runtime e auditoria", description="Quando necessario, acompanhe configuracao e eventos do admin para suportar a decisao operacional.", status_label="Suporte", ), ] if can_manage_collaborators: navigation.insert( 3, AdminPanelNavigationItem( label="Colaboradores", href=collaborator_management_view_href, description="Cadastro e governanca de acessos internos, exclusivo para diretor.", badge="Diretor", ), ) quick_actions.insert( 2, AdminPanelQuickAction( label="Gerir equipe", href=collaborator_management_view_href, button_class="btn-outline-dark", ), ) modules.insert( 2, AdminPanelModuleCard( eyebrow="Governanca de acesso", title="Gestao de colaboradores", description="Tela dedicada para o diretor criar contas internas, acompanhar o status da equipe e manter a entrada administrativa sob controle.", status_label="Tela ativa", status_variant="dark", highlights=( "Criacao de colaborador com senha inicial", "Ativacao e desativacao sem tocar no banco manualmente", "Fluxo exclusivo para diretor", ), cta_label="Abrir equipe", href=collaborator_management_view_href, is_available=True, ), ) surface_links.insert( 3, AdminPanelSurfaceLink( method="Equipe", label="Gestao de colaboradores", href=collaborator_management_view_href, description="Controle de acesso interno para cadastrar e administrar a equipe administrativa.", ), ) roadmap = [ AdminPanelRoadmapItem( step="01", title="Entrar pelo login administrativo", description="A sessao web libera o ambiente interno e evita navegacao confusa antes da autenticacao.", status_label="Obrigatorio", ), AdminPanelRoadmapItem( step="02", title="Passar pela dashboard", description="A home protegida organiza os modulos e mostra por onde comecar a operacao.", status_label="Entrada", ), AdminPanelRoadmapItem( step="03", title="Cadastrar ou validar o pre-draft", description="Use a nova tela para descrever a tool, seus parametros e o objetivo operacional antes da revisao.", status_label="Cadastro", ), AdminPanelRoadmapItem( step="04", title="Organizar a equipe interna", description="Diretores podem cadastrar novos colaboradores e controlar rapidamente o status de acesso administrativo.", status_label="Diretor", ), AdminPanelRoadmapItem( step="05", title="Abrir revisao de tools", description="Encaminhe a ferramenta para analise humana, aprovacao e ativacao controlada.", status_label="Principal", ), AdminPanelRoadmapItem( step="06", title="Consultar runtime e auditoria", description="Quando necessario, acompanhe configuracao e eventos do admin para suportar a decisao operacional.", status_label="Suporte", ), ] return AdminPanelHomeView( service="orquestrador-admin", app_name=settings.admin_app_name, panel_title="Painel Administrativo", panel_subtitle=( "Area interna protegida para operar o admin com mais clareza, foco e navegacao orientada por fluxo." ), environment=settings.admin_environment, version=settings.admin_version, api_prefix=settings.admin_api_prefix or "/", release_label="Bootstrap UI v1", navigation=tuple(navigation), quick_actions=tuple(quick_actions), metrics=( AdminPanelMetric( label="Runtimes independentes", value="2", description="Produto e admin seguem isolados para deploy e operacao.", ), AdminPanelMetric( label="Perfis internos", value=str(len(StaffRole)), description="Hierarquia base com colaborador e diretor.", ), AdminPanelMetric( label="Permissoes administrativas", value=str(len(AdminPermission)), description="Camada pronta para crescer por modulo sem misturar contexto.", ), AdminPanelMetric( label="Refresh token", value=f"{settings.admin_auth_refresh_token_ttl_days} dias", description="Sessao web persistida com renovacao controlada.", ), ), modules=tuple(modules), surface_links=tuple(surface_links), roadmap=tuple(roadmap), ) def _build_login_view(request: Request, settings: AdminSettings) -> AdminLoginPageView: dashboard_href = str(request.url_for("panel_home")) auth_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/auth/login") password_requirements = [] if settings.admin_auth_password_require_uppercase: password_requirements.append("maiuscula") if settings.admin_auth_password_require_lowercase: password_requirements.append("minuscula") if settings.admin_auth_password_require_digit: password_requirements.append("digito") if settings.admin_auth_password_require_symbol: password_requirements.append("simbolo") password_policy_label = ( f"Minimo de {settings.admin_auth_password_min_length} caracteres" + (f" com {', '.join(password_requirements)}." if password_requirements else ".") ) return AdminLoginPageView( app_name=settings.admin_app_name, title="Login administrativo", subtitle=( "Entre primeiro com sua conta interna. A dashboard e os modulos do sistema so aparecem depois da autenticacao." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=dashboard_href, auth_endpoint=auth_endpoint, email_placeholder="voce@empresa.com", password_placeholder="Sua senha administrativa", access_token_ttl_label=f"{settings.admin_auth_access_token_ttl_minutes} minutos", refresh_token_ttl_label=f"{settings.admin_auth_refresh_token_ttl_days} dias", password_policy_label=password_policy_label, security_highlights=( "Identidade separada do usuario de atendimento", "Rotacao de refresh token ja implementada", "Trilha de auditoria para login e logout", ), integration_notes=( "A dashboard administrativa so aparece depois da autenticacao do StaffAccount.", "Revisao, configuracao e operacao interna ficam atras da sessao web do painel.", "Cookies httpOnly e refresh token rotacionado mantem a sessao do navegador protegida.", ), ) def _build_tool_intake_view(request: Request, settings: AdminSettings) -> AdminToolIntakePageView: service = ToolManagementService(settings) form_payload = service.build_draft_form_payload() return AdminToolIntakePageView( app_name=settings.admin_app_name, title="Cadastro de nova tool", subtitle=( "Formulario guiado para o colaborador estruturar uma nova tool, validar o pre-draft e encaminhar a proposta para revisao de diretor." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=str(request.url_for("panel_home")), review_href=str(request.url_for("admin_tool_review_view")), intake_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/tools/drafts/intake"), domain_options=tuple( AdminToolIntakeDomainOption( value=item["value"], label=item["label"], description=item["description"], ) for item in form_payload["domain_options"] ), parameter_type_options=tuple( AdminToolIntakeParameterTypeOption( value=item["code"].value, label=item["label"], description=item["description"], ) for item in form_payload["parameter_types"] ), naming_rules=tuple(form_payload["naming_rules"]), submission_notes=tuple(form_payload["submission_notes"]), approval_notes=tuple(form_payload["approval_notes"]), ) def _build_tool_review_view(request: Request, settings: AdminSettings) -> AdminToolReviewPageView: dashboard_href = str(request.url_for("panel_home")) overview_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/overview") contracts_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/contracts") review_queue_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/review-queue") publications_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/publications") return AdminToolReviewPageView( app_name=settings.admin_app_name, title="Revisao, aprovacao e ativacao", subtitle=( "Hub visual para o time interno acompanhar a fila de revisao, validar o contrato compartilhado e inspecionar o catalogo de tools ativas antes da ativacao." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=dashboard_href, overview_endpoint=overview_endpoint, contracts_endpoint=contracts_endpoint, review_queue_endpoint=review_queue_endpoint, publications_endpoint=publications_endpoint, workflow=( AdminToolReviewWorkflowStep( eyebrow="Leitura inicial", title="Revisar fila", description="Carregar a fila de geracao e entender em que gate cada item se encontra.", status_label="Revisao", status_variant="info", ), AdminToolReviewWorkflowStep( eyebrow="Decisao humana", title="Aprovar com criterio", description="Conferir contrato, parametros e prontidao tecnica antes de liberar a proxima etapa.", status_label="Aprovacao", status_variant="warning", ), AdminToolReviewWorkflowStep( eyebrow="Publicacao", title="Ativar no catalogo", description="Usar o catalogo publicado como referencia para a versao que chega ao runtime de produto.", status_label="Ativacao", status_variant="success", ), ), review_notes=( "Conferir se o gate do item combina com o estado esperado do lifecycle.", "Observar se a descricao e o objetivo operacional da tool estao claros para o time.", "Usar o catalogo ativo como comparativo antes de promover uma nova versao.", ), approval_notes=( "Verificar nome, descricao e semantica dos parametros antes da aprovacao.", "Confirmar se a tool respeita a separacao entre admin e product definida nas ADRs.", "Checar se a publicacao planejada e auditavel e segura para o runtime de produto.", ), activation_notes=( "Publicacoes ativas exigem papel com permissao publish_tools.", "A leitura do catalogo e feita via sessao web do painel para facilitar a operacao do navegador.", "Sem permissao de publicacao, a tela continua util para revisao, mas bloqueia o catalogo ativo.", ), ) def _build_sales_revenue_reports_view( request: Request, settings: AdminSettings, ) -> AdminSalesRevenueReportsPageView: return AdminSalesRevenueReportsPageView( app_name=settings.admin_app_name, title="Relatorios de vendas e arrecadacao", subtitle=( "Visao unica para acompanhar vendas e arrecadacao no painel administrativo." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=str(request.url_for("panel_home")), sales_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/sales/overview"), revenue_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/arrecadacao/overview"), access_notes=( "A equipe interna pode consultar esta tela com a permissao de relatorios.", "Os dados exibidos aparecem de forma consolidada para leitura segura no admin.", "Vendas e arrecadacao ficam juntas para facilitar a rotina do time.", ), reading_notes=( "Comece pelos indicadores de cada bloco para ter uma leitura rapida.", "Use os cards para entender rapidamente o foco de cada relatorio.", "A area de proximas melhorias mostra o que entra nas etapas seguintes.", ), ) def _build_rental_reports_view( request: Request, settings: AdminSettings, ) -> AdminRentalReportsPageView: return AdminRentalReportsPageView( app_name=settings.admin_app_name, title="Relatorios de locacao", subtitle=( "Visao dedicada da locacao para acompanhar frota, contratos e receita operacional." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=str(request.url_for("panel_home")), overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/locacao/overview"), access_notes=( "A equipe interna pode consultar esta tela com a permissao de relatorios.", "Os dados exibidos aparecem de forma consolidada para leitura segura no admin.", "Locacao fica em uma tela propria para manter a leitura mais organizada.", ), reading_notes=( "Comece pelos indicadores principais para entender o momento da operacao.", "Use os cards para ver rapidamente os temas cobertos nesta etapa.", "A area de proximas melhorias indica o que ainda entra nas proximas entregas.", ), ) def _build_bot_monitoring_view( request: Request, settings: AdminSettings, ) -> AdminBotMonitoringPageView: return AdminBotMonitoringPageView( app_name=settings.admin_app_name, title="Monitoramento operacional do bot", subtitle=( "Painel unico para acompanhar o fluxo do bot e a telemetria do atendimento." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=str(request.url_for("panel_home")), bot_flow_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/fluxo-bot/overview"), telemetry_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/telemetria-conversacional/overview"), access_notes=( "A equipe interna pode consultar esta tela com a permissao de relatorios.", "Os dados exibidos aparecem de forma consolidada para leitura segura no painel.", "Fluxo e telemetria ficam juntos para agilizar a analise da operacao.", ), reading_notes=( "Comece pelo fluxo do bot para localizar status, desvios e pontos de atencao.", "Use a telemetria para acompanhar volume, latencia e saude do atendimento.", "A area de proximas melhorias resume o que ainda entra antes dos dashboards completos.", ), ) def _build_system_configuration_view( request: Request, settings: AdminSettings, ) -> AdminSystemConfigurationPageView: return AdminSystemConfigurationPageView( app_name=settings.admin_app_name, title="Configuracoes do sistema", subtitle=( "Visao unica do catalogo funcional, das regras do atendimento e das protecoes do painel." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=str(request.url_for("panel_home")), overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration"), runtime_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/runtime"), security_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/security"), model_runtimes_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/model-runtimes"), functional_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/functional"), functional_detail_base=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/functional"), bot_governance_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/functional/bot-governance"), access_notes=( "A equipe interna ja consegue consultar o catalogo funcional e os ajustes do atendimento nesta tela.", "Detalhes mais sensiveis do ambiente continuam reservados para perfis com permissao elevada.", "Toda a superficie segue somente leitura nesta etapa.", ), governance_notes=( "Configuracoes do atendimento e da geracao de tools aparecem separadas para evitar confusao.", "Os ajustes do bot continuam bloqueados para escrita direta nas tabelas operacionais.", "O foco aqui e leitura clara do estado atual antes da futura tela de edicao.", ), ) def _build_collaborator_management_view( request: Request, settings: AdminSettings, ) -> AdminCollaboratorManagementPageView: password_requirements = [] if settings.admin_auth_password_require_uppercase: password_requirements.append("maiuscula") if settings.admin_auth_password_require_lowercase: password_requirements.append("minuscula") if settings.admin_auth_password_require_digit: password_requirements.append("digito") if settings.admin_auth_password_require_symbol: password_requirements.append("simbolo") password_policy_label = ( f"Minimo de {settings.admin_auth_password_min_length} caracteres" + (f" com {', '.join(password_requirements)}." if password_requirements else ".") ) return AdminCollaboratorManagementPageView( app_name=settings.admin_app_name, title="Gestao de colaboradores", subtitle=( "Tela exclusiva de diretor para organizar a equipe interna, criar novos acessos administrativos e controlar rapidamente quem segue ativo no painel." ), environment=settings.admin_environment, version=settings.admin_version, dashboard_href=str(request.url_for("panel_home")), collection_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/colaboradores"), password_policy_label=password_policy_label, onboarding_notes=( "Novos acessos nascem sempre com papel de colaborador.", "A senha inicial ja respeita a mesma politica do login administrativo.", "Ativar ou desativar colaborador nao exige acesso direto ao banco.", ), governance_notes=( "Somente diretor acessa esta tela e as rotas de gestao de colaboradores.", "Cada criacao e alteracao de status gera trilha de auditoria administrativa.", "A conta de diretor continua fora deste fluxo para evitar mudancas acidentais na governanca principal.", ), ) def _redirect_to_route(request: Request, route_name: str) -> RedirectResponse: return RedirectResponse(url=str(request.url_for(route_name)), status_code=302) def _resolve_settings(request: Request) -> AdminSettings: app_settings = getattr(request.app.state, "admin_settings", None) if isinstance(app_settings, AdminSettings): return app_settings return get_admin_settings() def _build_prefixed_path(api_prefix: str, path: str) -> str: normalized_prefix = api_prefix.rstrip("/") normalized_path = path if path.startswith("/") else f"/{path}" if not normalized_prefix: return normalized_path if normalized_path == "/": return f"{normalized_prefix}/" return f"{normalized_prefix}{normalized_path}"