import { authPool } from '../db/authDb.js'

interface InsertAuditLogInput {
  userId: string
  actionCd: string
  actionDtl?: string
  httpMethod?: string
  crudType?: string
  reqUrl?: string
  resStatus?: number
  resSize?: number
  ipAddr?: string
  userAgent?: string
  extra?: Record<string, unknown>
}

interface AuditLogItem {
  logSn: number
  userId: string
  userName: string | null
  userAccount: string | null
  actionCd: string
  actionDtl: string | null
  httpMethod: string | null
  crudType: string | null
  reqUrl: string | null
  reqDtm: string
  resDtm: string | null
  resStatus: number | null
  resSize: number | null
  ipAddr: string | null
  userAgent: string | null
  extra: Record<string, unknown> | null
}

interface AuditLogListResult {
  items: AuditLogItem[]
  total: number
  page: number
  size: number
}

export async function insertAuditLog(input: InsertAuditLogInput): Promise<void> {
  await authPool.query(
    `INSERT INTO AUTH_AUDIT_LOG
       (USER_ID, ACTION_CD, ACTION_DTL, HTTP_METHOD, CRUD_TYPE, REQ_URL,
        RES_STATUS, RES_SIZE, IP_ADDR, USER_AGENT, EXTRA)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`,
    [
      input.userId,
      input.actionCd,
      input.actionDtl || null,
      input.httpMethod || null,
      input.crudType || null,
      input.reqUrl || null,
      input.resStatus || null,
      input.resSize || null,
      input.ipAddr || null,
      input.userAgent || null,
      input.extra ? JSON.stringify(input.extra) : null,
    ]
  )
}

export async function listAuditLogs(filters?: {
  page?: number
  size?: number
  userId?: string
  actionCd?: string
  from?: string
  to?: string
}): Promise<AuditLogListResult> {
  const page = filters?.page || 1
  const size = Math.min(filters?.size || 50, 200)
  const offset = (page - 1) * size

  let whereClause = 'WHERE 1=1'
  const params: (string | number)[] = []
  let paramIdx = 1

  if (filters?.userId) {
    whereClause += ` AND a.USER_ID = $${paramIdx++}`
    params.push(filters.userId)
  }
  if (filters?.actionCd) {
    whereClause += ` AND a.ACTION_CD = $${paramIdx++}`
    params.push(filters.actionCd)
  }
  if (filters?.from) {
    whereClause += ` AND a.REQ_DTM >= $${paramIdx++}`
    params.push(filters.from)
  }
  if (filters?.to) {
    whereClause += ` AND a.REQ_DTM <= $${paramIdx++}`
    params.push(filters.to)
  }

  const countResult = await authPool.query(
    `SELECT COUNT(*) as cnt FROM AUTH_AUDIT_LOG a ${whereClause}`,
    params
  )
  const total = parseInt(countResult.rows[0].cnt, 10)

  const dataParams = [...params, size, offset]
  const result = await authPool.query(
    `SELECT a.LOG_SN, a.USER_ID, u.USER_NM, u.USER_ACNT,
            a.ACTION_CD, a.ACTION_DTL, a.HTTP_METHOD, a.CRUD_TYPE,
            a.REQ_URL, a.REQ_DTM, a.RES_DTM, a.RES_STATUS, a.RES_SIZE,
            a.IP_ADDR, a.USER_AGENT, a.EXTRA
     FROM AUTH_AUDIT_LOG a
     LEFT JOIN AUTH_USER u ON a.USER_ID = u.USER_ID
     ${whereClause}
     ORDER BY a.REQ_DTM DESC
     LIMIT $${paramIdx++} OFFSET $${paramIdx}`,
    dataParams
  )

  const items: AuditLogItem[] = result.rows.map((row: Record<string, unknown>) => ({
    logSn: row.log_sn as number,
    userId: row.user_id as string,
    userName: row.user_nm as string | null,
    userAccount: row.user_acnt as string | null,
    actionCd: row.action_cd as string,
    actionDtl: row.action_dtl as string | null,
    httpMethod: row.http_method as string | null,
    crudType: row.crud_type as string | null,
    reqUrl: row.req_url as string | null,
    reqDtm: row.req_dtm as string,
    resDtm: row.res_dtm as string | null,
    resStatus: row.res_status as number | null,
    resSize: row.res_size as number | null,
    ipAddr: row.ip_addr as string | null,
    userAgent: row.user_agent as string | null,
    extra: row.extra as Record<string, unknown> | null,
  }))

  return { items, total, page, size }
}
