import type { defineModule as defineUserManagementModule } from "../user-management";
import { activateApprovalPolicy } from "./command/activateApprovalPolicy.generated";
import { approveApprovalStep } from "./command/approveApprovalStep.generated";
import { cancelApprovalRequest } from "./command/cancelApprovalRequest.generated";
import { createApprovalPolicy } from "./command/createApprovalPolicy.generated";
import { createApprovalRequest } from "./command/createApprovalRequest.generated";
import { deactivateApprovalPolicy } from "./command/deactivateApprovalPolicy.generated";
import { delegateApprovalStep } from "./command/delegateApprovalStep.generated";
import { rejectApprovalStep } from "./command/rejectApprovalStep.generated";
import { resubmitApprovalRequest } from "./command/resubmitApprovalRequest.generated";
import { sendBackApprovalStep } from "./command/sendBackApprovalStep.generated";
import { updateApprovalPolicy } from "./command/updateApprovalPolicy.generated";
import { withdrawApprovalRequest } from "./command/withdrawApprovalRequest.generated";
import { createApprovalDecisionType } from "./db/approvalDecision";
import { createApprovalPolicyType } from "./db/approvalPolicy";
import { createApprovalPolicyStepType } from "./db/approvalPolicyStep";
import { createApprovalPolicyStepAssigneeType } from "./db/approvalPolicyStepAssignee";
import { createApprovalRequestType } from "./db/approvalRequest";
import { createApprovalStepType } from "./db/approvalStep";
import { createApprovalStepAssigneeType } from "./db/approvalStepAssignee";
import { getActiveApprovalRequest } from "./query/getActiveApprovalRequest.generated";
import { getApprovalDecisionHistory } from "./query/getApprovalDecisionHistory.generated";
import { listApprovalPolicies } from "./query/listApprovalPolicies.generated";
import { listApprovalRequestsByTarget } from "./query/listApprovalRequestsByTarget.generated";
import { listApprovalRequestsForApprover } from "./query/listApprovalRequestsForApprover.generated";
import { listApprovalRequestsForRequester } from "./query/listApprovalRequestsForRequester.generated";

type UserManagementModule = ReturnType<typeof defineUserManagementModule>;
type UserManagementDB = UserManagementModule["db"];
export type UserManagementQueries = UserManagementModule["queries"];

export interface DefineModuleParams {
  userManagement: {
    db: { user: UserManagementDB["user"]; role: UserManagementDB["role"] };
    queries: { listUsersByRole: UserManagementQueries["listUsersByRole"] };
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = (params: DefineModuleParams) => {
  const approvalPolicy = createApprovalPolicyType();
  const approvalPolicyStep = createApprovalPolicyStepType();
  const approvalPolicyStepAssignee = createApprovalPolicyStepAssigneeType({
    userType: params.userManagement.db.user,
    roleType: params.userManagement.db.role,
  });
  const approvalRequest = createApprovalRequestType({
    userType: params.userManagement.db.user,
  });
  const approvalStep = createApprovalStepType();
  const approvalStepAssignee = createApprovalStepAssigneeType({
    userType: params.userManagement.db.user,
    roleType: params.userManagement.db.role,
  });
  const approvalDecision = createApprovalDecisionType({
    userType: params.userManagement.db.user,
  });

  const deps = { listUsersByRole: params.userManagement.queries.listUsersByRole };

  return {
    db: {
      approvalPolicy,
      approvalPolicyStep,
      approvalPolicyStepAssignee,
      approvalRequest,
      approvalStep,
      approvalStepAssignee,
      approvalDecision,
    },
    commands: {
      createApprovalPolicy: createApprovalPolicy(),
      updateApprovalPolicy: updateApprovalPolicy(),
      activateApprovalPolicy: activateApprovalPolicy(),
      deactivateApprovalPolicy: deactivateApprovalPolicy(),
      createApprovalRequest: createApprovalRequest(deps),
      withdrawApprovalRequest: withdrawApprovalRequest(),
      cancelApprovalRequest: cancelApprovalRequest(),
      approveApprovalStep: approveApprovalStep(deps),
      rejectApprovalStep: rejectApprovalStep(),
      sendBackApprovalStep: sendBackApprovalStep(),
      delegateApprovalStep: delegateApprovalStep(),
      resubmitApprovalRequest: resubmitApprovalRequest(),
    },
    queries: {
      listApprovalPolicies,
      getActiveApprovalRequest,
      listApprovalRequestsByTarget,
      listApprovalRequestsForApprover,
      listApprovalRequestsForRequester,
      getApprovalDecisionHistory,
    },
  };
};
