import { SystemRole } from "@capakraken/shared";
import type { TRPCContext } from "../../trpc.js";
import { withToolAccess, type ToolContext, type ToolDef, type ToolExecutor } from "./shared.js";

type AuditListItem = {
  id: string;
  entityType: string;
  entityId: string;
  entityName: string | null;
  action: string;
  userId: string | null;
  source: string | null;
  summary: string | null;
  createdAt: string;
  user: {
    id: string;
    name: string | null;
    email: string | null;
  } | null;
};

type AuditHistoryDeps = {
  createAuditLogCaller: (ctx: TRPCContext) => {
    listDetail: (params: {
      entityType?: string;
      entityId?: string;
      userId?: string;
      action?: string;
      source?: string;
      startDate?: Date;
      endDate?: Date;
      search?: string;
      limit: number;
      cursor?: string;
    }) => Promise<{
      items: AuditListItem[];
      nextCursor: string | null;
    }>;
    getByEntityDetail: (params: {
      entityType: string;
      entityId: string;
      limit: number;
    }) => Promise<unknown>;
  };
  createScopedCallerContext: (ctx: ToolContext) => TRPCContext;
};

export const auditHistoryToolDefinitions: ToolDef[] = withToolAccess([
  {
    type: "function",
    function: {
      name: "query_change_history",
      description: "Search the audit history for changes to projects, resources, allocations, vacations, or any entity. Reuses the real audit log list API. Controller/manager/admin roles only.",
      parameters: {
        type: "object",
        properties: {
          entityType: { type: "string", description: "Filter by entity type (e.g. 'Project', 'Resource', 'Allocation', 'Vacation', 'Role', 'Estimate')" },
          search: { type: "string", description: "Search in entity name or summary text" },
          userId: { type: "string", description: "Filter by user ID who made the change" },
          daysBack: { type: "integer", description: "How many days back to search. Default: 7" },
          action: { type: "string", description: "Filter by action type: CREATE, UPDATE, DELETE, SHIFT, IMPORT" },
          limit: { type: "integer", description: "Max results. Default: 20" },
        },
      },
    },
  },
  {
    type: "function",
    function: {
      name: "get_entity_timeline",
      description: "Get the audit history for a specific entity (project, resource, etc.) via the real audit API. Controller/manager/admin roles only.",
      parameters: {
        type: "object",
        properties: {
          entityType: { type: "string", description: "Entity type (e.g. 'Project', 'Resource', 'Allocation')" },
          entityId: { type: "string", description: "Entity ID" },
          limit: { type: "integer", description: "Max results. Default: 50" },
        },
        required: ["entityType", "entityId"],
      },
    },
  },
], {
  query_change_history: {
    allowedSystemRoles: [SystemRole.ADMIN, SystemRole.MANAGER, SystemRole.CONTROLLER],
  },
  get_entity_timeline: {
    allowedSystemRoles: [SystemRole.ADMIN, SystemRole.MANAGER, SystemRole.CONTROLLER],
  },
});

export function createAuditHistoryExecutors(
  deps: AuditHistoryDeps,
): Record<string, ToolExecutor> {
  return {
    async query_change_history(
      params: {
        entityType?: string;
        search?: string;
        userId?: string;
        daysBack?: number;
        action?: string;
        limit?: number;
      },
      ctx: ToolContext,
    ) {
      const limit = Math.min(params.limit ?? 20, 50);
      const daysBack = params.daysBack ?? 7;
      const startDate = new Date();
      startDate.setDate(startDate.getDate() - daysBack);

      const caller = deps.createAuditLogCaller(deps.createScopedCallerContext(ctx));
      const result = await caller.listDetail({
        ...(params.entityType ? { entityType: params.entityType } : {}),
        ...(params.userId ? { userId: params.userId } : {}),
        ...(params.action ? { action: params.action } : {}),
        ...(params.search ? { search: params.search } : {}),
        startDate,
        limit,
      });

      return {
        filters: {
          entityType: params.entityType ?? null,
          userId: params.userId ?? null,
          action: params.action ?? null,
          search: params.search ?? null,
          daysBack,
        },
        itemCount: result.items.length,
        nextCursor: result.nextCursor ?? null,
        items: result.items,
      };
    },

    async get_entity_timeline(
      params: { entityType: string; entityId: string; limit?: number },
      ctx: ToolContext,
    ) {
      const limit = Math.min(params.limit ?? 50, 200);
      const caller = deps.createAuditLogCaller(deps.createScopedCallerContext(ctx));
      return caller.getByEntityDetail({
        entityType: params.entityType,
        entityId: params.entityId,
        limit,
      });
    },
  };
}
