import { Page, expect } from '@playwright/test';
import type { RoleDefinition } from '../roles/base.role';

export class PermissionHelper {
  constructor(private page: Page) {}

  async verifyCanAccess(path: string): Promise<void> {
    await this.page.goto(path);
    await expect(this.page).not.toHaveURL(/\/login/);
    await expect(this.page).not.toHaveURL(/\/403/);
    await expect(this.page).not.toHaveURL(/\/404/);
  }

  async verifyCannotAccess(path: string): Promise<void> {
    await this.page.goto(path);
    
    // 应该被重定向到登录页或显示403错误
    const url = this.page.url();
    const isForbidden = url.includes('/403') || url.includes('/login');
    
    expect(isForbidden || await this.isAccessDenied()).toBeTruthy();
  }

  private async isAccessDenied(): Promise<boolean> {
    const deniedMessage = this.page.locator('text=/无权限|权限不足|Access Denied|Forbidden/i');
    return await deniedMessage.count() > 0;
  }

  async verifyCanCreate(_resource: string, createButtonSelector: string): Promise<void> {
    const createButton = this.page.locator(createButtonSelector);
    await expect(createButton).toBeVisible();
    await expect(createButton).toBeEnabled();
  }

  async verifyCannotCreate(_resource: string, createButtonSelector: string): Promise<void> {
    const createButton = this.page.locator(createButtonSelector);
    const count = await createButton.count();
    
    if (count > 0) {
      await expect(createButton).not.toBeVisible();
    }
  }

  async verifyCanEdit(_resourceId: string, editButtonSelector: string): Promise<void> {
    const editButton = this.page.locator(editButtonSelector);
    await expect(editButton).toBeVisible();
    await expect(editButton).toBeEnabled();
  }

  async verifyCannotEdit(_resourceId: string, editButtonSelector: string): Promise<void> {
    const editButton = this.page.locator(editButtonSelector);
    const count = await editButton.count();
    
    if (count > 0) {
      await expect(editButton).not.toBeVisible();
    }
  }

  async verifyCanDelete(_resourceId: string, deleteButtonSelector: string): Promise<void> {
    const deleteButton = this.page.locator(deleteButtonSelector);
    await expect(deleteButton).toBeVisible();
    await expect(deleteButton).toBeEnabled();
  }

  async verifyCannotDelete(_resourceId: string, deleteButtonSelector: string): Promise<void> {
    const deleteButton = this.page.locator(deleteButtonSelector);
    const count = await deleteButton.count();
    
    if (count > 0) {
      await expect(deleteButton).not.toBeVisible();
    }
  }

  async verifyRolePermissions(role: RoleDefinition): Promise<void> {
    // 验证可访问的路径
    for (const path of role.expectedBehaviors.canRead) {
      if (path !== 'self') {
        await this.verifyCanAccess(`/${path}`);
      }
    }

    // 验证不可访问的路径
    for (const path of role.cannotAccess) {
      await this.verifyCannotAccess(path);
    }
  }

  async verifyPermissionBoundary(
    role: RoleDefinition,
    testScenarios: {
      resource: string;
      path: string;
      createButton?: string;
      editButton?: string;
      deleteButton?: string;
    }
  ): Promise<void> {
    await this.page.goto(testScenarios.path);

    // 验证创建权限
    if (testScenarios.createButton) {
      if (role.expectedBehaviors.canCreate.includes(testScenarios.resource)) {
        await this.verifyCanCreate(testScenarios.resource, testScenarios.createButton);
      } else {
        await this.verifyCannotCreate(testScenarios.resource, testScenarios.createButton);
      }
    }

    // 验证编辑权限
    if (testScenarios.editButton) {
      if (role.expectedBehaviors.canUpdate.includes(testScenarios.resource)) {
        await this.verifyCanEdit(testScenarios.resource, testScenarios.editButton);
      } else {
        await this.verifyCannotEdit(testScenarios.resource, testScenarios.editButton);
      }
    }

    // 验证删除权限
    if (testScenarios.deleteButton) {
      if (role.expectedBehaviors.canDelete.includes(testScenarios.resource)) {
        await this.verifyCanDelete(testScenarios.resource, testScenarios.deleteButton);
      } else {
        await this.verifyCannotDelete(testScenarios.resource, testScenarios.deleteButton);
      }
    }
  }
}

export function createPermissionHelper(page: Page): PermissionHelper {
  return new PermissionHelper(page);
}
