import type { Querier } from '@platform-modules/db'
import type { FraudHostStore } from './host-store.js'

/** Adopter DB handle — generic over the host's combined schema. */
export type FraudDb = Querier<Record<string, unknown>>

export type FraudAction = 'pass' | 'flag' | 'hold' | 'block'

export type DecisionPoint = 'CLICK' | 'SIGNUP' | 'EARN' | 'WITHDRAW'

export type StoredDecisionPoint = 'click' | 'signup' | 'earn' | 'withdraw'

// Exhaustive map: in-memory domain enum (uppercase) → persisted/queryable representation (lowercase).
// Record<DecisionPoint, …> fails to compile if DecisionPoint gains a member.
const DECISION_POINT_STORAGE: Record<DecisionPoint, StoredDecisionPoint> = {
  CLICK: 'click',
  SIGNUP: 'signup',
  EARN: 'earn',
  WITHDRAW: 'withdraw',
}

export function toStoredDecisionPoint(point: DecisionPoint): StoredDecisionPoint {
  return DECISION_POINT_STORAGE[point]
}

export interface FraudSignal {
  adapter: string
  action: FraudAction
  codes: string[]
  score?: number
  detail?: Record<string, unknown>
}

export interface AdapterConfig {
  enabled: boolean
  /** Downgrade the adapter's natural action to at most this level. */
  action?: FraudAction
  params?: Record<string, unknown>
}

export interface FraudAdapter<Ctx = unknown> {
  /** Stable config key — must match fraud_config[key] and registry. */
  key: string
  points: DecisionPoint[]
  evaluate(ctx: Ctx, cfg: AdapterConfig): Promise<FraudSignal | null>
}

export interface PipelineResult {
  action: FraudAction
  signals: FraudSignal[]
}

export interface ClickCtx {
  ipHash: string
  userAgent: string
  country: string
  refererUrl: string
  linkId: string
  visitorId?: string
}

export interface SignupCtx {
  db: FraudDb
  host: FraudHostStore
  refereeUserId: string
  refereeEmail: string
  refereePhone?: string
  visitorId?: string
  ipHash?: string
  cfBotScore?: number
}

export interface EarnCtx {
  db: FraudDb
  host: FraudHostStore
  referralId: string
  referrerUserId: string
  refereeUserId: string
  purchaseId: string
  platformNetAgorot: number
  refereeEmail?: string
  refereePhone?: string
  refereeEmailCanonical?: string
  referrerEmailCanonical?: string
  visitorIdReferee?: string
  visitorIdReferrer?: string
  cardFingerprintReferee?: string
  cardFingerprintReferrer?: string
}

export interface WithdrawCtx {
  db: FraudDb
  userId: string
  amountAgorot: number
  affiliateId: string
}
