import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
  canDeleteExecutionByIdentity,
  canDeleteTaskByIdentity,
  canEditExecutionByIdentity,
  canEditTaskByIdentity
} from '../src/views/project/project/execution/composables/task-permission-rules';

function createExecution(overrides: Partial<Api.Project.ProjectExecution> = {}): Api.Project.ProjectExecution {
  return {
    id: 'execution-1',
    projectId: 'project-1',
    projectRequirementId: null,
    projectRequirementName: null,
    projectRequirementStatusCode: null,
    executionName: 'execution',
    executionType: null,
    ownerId: 'execution-owner',
    ownerNickname: null,
    statusCode: 'active',
    statusName: null,
    terminal: false,
    allowEdit: true,
    availableActions: [],
    plannedStartDate: null,
    plannedEndDate: null,
    actualStartDate: null,
    actualEndDate: null,
    progressRate: 0,
    priority: '2',
    priorityName: null,
    executionDesc: null,
    lastStatusReason: null,
    createTime: '2026-07-07 10:00:00',
    updateTime: '2026-07-07 10:00:00',
    ...overrides
  };
}

function createTask(overrides: Partial<Api.Project.ProjectTask> = {}): Api.Project.ProjectTask {
  return {
    id: 'task-1',
    projectId: 'project-1',
    executionId: 'execution-1',
    executionName: '执行',
    executionStatusCode: 'active',
    parentTaskId: null,
    projectRequirementId: null,
    projectRequirementName: null,
    projectRequirementStatusCode: null,
    taskTitle: '任务',
    type: '',
    ownerId: 'task-owner',
    ownerNickname: null,
    executionOwnerId: 'execution-owner',
    parentTaskOwnerId: null,
    statusCode: 'active',
    statusName: null,
    terminal: false,
    allowEdit: true,
    availableActions: [],
    progressRate: 0,
    plannedStartDate: null,
    plannedEndDate: null,
    actualStartDate: null,
    actualEndDate: null,
    priority: '2',
    priorityName: null,
    taskDesc: null,
    lastStatusReason: null,
    assignees: null,
    attachments: [],
    totalSpentHours: null,
    createTime: '2026-07-07 10:00:00',
    updateTime: '2026-07-07 10:00:00',
    ...overrides
  };
}

describe('task mutation permission rules', () => {
  it('allows task owner, execution owner, and project manager to edit mutable tasks', () => {
    const task = createTask();

    assert.equal(
      canEditTaskByIdentity(task, { currentUserId: 'task-owner', projectManagerUserId: 'project-manager' }),
      true
    );
    assert.equal(
      canEditTaskByIdentity(task, { currentUserId: 'execution-owner', projectManagerUserId: 'project-manager' }),
      true
    );
    assert.equal(
      canEditTaskByIdentity(task, { currentUserId: 'project-manager', projectManagerUserId: 'project-manager' }),
      true
    );
  });

  it('does not allow unrelated users to edit just because they have a task permission code', () => {
    const task = createTask();

    assert.equal(
      canEditTaskByIdentity(task, {
        currentUserId: 'developer',
        projectManagerUserId: 'project-manager'
      }),
      false
    );
  });

  it('uses the same identity rule for delete and only blocks completed tasks by status', () => {
    assert.equal(
      canDeleteTaskByIdentity(createTask({ statusCode: 'active' }), {
        currentUserId: 'execution-owner',
        projectManagerUserId: 'project-manager'
      }),
      true
    );
    assert.equal(
      canDeleteTaskByIdentity(createTask({ statusCode: 'completed' }), {
        currentUserId: 'execution-owner',
        projectManagerUserId: 'project-manager'
      }),
      false
    );
  });
});

describe('execution mutation permission rules', () => {
  it('allows only execution owner and project manager to edit mutable executions', () => {
    const execution = createExecution();

    assert.equal(
      canEditExecutionByIdentity(execution, {
        currentUserId: 'execution-owner',
        projectManagerUserId: 'project-manager'
      }),
      true
    );
    assert.equal(
      canEditExecutionByIdentity(execution, {
        currentUserId: 'project-manager',
        projectManagerUserId: 'project-manager'
      }),
      true
    );
    assert.equal(
      canEditExecutionByIdentity(execution, {
        currentUserId: 'developer',
        projectManagerUserId: 'project-manager'
      }),
      false
    );
  });

  it('uses the same identity rule for delete and only blocks completed executions by status', () => {
    assert.equal(
      canDeleteExecutionByIdentity(createExecution({ statusCode: 'active' }), {
        currentUserId: 'execution-owner',
        projectManagerUserId: 'project-manager'
      }),
      true
    );
    assert.equal(
      canDeleteExecutionByIdentity(createExecution({ statusCode: 'active' }), {
        currentUserId: 'developer',
        projectManagerUserId: 'project-manager'
      }),
      false
    );
    assert.equal(
      canDeleteExecutionByIdentity(createExecution({ statusCode: 'completed' }), {
        currentUserId: 'execution-owner',
        projectManagerUserId: 'project-manager'
      }),
      false
    );
  });
});
