import { query, withTransaction } from '../../db/client.js'
import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js'
import type { CreateWorkerInput, FinanceRequestListInput, ListInput, WalletLedgerListInput, WorkerFinanceRequestRow, WorkerLevelRow, WorkerUserRow, WorkerWalletLedgerRow, WorkerWalletRow } from './types.js'
import type { PoolClient } from 'pg'


const WORKER_USER_SELECT = `
  SELECT
    wu.*,
    wl.level_key,
    wl.name AS level_name,
    wl.permission_json AS level_permission_json,
    inv.username AS inviter_username,
    inv.display_name AS inviter_display_name,
    ww.available_amount,
    ww.frozen_deposit_amount,
    ww.pending_unfreeze_amount,
    ww.total_credited_amount,
    ww.total_settled_amount
  FROM worker_users wu
  LEFT JOIN worker_levels wl ON wl.id = wu.level_id
  LEFT JOIN worker_users inv ON inv.id = wu.inviter_id
  LEFT JOIN worker_wallets ww ON ww.worker_id = wu.id
`

const WORKER_FINANCE_REQUEST_SELECT = `
  SELECT
    wfr.*,
    wu.username AS worker_username,
    wu.display_name AS worker_display_name,
    wu.phone AS worker_phone
  FROM worker_finance_requests wfr
  LEFT JOIN worker_users wu ON wu.id = wfr.worker_id
`

export async function getWorkerLevelByKey(levelKey: string): Promise<WorkerLevelRow | null> {
  const result = await query<WorkerLevelRow>(
    'SELECT * FROM worker_levels WHERE level_key = $1 LIMIT 1',
    [String(levelKey || '').trim()],
  )
  return result.rows[0] || null
}

export async function getWorkerLevelById(levelId: number | string): Promise<WorkerLevelRow | null> {
  const result = await query<WorkerLevelRow>('SELECT * FROM worker_levels WHERE id = $1 LIMIT 1', [
    Number(levelId),
  ])
  return result.rows[0] || null
}

export async function listWorkerLevels(): Promise<WorkerLevelRow[]> {
  const result = await query<WorkerLevelRow>(
    'SELECT * FROM worker_levels ORDER BY sort_order ASC, id ASC',
  )
  return result.rows
}

export async function upsertWorkerLevel(input: {
  levelKey: string
  name: string
  sortOrder: number
  status: string
  permissionJson: string
  now: string
}): Promise<WorkerLevelRow | null> {
  const result = await query<WorkerLevelRow>(
    `
      INSERT INTO worker_levels (
        level_key, name, sort_order, status, permission_json, created_at, updated_at
      ) VALUES ($1, $2, $3, $4, $5::jsonb, $6, $7)
      ON CONFLICT (level_key) DO UPDATE
      SET
        name = EXCLUDED.name,
        sort_order = EXCLUDED.sort_order,
        status = EXCLUDED.status,
        permission_json = EXCLUDED.permission_json,
        updated_at = EXCLUDED.updated_at
      RETURNING *
    `,
    [
      input.levelKey,
      input.name,
      input.sortOrder,
      input.status,
      input.permissionJson,
      input.now,
      input.now,
    ],
  )
  return result.rows[0] || null
}

export async function countWorkerLevelUsages(levelId: number | string): Promise<number> {
  const result = await query<{ total: number }>(
    'SELECT COUNT(*)::int AS total FROM worker_users WHERE level_id = $1',
    [Number(levelId)],
  )
  return Number(result.rows[0]?.total || 0)
}

export async function deleteWorkerLevel(levelId: number | string): Promise<{ deleted: boolean }> {
  const result = await query<{ id: number }>(
    'DELETE FROM worker_levels WHERE id = $1 RETURNING id',
    [Number(levelId)],
  )
  return { deleted: Boolean(result.rows[0]) }
}

export async function getWorkerUserByUsername(username: string): Promise<WorkerUserRow | null> {
  const result = await query<WorkerUserRow>(
    `${WORKER_USER_SELECT} WHERE wu.username = $1 LIMIT 1`,
    [
      String(username || '')
        .trim()
        .toLowerCase(),
    ],
  )
  return result.rows[0] || null
}

export async function getWorkerUserByPhone(phone: string): Promise<WorkerUserRow | null> {
  const result = await query<WorkerUserRow>(
    `${WORKER_USER_SELECT} WHERE wu.phone = $1 LIMIT 1`,
    [String(phone || '').trim()],
  )
  return result.rows[0] || null
}

export async function getWorkerUserByInviteCode(
  inviteCode: string,
): Promise<WorkerUserRow | null> {
  const result = await query<WorkerUserRow>(
    `${WORKER_USER_SELECT} WHERE wu.invite_code = $1 LIMIT 1`,
    [String(inviteCode || '').trim().toUpperCase()],
  )
  return result.rows[0] || null
}

export async function getWorkerUserById(workerId: number | string): Promise<WorkerUserRow | null> {
  const result = await query<WorkerUserRow>(`${WORKER_USER_SELECT} WHERE wu.id = $1 LIMIT 1`, [
    Number(workerId),
  ])
  return result.rows[0] || null
}

export async function createWorkerUser(input: CreateWorkerInput): Promise<WorkerUserRow | null> {
  return withTransaction(async (client) => {
    const result = await client.query<{ id: number }>(
      `
        INSERT INTO worker_users (
          username, password_hash, display_name, phone, level_id, status,
          inviter_id, invite_code,
          created_at, updated_at
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
        RETURNING id
      `,
      [
        input.username,
        input.passwordHash,
        input.displayName,
        input.phone,
        input.levelId,
        input.status,
        input.inviterId || null,
        input.inviteCode,
        input.now,
        input.now,
      ],
    )
    const workerId = Number(result.rows[0]?.id || 0)
    await ensureWorkerWalletWithClient(client, workerId, input.now)
    return getWorkerUserByIdWithClient(client, workerId)
  })
}

export async function updateWorkerUser(
  workerId: number | string,
  patch: Partial<
    Pick<
      WorkerUserRow,
      'status' | 'review_note' | 'level_id' | 'session_version' | 'updated_at' | 'reviewed_at'
    >
  >,
): Promise<WorkerUserRow | null> {
  const current = await getWorkerUserById(workerId)
  if (!current) return null
  const next = { ...current, ...patch }

  await query(
    `
      UPDATE worker_users
      SET
        status = $1,
        review_note = $2,
        level_id = $3,
        session_version = $4,
        reviewed_at = $5,
        updated_at = $6
      WHERE id = $7
    `,
    [
      next.status,
      next.review_note || '',
      next.level_id || null,
      Number(next.session_version || 1),
      next.reviewed_at || null,
      next.updated_at,
      Number(workerId),
    ],
  )
  return getWorkerUserById(workerId)
}

export async function updateWorkerPassword(input: {
  workerId: number
  passwordHash: string
  sessionVersion: number
  now: string
}): Promise<WorkerUserRow | null> {
  const result = await query<{ id: number }>(
    `
      UPDATE worker_users
      SET
        password_hash = $1,
        session_version = $2,
        updated_at = $3
      WHERE id = $4
      RETURNING id
    `,
    [input.passwordHash, input.sessionVersion, input.now, input.workerId],
  )
  if (!result.rows[0]) {
    return null
  }
  return getWorkerUserById(input.workerId)
}

export async function incrementWorkerSessionVersion(
  workerId: number | string,
  now: string,
): Promise<WorkerUserRow | null> {
  const result = await query<{ id: number }>(
    `
      UPDATE worker_users
      SET session_version = session_version + 1, updated_at = $2
      WHERE id = $1
      RETURNING id
    `,
    [Number(workerId), now],
  )
  if (!result.rows[0]) {
    return null
  }
  return getWorkerUserById(workerId)
}

export async function listWorkerUsers({
  page = 1,
  pageSize = 20,
  status = '',
  keyword = '',
}: ListInput = {}): Promise<{ items: WorkerUserRow[]; total: number }> {
  const { whereClause, params } = buildWorkerUserWhere({ status, keyword })
  const totalResult = await query<{ total: number }>(
    `SELECT COUNT(*)::int AS total FROM worker_users wu ${whereClause}`,
    params,
  )

  const offset = (page - 1) * pageSize
  params.push(pageSize, offset)
  const itemsResult = await query<WorkerUserRow>(
    `${WORKER_USER_SELECT}
     ${whereClause}
     ORDER BY wu.id DESC
     LIMIT $${params.length - 1} OFFSET $${params.length}`,
    params,
  )
  return { items: itemsResult.rows, total: Number(totalResult.rows[0]?.total || 0) }
}

export async function ensureWorkerWallet(
  workerId: number | string,
  now: string,
): Promise<WorkerWalletRow | null> {
  return withTransaction(async (client) => {
    await ensureWorkerWalletWithClient(client, Number(workerId), now)
    return getWorkerWalletWithClient(client, Number(workerId))
  })
}

export async function getWorkerWallet(workerId: number | string): Promise<WorkerWalletRow | null> {
  const result = await query<WorkerWalletRow>(
    'SELECT * FROM worker_wallets WHERE worker_id = $1 LIMIT 1',
    [Number(workerId)],
  )
  return result.rows[0] || null
}

export async function listWorkerWalletLedgers({
  page = 1,
  pageSize = 20,
  workerId = 0,
  ledgerType = '',
}: WalletLedgerListInput = {}): Promise<{ items: WorkerWalletLedgerRow[]; total: number }> {
  const { whereClause, params } = buildWorkerWalletLedgerWhere({
    workerId,
    ledgerType,
  })
  const totalResult = await query<{ total: number }>(
    `SELECT COUNT(*)::int AS total FROM worker_wallet_ledgers wwl ${whereClause}`,
    params,
  )
  const offset = (page - 1) * pageSize
  params.push(pageSize, offset)
  const itemsResult = await query<WorkerWalletLedgerRow>(
    `
      SELECT *
      FROM worker_wallet_ledgers wwl
      ${whereClause}
      ORDER BY wwl.created_at DESC, wwl.id DESC
      LIMIT $${params.length - 1} OFFSET $${params.length}
    `,
    params,
  )
  return {
    items: itemsResult.rows,
    total: Number(totalResult.rows[0]?.total || 0),
  }
}

export async function addWorkerWalletCredit(input: {
  workerId: number
  amount: number
  note: string
  payloadJson: string
  now: string
}): Promise<WorkerWalletRow | null> {
  return withTransaction(async (client) => {
    await ensureWorkerWalletWithClient(client, input.workerId, input.now)
    const wallet = await getWorkerWalletWithClient(client, input.workerId)
    const nextAvailable = Number(wallet?.available_amount || 0) + input.amount
    const nextFrozen = Number(wallet?.frozen_deposit_amount || 0)
    await client.query(
      `
        UPDATE worker_wallets
        SET
          available_amount = $1,
          total_credited_amount = total_credited_amount + $2,
          updated_at = $3
        WHERE worker_id = $4
      `,
      [nextAvailable, input.amount, input.now, input.workerId],
    )
    await client.query(
      `
        INSERT INTO worker_wallet_ledgers (
          worker_id, ledger_type, amount, balance_after, frozen_after,
          audit_status, note, payload_json, created_at
        ) VALUES ($1, 'manual_credit', $2, $3, $4, 'approved', $5, $6::jsonb, $7)
      `,
      [
        input.workerId,
        input.amount,
        nextAvailable,
        nextFrozen,
        input.note,
        input.payloadJson,
        input.now,
      ],
    )
    return getWorkerWalletWithClient(client, input.workerId)
  })
}

export async function createWorkerFinanceRequest(input: {
  workerId: number
  requestType: string
  amount: number
  accountChannel: string
  accountName: string
  accountNo: string
  note: string
  payloadJson: string
  now: string
}): Promise<WorkerFinanceRequestRow | null> {
  const result = await query<WorkerFinanceRequestRow>(
    `
      INSERT INTO worker_finance_requests (
        worker_id, request_type, status, amount,
        account_channel, account_name, account_no,
        note, reviewed_note, payload_json, created_at, updated_at
      ) VALUES ($1, $2, 'pending', $3, $4, $5, $6, $7, '', $8::jsonb, $9, $10)
      RETURNING *
    `,
    [
      input.workerId,
      input.requestType,
      input.amount,
      input.accountChannel,
      input.accountName,
      input.accountNo,
      input.note,
      input.payloadJson,
      input.now,
      input.now,
    ],
  )
  return result.rows[0] || null
}

export async function getWorkerFinanceRequestById(
  requestId: number | string,
): Promise<WorkerFinanceRequestRow | null> {
  const result = await query<WorkerFinanceRequestRow>(
    `${WORKER_FINANCE_REQUEST_SELECT} WHERE wfr.id = $1 LIMIT 1`,
    [Number(requestId)],
  )
  return result.rows[0] || null
}

export async function countWorkerWithdrawRequestsOnDay(
  workerId: number | string,
  dayStartIso: string,
  dayEndIso: string,
): Promise<number> {
  const result = await query<{ total: number }>(
    `
      SELECT COUNT(*)::int AS total
      FROM worker_finance_requests
      WHERE worker_id = $1
        AND request_type = 'withdraw'
        AND status != 'cancelled'
        AND created_at >= $2
        AND created_at < $3
    `,
    [Number(workerId), dayStartIso, dayEndIso],
  )
  return Number(result.rows[0]?.total || 0)
}

export async function listWorkerFinanceRequests({
  page = 1,
  pageSize = 20,
  workerId = 0,
  status = '',
  requestType = '',
  keyword = '',
}: FinanceRequestListInput = {}): Promise<{ items: WorkerFinanceRequestRow[]; total: number }> {
  const { whereClause, params } = buildWorkerFinanceRequestWhere({
    workerId,
    status,
    requestType,
    keyword,
  })
  const totalResult = await query<{ total: number }>(
    `SELECT COUNT(*)::int AS total FROM worker_finance_requests wfr
     LEFT JOIN worker_users wu ON wu.id = wfr.worker_id
     ${whereClause}`,
    params,
  )
  const offset = (page - 1) * pageSize
  params.push(pageSize, offset)
  const itemsResult = await query<WorkerFinanceRequestRow>(
    `${WORKER_FINANCE_REQUEST_SELECT}
     ${whereClause}
     ORDER BY wfr.created_at DESC, wfr.id DESC
     LIMIT $${params.length - 1} OFFSET $${params.length}`,
    params,
  )
  return {
    items: itemsResult.rows,
    total: Number(totalResult.rows[0]?.total || 0),
  }
}

export async function reviewWorkerFinanceRequest(input: {
  requestId: number
  status: string
  reviewedNote: string
  now: string
}): Promise<{
  request: WorkerFinanceRequestRow | null
  failureReason: 'request_not_pending' | 'withdraw_insufficient' | null
}> {
  return withTransaction(async (client) => {
    const currentResult = await client.query<WorkerFinanceRequestRow>(
      `
        SELECT *
        FROM worker_finance_requests
        WHERE id = $1
        LIMIT 1
        FOR UPDATE
      `,
      [input.requestId],
    )
    const current = currentResult.rows[0] || null
    if (!current) {
      return {
        request: null,
        failureReason: null,
      }
    }

    if (current.status !== 'pending') {
      return {
        request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId),
        failureReason: 'request_not_pending',
      }
    }

    if (input.status === 'approved') {
      await ensureWorkerWalletWithClient(client, Number(current.worker_id), input.now)
      const wallet = await getWorkerWalletWithClient(client, Number(current.worker_id))
      const availableAmount = Number(wallet?.available_amount || 0)
      const frozenAmount = Number(wallet?.frozen_deposit_amount || 0)
      const amount = Number(current.amount || 0)
      const note =
        input.reviewedNote ||
        (current.request_type === 'withdraw' ? '提现申请审核通过' : '充值申请审核通过')

      if (current.request_type === 'withdraw') {
        if (availableAmount < amount) {
          return {
            request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId),
            failureReason: 'withdraw_insufficient',
          }
        }

        const nextAvailable = availableAmount - amount
        await client.query(
          `
            UPDATE worker_wallets
            SET available_amount = $1, updated_at = $2
            WHERE worker_id = $3
          `,
          [nextAvailable, input.now, Number(current.worker_id)],
        )
        await client.query(
          `
            INSERT INTO worker_wallet_ledgers (
              worker_id, ledger_type, amount, balance_after, frozen_after,
              audit_status, note, payload_json, created_at
            ) VALUES ($1, 'withdraw_paid', $2, $3, $4, 'approved', $5, $6::jsonb, $7)
          `,
          [
            Number(current.worker_id),
            -amount,
            nextAvailable,
            frozenAmount,
            note,
            JSON.stringify({
              requestId: Number(current.id),
              requestType: current.request_type,
              source: 'admin_finance_review',
            }),
            input.now,
          ],
        )
      } else {
        const nextAvailable = availableAmount + amount
        await client.query(
          `
            UPDATE worker_wallets
            SET
              available_amount = $1,
              total_credited_amount = total_credited_amount + $2,
              updated_at = $3
            WHERE worker_id = $4
          `,
          [nextAvailable, amount, input.now, Number(current.worker_id)],
        )
        await client.query(
          `
            INSERT INTO worker_wallet_ledgers (
              worker_id, ledger_type, amount, balance_after, frozen_after,
              audit_status, note, payload_json, created_at
            ) VALUES ($1, 'manual_credit', $2, $3, $4, 'approved', $5, $6::jsonb, $7)
          `,
          [
            Number(current.worker_id),
            amount,
            nextAvailable,
            frozenAmount,
            note,
            JSON.stringify({
              requestId: Number(current.id),
              requestType: current.request_type,
              source: 'admin_finance_review',
            }),
            input.now,
          ],
        )
      }
    }

    await client.query(
      `
        UPDATE worker_finance_requests
        SET
          status = $1,
          reviewed_note = $2,
          reviewed_at = $3,
          updated_at = $3
        WHERE id = $4
      `,
      [input.status, input.reviewedNote, input.now, input.requestId],
    )

    return {
      request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId),
      failureReason: null,
    }
  })
}

export async function getWorkerFinanceRequestSummary(workerId: number | string) {
  const result = await query<{
    pending_withdraw_amount: number
    approved_withdraw_amount: number
    pending_recharge_amount: number
  }>(
    `
      SELECT
        COALESCE(
          SUM(CASE WHEN request_type = 'withdraw' AND status = 'pending' THEN amount ELSE 0 END),
          0
        )::int AS pending_withdraw_amount,
        COALESCE(
          SUM(CASE WHEN request_type = 'withdraw' AND status = 'approved' THEN amount ELSE 0 END),
          0
        )::int AS approved_withdraw_amount,
        COALESCE(
          SUM(CASE WHEN request_type = 'recharge' AND status = 'pending' THEN amount ELSE 0 END),
          0
        )::int AS pending_recharge_amount
      FROM worker_finance_requests
      WHERE worker_id = $1
    `,
    [Number(workerId)],
  )
  return {
    pendingWithdrawAmount: Number(result.rows[0]?.pending_withdraw_amount || 0),
    approvedWithdrawAmount: Number(result.rows[0]?.approved_withdraw_amount || 0),
    pendingRechargeAmount: Number(result.rows[0]?.pending_recharge_amount || 0),
  }
}

export async function countWorkerAcceptedOrders(workerId: number | string): Promise<number> {
  const result = await query<{ total: number }>(
    `
      SELECT
        (SELECT COUNT(*)::int FROM work_orders WHERE assigned_worker_id = $1 AND status = 'accepted')
        +
        COALESCE(
          (SELECT SUM(quantity)::int FROM work_order_shares WHERE worker_id = $1 AND status = 'accepted'),
          0
        ) AS total
    `,
    [Number(workerId)],
  )
  return Number(result.rows[0]?.total || 0)
}

export async function maybeUpgradeWorkerLevelWithClient(
  client: PoolClient,
  workerId: number,
  now: string,
): Promise<WorkerUserRow | null> {
  const acceptedResult = await client.query<{ total: number }>(
    `
      SELECT
        (SELECT COUNT(*)::int FROM work_orders WHERE assigned_worker_id = $1 AND status = 'accepted')
        +
        COALESCE(
          (SELECT SUM(quantity)::int FROM work_order_shares WHERE worker_id = $1 AND status = 'accepted'),
          0
        ) AS total
    `,
    [workerId],
  )
  const acceptedCount = Number(acceptedResult.rows[0]?.total || 0)

  const nextLevelResult = await client.query<{ id: number }>(
    `
      SELECT id
      FROM worker_levels
      WHERE status = 'active'
        AND COALESCE((permission_json->>'upgradeThreshold')::int, 0) <= $1
      ORDER BY COALESCE((permission_json->>'upgradeThreshold')::int, 0) DESC, sort_order ASC
      LIMIT 1
    `,
    [acceptedCount],
  )
  const nextLevelId = Number(nextLevelResult.rows[0]?.id || 0)
  if (!nextLevelId) return null

  const current = await client.query<{ id: number; level_id: number | null }>(
    'SELECT id, level_id FROM worker_users WHERE id = $1 LIMIT 1',
    [workerId],
  )
  const currentRow = current.rows[0]
  if (!currentRow || Number(currentRow.level_id || 0) === nextLevelId) return null

  await client.query(
    'UPDATE worker_users SET level_id = $1, updated_at = $2 WHERE id = $3',
    [nextLevelId, now, workerId],
  )
  await client.query(
    `
      INSERT INTO worker_level_logs (
        worker_id, from_level_id, to_level_id, reason, payload_json, created_at
      ) VALUES ($1, $2, $3, 'auto', $4::jsonb, $5)
    `,
    [
      workerId,
      currentRow.level_id || null,
      nextLevelId,
      JSON.stringify({ acceptedCount }),
      now,
    ],
  )
  return getWorkerUserByIdWithClient(client, workerId)
}

async function getWorkerUserByIdWithClient(
  client: PoolClient,
  workerId: number | string,
): Promise<WorkerUserRow | null> {
  const result = await client.query<WorkerUserRow>(
    `${WORKER_USER_SELECT} WHERE wu.id = $1 LIMIT 1`,
    [Number(workerId)],
  )
  return result.rows[0] || null
}

async function getWorkerFinanceRequestByIdWithClient(
  client: PoolClient,
  requestId: number | string,
): Promise<WorkerFinanceRequestRow | null> {
  const result = await client.query<WorkerFinanceRequestRow>(
    `${WORKER_FINANCE_REQUEST_SELECT} WHERE wfr.id = $1 LIMIT 1`,
    [Number(requestId)],
  )
  return result.rows[0] || null
}

function buildWorkerUserWhere({
  status = '',
  keyword = '',
}: Pick<ListInput, 'status' | 'keyword'>) {
  const filters: string[] = []
  const params: unknown[] = []
  if (status) {
    params.push(status)
    filters.push(`wu.status = $${params.length}`)
  }
  if (keyword) {
    params.push(`%${keyword}%`)
    filters.push(
      `(wu.username ILIKE $${params.length} OR wu.display_name ILIKE $${params.length} OR wu.phone ILIKE $${params.length})`,
    )
  }
  return {
    whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '',
    params,
  }
}

function buildWorkerWalletLedgerWhere({
  workerId = 0,
  ledgerType = '',
}: WalletLedgerListInput) {
  const filters: string[] = []
  const params: unknown[] = []
  if (workerId) {
    params.push(workerId)
    filters.push(`wwl.worker_id = $${params.length}`)
  }
  if (ledgerType) {
    params.push(ledgerType)
    filters.push(`wwl.ledger_type = $${params.length}`)
  }
  return {
    whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '',
    params,
  }
}

function buildWorkerFinanceRequestWhere({
  workerId = 0,
  status = '',
  requestType = '',
  keyword = '',
}: FinanceRequestListInput) {
  const filters: string[] = []
  const params: unknown[] = []
  if (workerId) {
    params.push(workerId)
    filters.push(`wfr.worker_id = $${params.length}`)
  }
  if (status) {
    params.push(status)
    filters.push(`wfr.status = $${params.length}`)
  }
  if (requestType) {
    params.push(requestType)
    filters.push(`wfr.request_type = $${params.length}`)
  }
  if (keyword) {
    params.push(`%${keyword}%`)
    filters.push(
      `(wu.username ILIKE $${params.length}
        OR wu.display_name ILIKE $${params.length}
        OR wu.phone ILIKE $${params.length}
        OR wfr.account_name ILIKE $${params.length}
        OR wfr.account_no ILIKE $${params.length})`,
    )
  }
  return {
    whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '',
    params,
  }
}
