import type {
  ApiKeyWalletPolicyBindingScope,
  ApprovalRequestStatus,
  PolicyControlInventoryStatus,
  PolicyControlInventoryTarget,
  PolicyDecision,
  PolicyDefaultAction,
  PolicyEvaluationContext,
  PolicyProfileStatus,
  PolicyProviderSyncStatus,
  PolicyRule,
  WalletOperationActor,
  WalletOperationContext,
  WalletOperationFamily,
  WalletOperationProviderExtensions,
  WalletOperationStatus,
} from "@sdp/types";
import type { RepositoryDbClient } from "./base";

export function generateWalletControlProfileId(): string {
  return `wcp_${crypto.randomUUID()}`;
}

export function generateWalletControlProfileRevisionId(): string {
  return `wcpr_${crypto.randomUUID()}`;
}

export function generateApiKeyControlProfileId(): string {
  return `akcp_${crypto.randomUUID()}`;
}

export function generateApiKeyControlProfileRevisionId(): string {
  return `akcpr_${crypto.randomUUID()}`;
}

export function generateApiKeyWalletPolicyBindingId(): string {
  return `akwpol_${crypto.randomUUID()}`;
}

export function generateWalletOperationId(): string {
  return `wop_${crypto.randomUUID()}`;
}

export function generatePolicyEvaluationId(): string {
  return `peval_${crypto.randomUUID()}`;
}

export function generateApprovalRequestId(): string {
  return `appr_${crypto.randomUUID()}`;
}

export interface WalletControlProfileRow {
  id: string;
  organization_id: string;
  project_id: string | null;
  custody_wallet_id: string;
  name: string;
  status: PolicyProfileStatus;
  active_revision_id: string | null;
  created_by: string | null;
  created_at: string;
  updated_at: string;
  activated_at: string | null;
  archived_at: string | null;
}

export interface WalletControlProfileRevisionRow {
  id: string;
  profile_id: string;
  revision_number: number;
  rules: Record<string, unknown>[];
  default_action: PolicyDefaultAction;
  commit_message: string | null;
  created_by: string | null;
  created_at: string;
  activated_at: string | null;
}

export interface ApiKeyControlProfileRow {
  id: string;
  organization_id: string;
  project_id: string | null;
  api_key_id: string;
  name: string;
  status: PolicyProfileStatus;
  active_revision_id: string | null;
  created_by: string | null;
  created_at: string;
  updated_at: string;
  activated_at: string | null;
  archived_at: string | null;
}

export interface ApiKeyControlProfileRevisionRow {
  id: string;
  profile_id: string;
  revision_number: number;
  rules: Record<string, unknown>[];
  default_action: PolicyDefaultAction;
  created_by: string | null;
  created_at: string;
  activated_at: string | null;
}

export interface ApiKeyWalletPolicyBindingRow {
  id: string;
  api_key_id: string;
  binding_scope: ApiKeyWalletPolicyBindingScope;
  wallet_id: string | null;
  custody_wallet_id: string | null;
  wallet_control_profile_id: string | null;
  api_key_control_profile_id: string | null;
  created_at: string;
  updated_at: string;
}

export interface ActivePolicyProfileRevisionRefRow {
  profile_id: string;
  active_revision_id: string | null;
}

export interface PolicyControlInventoryRow {
  target_type: Exclude<PolicyControlInventoryTarget, "all">;
  target_id: string;
  wallet_id: string | null;
  display_name: string;
  wallet_address: string | null;
  api_key_prefix: string | null;
  control_profile_id: string | null;
  status: PolicyControlInventoryStatus;
  active_revision_id: string | null;
  active_revision_number: number | null;
  default_action: PolicyDefaultAction;
  rule_count: number;
  updated_at: string;
  activated_at: string | null;
  provider_mapping_status: PolicyProviderSyncStatus | null;
  binding_scope: ApiKeyWalletPolicyBindingScope | null;
  selected_wallet_count: number | null;
  latest_evaluation_decision: PolicyDecision | null;
  latest_evaluation_at: string | null;
}

export interface ListPolicyControlInventoryInput {
  organizationId: string;
  projectId: string | null;
  target?: PolicyControlInventoryTarget;
  status?: PolicyControlInventoryStatus;
  query?: string;
  walletIds?: string[];
  page?: number;
  pageSize?: number;
}

export interface PolicyControlInventorySummaryRow {
  total: number;
  default_allow: number;
  draft: number;
  active: number;
  disabled: number;
  total_api_key_bindings: number;
}

export interface ListPolicyControlInventoryResult {
  rows: PolicyControlInventoryRow[];
  total: number;
  summary: PolicyControlInventorySummaryRow;
}

export interface WalletOperationRow {
  id: string;
  organization_id: string;
  project_id: string | null;
  custody_wallet_id: string | null;
  wallet_id: string;
  api_key_id: string | null;
  source: string;
  operation_family: WalletOperationFamily;
  operation_type: string;
  asset: string | null;
  amount: string | null;
  destination: string | null;
  raw_payload: Record<string, unknown>;
  idempotency_key: string | null;
  status: WalletOperationStatus;
  execution_started_at: string | null;
  execution_completed_at: string | null;
  execution_error: string | null;
  execution_result: Record<string, unknown> | null;
  execution_attempt_id: string | null;
  execution_lease_expires_at: string | null;
  execution_effect_started_at: string | null;
  execution_attempts: number;
  created_at: string;
  updated_at: string;
}

export interface PolicyEvaluationRow {
  id: string;
  wallet_operation_id: string;
  wallet_policy_revision_id: string | null;
  api_key_policy_revision_id: string | null;
  decision: PolicyDecision;
  reason_code: string;
  reason: string | null;
  matched_rules: Record<string, unknown>[];
  evaluation_context: PolicyEvaluationContext | null;
  requires_approval: boolean;
  approval_request_id: string | null;
  created_at: string;
}

export interface WalletPolicyEvaluationAuditRow {
  wallet_operation_id: string;
  policy_evaluation_id: string;
  operation_family: WalletOperationFamily;
  operation_type: string;
  asset: string | null;
  amount: string | null;
  destination: string | null;
  operation_status: WalletOperationStatus;
  wallet_policy_revision_id: string | null;
  active_wallet_policy_revision_id: string | null;
  api_key_policy_revision_id: string | null;
  active_api_key_policy_revision_id: string | null;
  decision: PolicyDecision;
  reason_code: string;
  reason: string | null;
  matched_rules: Record<string, unknown>[];
  evaluation_context: PolicyEvaluationContext | null;
  requires_approval: boolean;
  approval_request_id: string | null;
  operation_created_at: string;
  operation_updated_at: string;
  evaluated_at: string;
}

export interface ApprovalRequestRow {
  id: string;
  organization_id: string;
  project_id: string | null;
  wallet_operation_id: string;
  approval_group_id: string | null;
  status: ApprovalRequestStatus;
  provider: string | null;
  provider_reference: string | null;
  provider_payload: Record<string, unknown>;
  requested_by: string | null;
  resolved_by: string | null;
  expires_at: string | null;
  resolved_at: string | null;
  created_at: string;
  updated_at: string;
}

export interface ApprovalRequestDetailRow {
  approval_request_id: string;
  organization_id: string;
  project_id: string | null;
  wallet_operation_id: string;
  approval_group_id: string | null;
  approval_status: ApprovalRequestStatus;
  provider: string | null;
  provider_reference: string | null;
  requested_by: string | null;
  resolved_by: string | null;
  expires_at: string | null;
  resolved_at: string | null;
  approval_created_at: string;
  approval_updated_at: string;
  custody_wallet_id: string | null;
  wallet_id: string;
  wallet_public_key: string | null;
  wallet_label: string | null;
  api_key_id: string | null;
  source: string;
  operation_family: WalletOperationFamily;
  operation_type: string;
  asset: string | null;
  amount: string | null;
  destination: string | null;
  operation_status: WalletOperationStatus;
  operation_execution_started_at: string | null;
  operation_execution_completed_at: string | null;
  operation_execution_error: string | null;
  operation_created_at: string;
  operation_updated_at: string;
  policy_evaluation_id: string | null;
  decision: PolicyDecision | null;
  reason_code: string | null;
  reason: string | null;
  matched_rules: Record<string, unknown>[];
  requires_approval: boolean | null;
  evaluated_at: string | null;
}

export interface ActiveWalletControlProfileResult {
  profile: WalletControlProfileRow;
  revision: WalletControlProfileRevisionRow | null;
}

export interface ActiveApiKeyControlProfileResult {
  profile: ApiKeyControlProfileRow;
  revision: ApiKeyControlProfileRevisionRow | null;
}

export interface ApiKeyPolicySubjectRow {
  api_key_id: string;
  organization_id: string;
  project_id: string | null;
}

export interface ApiKeyWalletPolicyTargetRow {
  api_key_id: string;
  organization_id: string;
  project_id: string | null;
  wallet_id: string;
  custody_wallet_id: string;
  wallet_project_id: string | null;
  endpoint_binding_count: number;
  endpoint_wallet_binding_id: string | null;
}

export interface ApiKeyWalletPolicyBindingResolutionRow {
  total_binding_count: number;
  binding: ApiKeyWalletPolicyBindingRow | null;
}

export interface CreateWalletControlProfileInput {
  organizationId: string;
  projectId: string | null;
  custodyWalletId: string;
  name: string;
  status?: PolicyProfileStatus;
  createdBy?: string | null;
}

export interface CreateWalletControlProfileRevisionInput {
  profileId: string;
  rules?: PolicyRule[];
  defaultAction?: PolicyDefaultAction;
  commitMessage?: string | null;
  createdBy?: string | null;
}

export interface ActivateWalletControlProfileRevisionInput {
  profileId: string;
  revisionId: string;
  activatedAt?: string;
}

export interface CreateApiKeyControlProfileInput {
  organizationId: string;
  projectId: string | null;
  apiKeyId: string;
  name: string;
  status?: PolicyProfileStatus;
  createdBy?: string | null;
}

export interface CreateApiKeyControlProfileRevisionInput {
  profileId: string;
  rules?: PolicyRule[];
  defaultAction?: PolicyDefaultAction;
  createdBy?: string | null;
}

export interface ActivateApiKeyControlProfileRevisionInput {
  profileId: string;
  revisionId: string;
  activatedAt?: string;
}

interface UpsertApiKeyWalletPolicyBindingBaseInput {
  apiKeyId: string;
  walletControlProfileId?: string | null;
  apiKeyControlProfileId?: string | null;
}

export type UpsertApiKeyWalletPolicyBindingInput = UpsertApiKeyWalletPolicyBindingBaseInput &
  (
    | {
        bindingScope: "all";
        walletId?: null;
        custodyWalletId?: null;
      }
    | {
        bindingScope: "selected";
        walletId: string;
        custodyWalletId: string;
      }
  );

export interface ReplaceApiKeyWalletPolicyBindingsInput {
  apiKeyId: string;
  bindings: UpsertApiKeyWalletPolicyBindingInput[];
}

export interface CreateWalletOperationInput {
  organizationId: string;
  projectId: string | null;
  custodyWalletId?: string | null;
  walletId: string;
  apiKeyId?: string | null;
  actor?: WalletOperationActor | null;
  source?: string;
  operationFamily: WalletOperationFamily;
  operationType: string;
  asset?: string | null;
  amount?: string | null;
  destination?: string | null;
  context?: WalletOperationContext;
  providerExtensions?: WalletOperationProviderExtensions;
  rawPayload?: Record<string, unknown>;
  idempotencyKey?: string | null;
  status?: WalletOperationStatus;
}

export interface CreatePolicyEvaluationInput {
  walletOperationId: string;
  walletPolicyRevisionId?: string | null;
  apiKeyPolicyRevisionId?: string | null;
  decision: PolicyDecision;
  reasonCode: string;
  reason?: string | null;
  matchedRules?: Record<string, unknown>[];
  evaluationContext: PolicyEvaluationContext;
  requiresApproval?: boolean;
  approvalRequestId?: string | null;
}

export interface CreateApprovalRequestInput {
  organizationId: string;
  projectId: string | null;
  walletOperationId: string;
  approvalGroupId?: string | null;
  provider?: string | null;
  providerReference?: string | null;
  providerPayload?: Record<string, unknown>;
  requestedBy?: string | null;
  expiresAt?: string | null;
}

export interface UpdateApprovalRequestStatusInput {
  organizationId: string;
  projectId: string | null;
  approvalRequestId: string;
  status: ApprovalRequestStatus;
  operationStatus?: WalletOperationStatus;
  resolvedBy?: string | null;
  resolvedAt?: string;
}

export interface CompleteWalletOperationExecutionInput {
  walletOperationId: string;
  executionAttemptId: string;
  status: "completed" | "failed";
  result?: Record<string, unknown> | null;
  error?: string | null;
}

export interface ListApprovalRequestDetailsInput {
  organizationId: string;
  projectId: string | null;
  status?: ApprovalRequestStatus;
  limit?: number;
}

export interface GetApprovalRequestDetailInput {
  organizationId: string;
  projectId: string | null;
  approvalRequestId: string;
}

export interface GetWalletControlProfileRevisionHistoryInput {
  organizationId: string;
  projectId: string | null;
  custodyWalletId: string;
}

export interface WalletControlProfileRevisionHistoryRow {
  profile: WalletControlProfileRow;
  revisions: WalletControlProfileRevisionRow[];
}

export interface ListWalletPolicyEvaluationAuditsInput {
  organizationId: string;
  projectId: string | null;
  custodyWalletId: string;
  page?: number;
  pageSize?: number;
  decision?: PolicyDecision;
  status?: WalletOperationStatus;
  operationFamily?: WalletOperationFamily;
  reasonCode?: string;
}

export interface ListWalletPolicyEvaluationAuditsResult {
  rows: WalletPolicyEvaluationAuditRow[];
  total: number;
}

export interface GetWalletPolicyEvaluationAuditInput {
  organizationId: string;
  projectId: string | null;
  custodyWalletId: string;
  policyEvaluationId: string;
}

export interface PolicyRepositoryContext {
  db: RepositoryDbClient;
}

export interface PolicyRepository {
  listPolicyControlInventory(
    input: ListPolicyControlInventoryInput
  ): Promise<ListPolicyControlInventoryResult>;
  createWalletControlProfile(
    input: CreateWalletControlProfileInput
  ): Promise<WalletControlProfileRow | null>;
  createWalletControlProfileRevision(
    input: CreateWalletControlProfileRevisionInput
  ): Promise<WalletControlProfileRevisionRow | null>;
  activateWalletControlProfileRevision(
    input: ActivateWalletControlProfileRevisionInput
  ): Promise<ActiveWalletControlProfileResult | null>;
  getActiveWalletControlProfileByCustodyWalletId(
    custodyWalletId: string
  ): Promise<ActiveWalletControlProfileResult | null>;
  getActiveWalletControlProfileByProfileId(
    profileId: string
  ): Promise<ActiveWalletControlProfileResult | null>;
  getWalletControlProfileRevisionHistory(
    input: GetWalletControlProfileRevisionHistoryInput
  ): Promise<WalletControlProfileRevisionHistoryRow | null>;

  createApiKeyControlProfile(
    input: CreateApiKeyControlProfileInput
  ): Promise<ApiKeyControlProfileRow | null>;
  getApiKeyControlProfileById(profileId: string): Promise<ApiKeyControlProfileRow | null>;
  createApiKeyControlProfileRevision(
    input: CreateApiKeyControlProfileRevisionInput
  ): Promise<ApiKeyControlProfileRevisionRow | null>;
  getApiKeyControlProfileRevisionById(
    revisionId: string
  ): Promise<ApiKeyControlProfileRevisionRow | null>;
  activateApiKeyControlProfileRevision(
    input: ActivateApiKeyControlProfileRevisionInput
  ): Promise<ActiveApiKeyControlProfileResult | null>;
  getActiveApiKeyControlProfileByApiKeyId(
    apiKeyId: string
  ): Promise<ActiveApiKeyControlProfileResult | null>;
  getActiveApiKeyControlProfileByProfileId(
    profileId: string
  ): Promise<ActiveApiKeyControlProfileResult | null>;
  getApiKeyPolicySubject(apiKeyId: string): Promise<ApiKeyPolicySubjectRow | null>;

  upsertApiKeyWalletPolicyBinding(
    input: UpsertApiKeyWalletPolicyBindingInput
  ): Promise<ApiKeyWalletPolicyBindingRow | null>;
  replaceApiKeyWalletPolicyBindings(
    input: ReplaceApiKeyWalletPolicyBindingsInput
  ): Promise<ApiKeyWalletPolicyBindingRow[]>;
  listApiKeyWalletPolicyBindings(apiKeyId: string): Promise<ApiKeyWalletPolicyBindingRow[]>;
  listApiKeyWalletPolicyBindingsForApiKeys(
    apiKeyIds: string[]
  ): Promise<ApiKeyWalletPolicyBindingRow[]>;
  listActiveWalletControlProfileRevisionRefs(
    profileIds: string[]
  ): Promise<ActivePolicyProfileRevisionRefRow[]>;
  listActiveApiKeyControlProfileRevisionRefs(
    profileIds: string[]
  ): Promise<ActivePolicyProfileRevisionRefRow[]>;
  getApiKeyWalletPolicyBindingResolution(
    apiKeyId: string,
    custodyWalletId: string
  ): Promise<ApiKeyWalletPolicyBindingResolutionRow>;
  getApiKeyWalletPolicyTarget(
    apiKeyId: string,
    custodyWalletId: string
  ): Promise<ApiKeyWalletPolicyTargetRow | null>;

  createWalletOperation(input: CreateWalletOperationInput): Promise<WalletOperationRow | null>;
  getWalletOperationById(walletOperationId: string): Promise<WalletOperationRow | null>;
  updateWalletOperationStatus(
    walletOperationId: string,
    status: WalletOperationStatus
  ): Promise<WalletOperationRow | null>;
  claimWalletOperationExecution(
    walletOperationId: string,
    executionAttemptId: string
  ): Promise<WalletOperationRow | null>;
  renewWalletOperationExecutionLease(
    walletOperationId: string,
    executionAttemptId: string
  ): Promise<boolean>;
  beginWalletOperationExecutionEffect(
    walletOperationId: string,
    executionAttemptId: string
  ): Promise<boolean>;
  completeWalletOperationExecution(
    input: CompleteWalletOperationExecutionInput
  ): Promise<WalletOperationRow | null>;
  getApiKeyCreatorUserId(apiKeyId: string): Promise<string | null>;
  isApprovalGroupMember(approvalGroupId: string, userId: string): Promise<boolean>;
  createPolicyEvaluation(input: CreatePolicyEvaluationInput): Promise<PolicyEvaluationRow | null>;
  listPolicyEvaluationsForOperation(walletOperationId: string): Promise<PolicyEvaluationRow[]>;
  listWalletPolicyEvaluationAudits(
    input: ListWalletPolicyEvaluationAuditsInput
  ): Promise<ListWalletPolicyEvaluationAuditsResult>;
  getWalletPolicyEvaluationAudit(
    input: GetWalletPolicyEvaluationAuditInput
  ): Promise<WalletPolicyEvaluationAuditRow | null>;
  createApprovalRequest(input: CreateApprovalRequestInput): Promise<ApprovalRequestRow | null>;
  updateApprovalRequestStatus(
    input: UpdateApprovalRequestStatusInput
  ): Promise<ApprovalRequestRow | null>;
  listApprovalRequestDetails(
    input: ListApprovalRequestDetailsInput
  ): Promise<ApprovalRequestDetailRow[]>;
  getApprovalRequestDetail(
    input: GetApprovalRequestDetailInput
  ): Promise<ApprovalRequestDetailRow | null>;
}
