<?php

namespace MintyPHP\Tests\Architecture;

use PHPUnit\Framework\TestCase;

class AuthzAdminContractTest extends TestCase
{
    use ProjectFileAssertionSupport;

    public function testUsersDataActionRequiresUsersViewPermission(): void
    {
        $content = $this->readProjectFile('pages/admin/users/data().php');
        $this->assertStringContainsString('Guard::requireLogin();', $content);
        $this->assertStringContainsString('Guard::requireAbilityOrForbidden(UserAuthorizationPolicy::ABILITY_ADMIN_USERS_VIEW);', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_VIEW', $content);
    }


    public function testUsersExportActionRequiresUsersViewPermission(): void
    {
        $content = $this->readProjectFile('pages/admin/users/export().php');
        $this->assertStringContainsString('Guard::requireLogin();', $content);
        $this->assertStringContainsString('AuthorizationService::class', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_VIEW', $content);
    }


    public function testUsersActivateActionRequiresUsersUpdatePermission(): void
    {
        $content = $this->readProjectFile('pages/admin/users/activate($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_ACTIVATE', $content);
    }


    public function testUsersDeactivateActionRequiresUsersUpdatePermission(): void
    {
        $content = $this->readProjectFile('pages/admin/users/deactivate($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_DEACTIVATE', $content);
    }


    public function testUsersBulkActionPermissionMappingIsConsistent(): void
    {
        $content = $this->readProjectFile('pages/admin/users/bulk($action).php');
        $this->assertStringContainsString('AuthorizationService::class', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_BULK', $content);
        $this->assertStringContainsString("'bulk_action' => \$action", $content);
    }


    public function testAdditionalAdminUserActionsUseCentralPolicy(): void
    {
        $indexContent = $this->readProjectFile('pages/admin/users/index().php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_VIEW', $indexContent);

        $createContent = $this->readProjectFile('pages/admin/users/create().php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_CREATE', $createContent);

        $deleteContent = $this->readProjectFile('pages/admin/users/delete($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_DELETE', $deleteContent);

        $accessPdfContent = $this->readProjectFile('pages/admin/users/access-pdf($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_ACCESS_PDF', $accessPdfContent);

        $accessPdfBulkContent = $this->readProjectFile('pages/admin/users/access-pdf-bulk().php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_ACCESS_PDF_BULK', $accessPdfBulkContent);

        $tokenCreateContent = $this->readProjectFile('pages/admin/users/api-token-create($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_API_TOKENS_MANAGE', $tokenCreateContent);

        $tokenRevokeContent = $this->readProjectFile('pages/admin/users/api-token-revoke($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_API_TOKENS_MANAGE', $tokenRevokeContent);

        $sendAccessContent = $this->readProjectFile('pages/admin/users/send-access($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_SEND_ACCESS', $sendAccessContent);

        $forgetTokensContent = $this->readProjectFile('pages/admin/users/forget-tokens($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_FORGET_TOKENS', $forgetTokensContent);
    }


    public function testAdminUserEditUsesContextAndSubmitPolicies(): void
    {
        $content = $this->readProjectFile('pages/admin/users/edit($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_EDIT_CONTEXT', $content);
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_EDIT_SUBMIT', $content);
    }


    public function testAdminUserAvatarEndpointsUseCentralPolicies(): void
    {
        $uploadContent = $this->readProjectFile('pages/admin/users/avatar($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_AVATAR_UPLOAD', $uploadContent);

        $deleteContent = $this->readProjectFile('pages/admin/users/avatar-delete($id).php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_AVATAR_DELETE', $deleteContent);

        $viewContent = $this->readProjectFile('pages/admin/users/avatar-file().php');
        $this->assertStringContainsString('UserAuthorizationPolicy::ABILITY_ADMIN_USERS_AVATAR_VIEW', $viewContent);
    }


    public function testAdminTenantEditAndCustomFieldActionsUseCentralPolicies(): void
    {
        $indexContent = $this->readProjectFile('pages/admin/tenants/index().php');
        $this->assertStringContainsString('AuthorizationService::class', $indexContent);
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_VIEW', $indexContent);

        $dataContent = $this->readProjectFile('pages/admin/tenants/data().php');
        $this->assertStringContainsString('Guard::requireAbilityDecisionOrForbidden(TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_VIEW);', $dataContent);
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_VIEW', $dataContent);

        $createContent = $this->readProjectFile('pages/admin/tenants/create().php');
        $this->assertStringContainsString('AuthorizationService::class', $createContent);
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_CREATE', $createContent);

        $editContent = $this->readProjectFile('pages/admin/tenants/edit($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $editContent);
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_EDIT_CONTEXT', $editContent);
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_EDIT_SUBMIT', $editContent);

        $customFieldCreate = $this->readProjectFile('pages/admin/tenants/custom-field-create($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_CUSTOM_FIELDS_MANAGE', $customFieldCreate);

        $customFieldUpdate = $this->readProjectFile('pages/admin/tenants/custom-field-update($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_CUSTOM_FIELDS_MANAGE', $customFieldUpdate);

        $customFieldDelete = $this->readProjectFile('pages/admin/tenants/custom-field-delete($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_CUSTOM_FIELDS_MANAGE', $customFieldDelete);
    }


    public function testAdminTenantDeleteUsesCentralPolicy(): void
    {
        $deleteContent = $this->readProjectFile('pages/admin/tenants/delete($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $deleteContent);
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_DELETE', $deleteContent);
    }


    public function testAdminTenantMediaEndpointsUseCentralPolicies(): void
    {
        $avatarView = $this->readProjectFile('pages/admin/tenants/avatar-file().php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_AVATAR_VIEW', $avatarView);

        $avatarUpload = $this->readProjectFile('pages/admin/tenants/avatar($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_MEDIA_UPDATE', $avatarUpload);

        $avatarDelete = $this->readProjectFile('pages/admin/tenants/avatar-delete($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_MEDIA_UPDATE', $avatarDelete);

        $faviconUpload = $this->readProjectFile('pages/admin/tenants/favicon($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_MEDIA_UPDATE', $faviconUpload);

        $faviconDelete = $this->readProjectFile('pages/admin/tenants/favicon-delete($id).php');
        $this->assertStringContainsString('TenantAuthorizationPolicy::ABILITY_ADMIN_TENANTS_MEDIA_UPDATE', $faviconDelete);
    }


    public function testAdminDepartmentsEditAndDeleteUseCentralPolicies(): void
    {
        $indexContent = $this->readProjectFile('pages/admin/departments/index().php');
        $this->assertStringContainsString('AuthorizationService::class', $indexContent);
        $this->assertStringContainsString('DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_VIEW', $indexContent);

        $dataContent = $this->readProjectFile('pages/admin/departments/data().php');
        $this->assertStringContainsString('Guard::requireAbilityDecisionOrForbidden(DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_VIEW);', $dataContent);
        $this->assertStringContainsString('DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_VIEW', $dataContent);

        $createContent = $this->readProjectFile('pages/admin/departments/create().php');
        $this->assertStringContainsString('AuthorizationService::class', $createContent);
        $this->assertStringContainsString('DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_CREATE', $createContent);

        $editContent = $this->readProjectFile('pages/admin/departments/edit($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $editContent);
        $this->assertStringContainsString('DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_EDIT_CONTEXT', $editContent);
        $this->assertStringContainsString('DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_EDIT_SUBMIT', $editContent);

        $deleteContent = $this->readProjectFile('pages/admin/departments/delete($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $deleteContent);
        $this->assertStringContainsString('DepartmentAuthorizationPolicy::ABILITY_ADMIN_DEPARTMENTS_DELETE', $deleteContent);
    }


    public function testAdminRolesActionsUseCentralPolicies(): void
    {
        $indexContent = $this->readProjectFile('pages/admin/roles/index().php');
        $this->assertStringContainsString('AuthorizationService::class', $indexContent);
        $this->assertStringContainsString('RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_VIEW', $indexContent);

        $dataContent = $this->readProjectFile('pages/admin/roles/data().php');
        $this->assertStringContainsString('Guard::requireAbilityOrForbidden(RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_VIEW);', $dataContent);
        $this->assertStringContainsString('RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_VIEW', $dataContent);

        $createContent = $this->readProjectFile('pages/admin/roles/create().php');
        $this->assertStringContainsString('AuthorizationService::class', $createContent);
        $this->assertStringContainsString('RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_CREATE', $createContent);

        $editContent = $this->readProjectFile('pages/admin/roles/edit($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $editContent);
        $this->assertStringContainsString('RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_EDIT_CONTEXT', $editContent);
        $this->assertStringContainsString('RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_EDIT_SUBMIT', $editContent);

        $deleteContent = $this->readProjectFile('pages/admin/roles/delete($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $deleteContent);
        $this->assertStringContainsString('RoleAuthorizationPolicy::ABILITY_ADMIN_ROLES_DELETE', $deleteContent);
    }


    public function testAdminPermissionsActionsUseCentralPolicies(): void
    {
        $indexContent = $this->readProjectFile('pages/admin/permissions/index().php');
        $this->assertStringContainsString('AuthorizationService::class', $indexContent);
        $this->assertStringContainsString('PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_VIEW', $indexContent);

        $dataContent = $this->readProjectFile('pages/admin/permissions/data().php');
        $this->assertStringContainsString('Guard::requireAbilityOrForbidden(PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_VIEW);', $dataContent);
        $this->assertStringContainsString('PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_VIEW', $dataContent);

        $createContent = $this->readProjectFile('pages/admin/permissions/create().php');
        $this->assertStringContainsString('AuthorizationService::class', $createContent);
        $this->assertStringContainsString('PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_CREATE', $createContent);

        $editContent = $this->readProjectFile('pages/admin/permissions/edit($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $editContent);
        $this->assertStringContainsString('PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_EDIT_CONTEXT', $editContent);
        $this->assertStringContainsString('PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_EDIT_SUBMIT', $editContent);

        $deleteContent = $this->readProjectFile('pages/admin/permissions/delete($id).php');
        $this->assertStringContainsString('AuthorizationService::class', $deleteContent);
        $this->assertStringContainsString('PermissionAuthorizationPolicy::ABILITY_ADMIN_PERMISSIONS_DELETE', $deleteContent);
    }


    public function testAdminSettingsActionsUseCentralPolicies(): void
    {
        $indexContent = $this->readProjectFile('pages/admin/settings/index().php');
        $this->assertStringContainsString('AuthorizationService::class', $indexContent);
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_VIEW', $indexContent);
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_UPDATE', $indexContent);

        $logoUpload = $this->readProjectFile('pages/admin/settings/logo().php');
        $this->assertStringContainsString('AuthorizationService::class', $logoUpload);
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_BRANDING_UPDATE', $logoUpload);

        $logoDelete = $this->readProjectFile('pages/admin/settings/logo-delete().php');
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_BRANDING_UPDATE', $logoDelete);

        $faviconUpload = $this->readProjectFile('pages/admin/settings/favicon().php');
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_BRANDING_UPDATE', $faviconUpload);

        $faviconDelete = $this->readProjectFile('pages/admin/settings/favicon-delete().php');
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_BRANDING_UPDATE', $faviconDelete);

        $revokeApiTokens = $this->readProjectFile('pages/admin/settings/revoke-api-tokens().php');
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_TOKENS_REVOKE', $revokeApiTokens);

        $expireRememberTokens = $this->readProjectFile('pages/admin/settings/expire-remember-tokens().php');
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_TOKENS_REVOKE', $expireRememberTokens);

        $runUserLifecycle = $this->readProjectFile('pages/admin/settings/run-user-lifecycle().php');
        $this->assertStringContainsString('SettingsAuthorizationPolicy::ABILITY_ADMIN_SETTINGS_USER_LIFECYCLE_RUN', $runUserLifecycle);
    }


    public function testScheduledJobEditUsesAbilityChecksAndNoPermissionHelper(): void
    {
        $content = $this->readProjectFile('pages/admin/scheduled-jobs/edit($id).php');
        $this->assertStringContainsString('OperationsAuthorizationPolicy::ABILITY_ADMIN_JOBS_VIEW', $content);
        $this->assertStringContainsString('OperationsAuthorizationPolicy::ABILITY_ADMIN_JOBS_MANAGE', $content);
        $this->assertStringContainsString('OperationsAuthorizationPolicy::ABILITY_ADMIN_JOBS_RUN_NOW', $content);
        $this->assertStringNotContainsString("can('jobs.manage')", $content);
        $this->assertStringNotContainsString("can('jobs.run_now')", $content);
    }


}
