import type { FraudAdapter, EarnCtx, SignupCtx, FraudSignal, AdapterConfig } from '../types.js'
import { sql } from 'drizzle-orm'
import { referralsTable } from '../../schema.js'

export const ipClusterAdapter: FraudAdapter<EarnCtx | SignupCtx> = {
  key: 'ip-cluster',
  points: ['SIGNUP', 'EARN'],
  async evaluate(ctx: EarnCtx | SignupCtx, cfg: AdapterConfig): Promise<FraudSignal | null> {
    const windowHours = Number(cfg.params?.['windowHours'] ?? 4)
    if (!Number.isInteger(windowHours) || windowHours <= 0 || windowHours > 8760) return null
    const threshold = (cfg.params?.['clusterSize'] as number | undefined) ?? 3

    let ipHash: string | undefined
    let db: EarnCtx['db']

    if ('referralId' in ctx) {
      const earnCtx = ctx as EarnCtx
      db = earnCtx.db
      // Load ip_hash_referee from referral row
      const [row] = await db
        .select({ ipHashReferee: referralsTable.ipHashReferee })
        .from(referralsTable)
        .where(sql`${referralsTable.id} = ${earnCtx.referralId}`)
        .limit(1)
      ipHash = row?.ipHashReferee ?? undefined
    } else {
      const signupCtx = ctx as SignupCtx
      db = signupCtx.db
      ipHash = signupCtx.ipHash
    }

    if (!ipHash) return null

    const result = (await db.execute(sql`
      SELECT COUNT(*) AS cnt
      FROM referrals
      WHERE ip_hash_referee = ${ipHash}
        AND created_at >= NOW() - (INTERVAL '1 hour' * ${windowHours})
    `)) as { rows: Array<{ cnt: string }> }
    const cnt = Number((result.rows[0] as { cnt: string })?.cnt ?? 0)

    if (cnt < threshold) return null

    return {
      adapter: 'ip-cluster',
      action: 'flag',
      codes: ['IP_CLUSTER'],
      detail: { ipHashSuffix: ipHash.slice(-8), clusterSize: cnt, windowHours },
    }
  },
}
