from __future__ import annotations

from app.modules.core.rbac.permissions_registry import expand_permission_codes


def _has(permissions: list[str] | None, code: str) -> bool:
    granted = set(permissions or [])
    for candidate in expand_permission_codes(code):
        if candidate in granted:
            return True
    return False


def _roles(role_names: list[str] | None) -> set[str]:
    return set(role_names or [])


def is_system_admin(role_names: list[str] | None = None) -> bool:
    return "System Admin" in _roles(role_names)


def is_firm_admin(role_names: list[str] | None = None) -> bool:
    return "Firm Admin" in _roles(role_names)


def can_view_own_alerts(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "alerts.view_self") or bool(user)


def can_manage_alerts(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "alerts.manage") and (is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names))


def can_view_users(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "users.view")


def can_manage_users(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "users.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names)
    )


def can_view_settings(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "system.settings.view")


def can_edit_settings(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "system.settings.edit")


def can_manage_settings(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names)


def can_view_tenants(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names)


def can_manage_tenants(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names)


def can_view_branches(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) or is_firm_admin(role_names)


def can_manage_branches(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) or is_firm_admin(role_names)


def can_change_branch_tenant(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names)


def can_view_rbac(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names)


def can_manage_rbac(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names)


def can_view_audit(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "audit.view") and (
        is_system_admin(role_names) or is_firm_admin(role_names)
    )


def can_view_services(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "services.view")


def can_manage_services(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "services.create") or _has(permissions, "services.edit")


def can_manage_service_tasks(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "service_tasks.create") or _has(permissions, "service_tasks.edit")


def can_import_services(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "services.import")


def can_import_service_tasks(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "service_tasks.import")


def can_switch_service_tenant(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "services.cross_tenant")


def can_switch_service_branch(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "services.cross_branch") or can_switch_service_tenant(
        user, permissions, role_names
    )


def can_view_clients(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "clients.view")


def can_manage_clients(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "clients.create") or _has(permissions, "clients.edit")


def can_export_clients(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "clients.export")


def can_switch_client_tenant(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "clients.cross_tenant")


def can_switch_client_branch(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "clients.cross_branch") or can_switch_client_tenant(
        user, permissions, role_names
    )

def can_view_consultants(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "consultants.view")


def can_manage_consultants(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "consultants.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names)
    )


def can_link_consultant_clients(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "consultants.link_clients")


def can_manage_consultant_service_requests(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "consultants.service_requests.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names)
    )


def can_manage_consultant_conversions(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "consultants.conversions.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names)
    )


def can_view_consultant_portal(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "consultants.portal.view") or "Consultant" in _roles(role_names)


def can_manage_own_consultant_workspace(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return can_view_consultant_portal(user, permissions, role_names) and _has(permissions, "consultants.workspace.manage")






def can_view_employee_dashboard(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.dashboard.view") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )

def can_view_employees(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.view")


def can_manage_employees(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.create") or _has(permissions, "employees.edit")


def can_change_employee_status(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.status")


def can_switch_employee_tenant(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "employees.cross_tenant")


def can_switch_employee_branch(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.cross_branch") or can_switch_employee_tenant(user, permissions, role_names)



def can_view_employee_portal(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.ess.view") or bool({"System Admin", "Firm Admin", "Partner", "Branch Manager", "Staff"}.intersection(_roles(role_names)))


def can_edit_own_employee_profile(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return can_view_employee_portal(user, permissions, role_names) and _has(permissions, "employees.ess.profile.edit")


def can_view_own_employee_work(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.work.view_self") or can_view_employee_portal(user, permissions, role_names)


def can_request_employee_registration(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.registration.request") or can_view_employee_portal(user, permissions, role_names)


def can_approve_employee_registrations(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.registration.approve") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )



def can_punch_employee_attendance(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.attendance.punch") or can_view_employee_portal(user, permissions, role_names)


def can_view_own_employee_attendance(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.attendance.view_self") or can_view_employee_portal(user, permissions, role_names)


def can_view_all_employee_attendance(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.attendance.view_all") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_approve_employee_attendance(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.attendance.approve") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )



def can_apply_employee_leave(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.leave.apply") or can_view_employee_portal(user, permissions, role_names)


def can_view_own_employee_leave(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.leave.view_self") or can_view_employee_portal(user, permissions, role_names)


def can_view_all_employee_leave(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.leave.view_all") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_approve_employee_leave(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.leave.approve") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_leave_types(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.leave_type.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_leave_balances(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.leave_balance.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )



def can_view_own_employee_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.documents.view_self") or can_view_employee_portal(user, permissions, role_names)


def can_upload_own_employee_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.documents.upload_self") or can_view_employee_portal(user, permissions, role_names)


def can_view_all_employee_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.documents.view_all") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.documents.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_verify_employee_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.documents.verify") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_document_types(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.document_type.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )



def can_view_employee_onboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.onboarding.view") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_onboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.onboarding.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_approve_employee_onboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.onboarding.approve") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_view_employee_offboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.offboarding.view") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_offboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.offboarding.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_approve_employee_offboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.offboarding.approve") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_request_own_employee_offboarding(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.offboarding.request_self") or can_view_employee_portal(user, permissions, role_names)




def can_import_employee_hr(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.import") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )

def can_manage_employee_payroll_structures(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.payroll.structure.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_run_employee_payroll(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.payroll.run") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_view_employee_payroll(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.payroll.view") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_view_own_employee_payslips(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.payroll.view_self") or can_view_employee_portal(user, permissions, role_names)


def can_approve_employee_payroll(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.payroll.payout") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names)
    )



def can_view_employee_progress(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.progress.view") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_manage_employee_work(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "employees.work.manage") and (
        is_system_admin(role_names) or is_firm_admin(role_names) or "Partner" in _roles(role_names) or "Branch Manager" in _roles(role_names)
    )


def can_view_billing(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "billing.view")


def can_create_billing(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "billing.create")


def can_import_billing_fee_structure(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "billing_fee_structure.import")


def can_view_billing_fee_structure(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "billing_fee_structure.view")


def can_generate_billing_invoices(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "billing_invoice.generate") or _has(permissions, "billing_invoice.bulk_generate")


def can_view_platform_billing(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "platform_billing.view")


def can_manage_platform_billing(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and (_has(permissions, "platform_billing.create") or _has(permissions, "platform_billing.edit"))


def can_generate_platform_billing(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "platform_billing.generate")


def can_manage_platform_plans(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "platform_plans.manage")


def can_manage_platform_subscriptions(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "platform_subscriptions.manage")


def can_view_marketplace_leads(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "marketplace_leads.view") or _has(permissions, "marketplace_leads.view_assigned")


def can_create_marketplace_leads(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "marketplace_leads.create")


def can_assign_marketplace_leads(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return is_system_admin(role_names) and _has(permissions, "marketplace_leads.assign")


def can_update_marketplace_leads(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "marketplace_leads.update")


def can_convert_marketplace_leads(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "marketplace_leads.convert")



def can_view_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "documents.view")


def can_upload_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "documents.upload")


def can_download_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "documents.download")


def can_delete_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "documents.delete") and (is_firm_admin(role_names) or "Partner" in _roles(role_names))


def can_view_notice_cases(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "notice_cases.view")

def can_manage_notice_cases(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "notice_cases.create") or _has(permissions, "notice_cases.edit")

def can_upload_notice_case_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "notice_cases.documents.upload")

def can_download_notice_case_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "notice_cases.documents.download")

def can_delete_notice_case_documents(user=None, permissions: list[str] | None = None, role_names: list[str] | None = None) -> bool:
    return _has(permissions, "notice_cases.documents.delete")
