/**
 * Referral security guardrails — barrel export + pipeline runner.
 *
 * Middleware order (per spec §G):
 *   1. cookie-stuffing  — reject programmatic injections first (cheapest check)
 *   2. velocity         — reject bursts before any DB/network work
 *   3. referer-eval     — flag/reject disallowed origins
 *   4. brand-keyword    — flag search engine brand bids
 *   5. coupon-poaching  — flag coupon aggregator traffic
 *   6. cloaking         — flag bot UA + headless browser signals
 *   7. geo              — flag non-IL traffic
 *   8. fingerprint      — compute HMAC IP hash (always runs; no reject)
 *
 * Each guardrail returns a GuardResult with:
 *   - isSuspicious: boolean
 *   - codes: string[]   (suspicion codes logged to AE blob7)
 *   - setCookie: boolean (false = do not attribute this click)
 *
 * runSecurityPipeline returns the merged verdict. If ANY guardrail sets
 * setCookie=false, the pipeline result is setCookie=false.
 */

export type { GuardResult } from './brand-keyword.js'
export { evaluateBrandKeyword } from './brand-keyword.js'
export { evaluateGeo } from './geo.js'
export { evaluateCookieStuffing } from './cookie-stuffing.js'
export { evaluateReferer } from './referer-eval.js'
export { evaluateVelocity, _resetVelocityMap } from './velocity.js'
export { hashIp, evaluateFingerprint } from './fingerprint.js'
export { evaluateCouponPoaching } from './coupon-poaching.js'
export { evaluateCloaking } from './cloaking.js'

import { evaluateBrandKeyword, type BrandKeywordSettings } from './brand-keyword.js'
import { evaluateGeo } from './geo.js'
import { evaluateCookieStuffing, type SecFetchHeaders } from './cookie-stuffing.js'
import { evaluateReferer } from './referer-eval.js'
import { evaluateVelocity } from './velocity.js'
import { evaluateFingerprint } from './fingerprint.js'
import { evaluateCouponPoaching } from './coupon-poaching.js'
import { evaluateCloaking } from './cloaking.js'

export type SecurityPipelineInput = {
  ipHash: string
  refererUrl: string
  userAgent: string
  country: string
  secFetch: SecFetchHeaders
  settings: BrandKeywordSettings & { couponDomains?: string[]; allowedCountries?: string[] }
}

export type SecurityPipelineResult = {
  /** Whether any guardrail fired. */
  isSuspicious: boolean
  /** All suspicion codes from all guardrails that fired. */
  codes: string[]
  /** False if any guardrail vetoed attribution. */
  setCookie: boolean
}

/**
 * Run all 8 security guardrails in order and merge results.
 *
 * Short-circuits after cookie-stuffing or velocity if they reject (setCookie=false)
 * to avoid unnecessary work, but still collects all codes.
 */
export function runSecurityPipeline(input: SecurityPipelineInput): SecurityPipelineResult {
  const { ipHash, refererUrl, userAgent, country, secFetch, settings } = input
  const allCodes: string[] = []
  let setCookie = true

  // 1. Cookie-stuffing
  const csResult = evaluateCookieStuffing(secFetch)
  if (csResult.isSuspicious) allCodes.push(...csResult.codes)
  if (!csResult.setCookie) setCookie = false

  // 1b. Modern browser claiming to be Chrome/Edge/Firefox but missing
  // Sec-Fetch-Mode → not a real browser. Flag, do not block (some proxies
  // strip Fetch Metadata).
  const looksLikeModernBrowser =
    /Chrome\/[1-9]\d{2,}|Edg\/[1-9]\d{2,}|Firefox\/[1-9]\d{2,}/.test(userAgent)
  if (looksLikeModernBrowser && !secFetch.secFetchMode) {
    allCodes.push('FETCH_METADATA_MISSING')
  }

  // 2. Velocity
  const velResult = evaluateVelocity(ipHash)
  if (velResult.isSuspicious) allCodes.push(...velResult.codes)
  if (!velResult.setCookie) setCookie = false

  // 3. Referer eval
  const refResult = evaluateReferer(refererUrl, settings.disallowedRefererHosts)
  if (refResult.isSuspicious) allCodes.push(...refResult.codes)
  if (!refResult.setCookie) setCookie = false

  // 4. Brand keyword
  const bkResult = evaluateBrandKeyword(refererUrl, settings)
  if (bkResult.isSuspicious) allCodes.push(...bkResult.codes)
  if (!bkResult.setCookie) setCookie = false

  // 5. Coupon poaching
  const cpResult = evaluateCouponPoaching(refererUrl, settings.couponDomains ?? [])
  if (cpResult.isSuspicious) allCodes.push(...cpResult.codes)
  if (!cpResult.setCookie) setCookie = false

  // 6. Cloaking
  const clResult = evaluateCloaking(userAgent, secFetch.secFetchMode)
  if (clResult.isSuspicious) allCodes.push(...clResult.codes)
  if (!clResult.setCookie) setCookie = false

  // 7. Geo
  const geoResult = evaluateGeo(country, settings.allowedCountries ?? [])
  if (geoResult.isSuspicious) allCodes.push(...geoResult.codes)
  if (!geoResult.setCookie) setCookie = false

  // 8. Fingerprint (never rejects — just validates hash format)
  const fpResult = evaluateFingerprint(ipHash)
  if (fpResult.isSuspicious) allCodes.push(...fpResult.codes)
  if (!fpResult.setCookie) setCookie = false

  return {
    isSuspicious: allCodes.length > 0,
    codes: allCodes,
    setCookie,
  }
}
