import { describe, expect, it } from "vitest";
import { PermissionKey, SystemRole, type PermissionKey as PermissionKeyValue } from "@capakraken/shared";
import { getAvailableAssistantTools } from "../router/assistant-tool-policy.js";

function getToolNames(
  permissions: PermissionKeyValue[],
  userRole: SystemRole = SystemRole.ADMIN,
) {
  return getAvailableAssistantTools(new Set(permissions), userRole).map((tool) => tool.function.name);
}

describe("assistant tool policy planning flows", () => {
  it("requires both controller role and advanced assistant access for timeline detail tools", () => {
    const controllerWithAdvanced = getToolNames([
      PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS,
    ], SystemRole.CONTROLLER);
    const controllerWithoutAdvanced = getToolNames([], SystemRole.CONTROLLER);
    const userWithAdvanced = getToolNames([
      PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS,
    ], SystemRole.USER);

    expect(controllerWithAdvanced).toContain("get_timeline_entries_view");
    expect(controllerWithAdvanced).toContain("get_timeline_holiday_overlays");
    expect(controllerWithAdvanced).toContain("get_project_timeline_context");
    expect(controllerWithAdvanced).toContain("preview_project_shift");
    expect(controllerWithoutAdvanced).not.toContain("get_timeline_entries_view");
    expect(controllerWithoutAdvanced).not.toContain("get_timeline_holiday_overlays");
    expect(controllerWithoutAdvanced).not.toContain("get_project_timeline_context");
    expect(controllerWithoutAdvanced).not.toContain("preview_project_shift");
    expect(userWithAdvanced).not.toContain("get_timeline_entries_view");
    expect(userWithAdvanced).not.toContain("get_timeline_holiday_overlays");
    expect(userWithAdvanced).not.toContain("get_project_timeline_context");
    expect(userWithAdvanced).not.toContain("preview_project_shift");
  });

  it("exposes self-service timeline tools to authenticated users without advanced assistant access", () => {
    const userNames = getToolNames([], SystemRole.USER);
    const viewerNames = getToolNames([], SystemRole.VIEWER);
    const controllerNames = getToolNames([], SystemRole.CONTROLLER);

    expect(userNames).toContain("get_my_timeline_entries_view");
    expect(userNames).toContain("get_my_timeline_holiday_overlays");
    expect(viewerNames).toContain("get_my_timeline_entries_view");
    expect(viewerNames).toContain("get_my_timeline_holiday_overlays");
    expect(controllerNames).toContain("get_my_timeline_entries_view");
    expect(controllerNames).toContain("get_my_timeline_holiday_overlays");
  });

  it("keeps timeline write parity tools behind manager/admin role, manageAllocations, and advanced assistant access", () => {
    const managerNames = getToolNames([
      PermissionKey.MANAGE_ALLOCATIONS,
      PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS,
    ], SystemRole.MANAGER);
    const userNames = getToolNames([
      PermissionKey.MANAGE_ALLOCATIONS,
      PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS,
    ], SystemRole.USER);
    const missingAdvancedNames = getToolNames([
      PermissionKey.MANAGE_ALLOCATIONS,
    ], SystemRole.MANAGER);

    expect(managerNames).toContain("update_timeline_allocation_inline");
    expect(managerNames).toContain("apply_timeline_project_shift");
    expect(managerNames).toContain("quick_assign_timeline_resource");
    expect(managerNames).toContain("batch_quick_assign_timeline_resources");
    expect(managerNames).toContain("batch_shift_timeline_allocations");
    expect(userNames).not.toContain("update_timeline_allocation_inline");
    expect(userNames).not.toContain("apply_timeline_project_shift");
    expect(userNames).not.toContain("quick_assign_timeline_resource");
    expect(userNames).not.toContain("batch_quick_assign_timeline_resources");
    expect(userNames).not.toContain("batch_shift_timeline_allocations");
    expect(missingAdvancedNames).not.toContain("update_timeline_allocation_inline");
    expect(missingAdvancedNames).not.toContain("quick_assign_timeline_resource");
  });

  it("keeps estimate lifecycle mutations behind manager/admin role and their router permissions", () => {
    const managerProjectNames = getToolNames([PermissionKey.MANAGE_PROJECTS], SystemRole.MANAGER);
    const managerAllocationNames = getToolNames([PermissionKey.MANAGE_ALLOCATIONS], SystemRole.MANAGER);
    const userProjectNames = getToolNames([PermissionKey.MANAGE_PROJECTS], SystemRole.USER);

    expect(managerProjectNames).toContain("create_estimate");
    expect(managerProjectNames).toContain("clone_estimate");
    expect(managerProjectNames).toContain("update_estimate_draft");
    expect(managerProjectNames).toContain("submit_estimate_version");
    expect(managerProjectNames).toContain("approve_estimate_version");
    expect(managerProjectNames).toContain("create_estimate_revision");
    expect(managerProjectNames).toContain("create_estimate_export");
    expect(managerProjectNames).toContain("generate_estimate_weekly_phasing");
    expect(managerProjectNames).toContain("update_estimate_commercial_terms");
    expect(managerProjectNames).not.toContain("create_estimate_planning_handoff");
    expect(managerAllocationNames).toContain("create_estimate_planning_handoff");
    expect(managerAllocationNames).not.toContain("create_estimate");
    expect(userProjectNames).not.toContain("create_estimate");
    expect(userProjectNames).not.toContain("clone_estimate");
    expect(userProjectNames).not.toContain("update_estimate_draft");
    expect(userProjectNames).not.toContain("submit_estimate_version");
    expect(userProjectNames).not.toContain("approve_estimate_version");
    expect(userProjectNames).not.toContain("create_estimate_revision");
    expect(userProjectNames).not.toContain("create_estimate_export");
    expect(userProjectNames).not.toContain("generate_estimate_weekly_phasing");
    expect(userProjectNames).not.toContain("update_estimate_commercial_terms");
    expect(userProjectNames).not.toContain("create_estimate_planning_handoff");
  });

  it("keeps estimate read tools aligned to controller/manager/admin visibility and cost requirements", () => {
    const controllerNames = getToolNames([PermissionKey.VIEW_COSTS], SystemRole.CONTROLLER);
    const controllerWithoutCosts = getToolNames([], SystemRole.CONTROLLER);
    const managerNames = getToolNames([PermissionKey.VIEW_COSTS], SystemRole.MANAGER);
    const managerWithoutCosts = getToolNames([], SystemRole.MANAGER);
    const userNames = getToolNames([PermissionKey.VIEW_COSTS], SystemRole.USER);

    expect(controllerNames).toContain("search_estimates");
    expect(controllerNames).toContain("get_estimate_detail");
    expect(controllerNames).toContain("list_estimate_versions");
    expect(controllerNames).toContain("get_estimate_version_snapshot");
    expect(controllerNames).toContain("get_estimate_weekly_phasing");
    expect(controllerNames).toContain("get_estimate_commercial_terms");
    expect(controllerWithoutCosts).toContain("search_estimates");
    expect(controllerWithoutCosts).not.toContain("get_estimate_detail");
    expect(controllerWithoutCosts).toContain("list_estimate_versions");
    expect(controllerWithoutCosts).not.toContain("get_estimate_version_snapshot");
    expect(controllerWithoutCosts).toContain("get_estimate_weekly_phasing");
    expect(controllerWithoutCosts).toContain("get_estimate_commercial_terms");
    expect(managerNames).toContain("search_estimates");
    expect(managerNames).toContain("get_estimate_detail");
    expect(managerNames).toContain("list_estimate_versions");
    expect(managerNames).toContain("get_estimate_version_snapshot");
    expect(managerNames).toContain("get_estimate_weekly_phasing");
    expect(managerNames).toContain("get_estimate_commercial_terms");
    expect(managerWithoutCosts).toContain("search_estimates");
    expect(managerWithoutCosts).toContain("list_estimate_versions");
    expect(managerWithoutCosts).not.toContain("get_estimate_version_snapshot");
    expect(userNames).not.toContain("search_estimates");
    expect(userNames).not.toContain("get_estimate_detail");
    expect(userNames).not.toContain("list_estimate_versions");
    expect(userNames).not.toContain("get_estimate_version_snapshot");
    expect(userNames).not.toContain("get_estimate_weekly_phasing");
    expect(userNames).not.toContain("get_estimate_commercial_terms");
  });
});
