import { query, withTransaction } from '../../db/client.js'
import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js'
import type { WalletLedgerListInput, WorkerWalletLedgerRow, WorkerWalletRow } from './types.js'

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 wwl.*, wo.platform_order_id AS related_platform_order_id
     FROM worker_wallet_ledgers wwl
     LEFT JOIN work_orders wo ON wo.id = wwl.related_work_order_id
     ${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)
  })
}

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 }
}
