import { query } from '../db/client.js'
import type {
  WebhookEventCreateInput,
  WebhookEventListQueryInput,
  WebhookEventUpdatePatch,
} from '../types/repository-inputs.js'
import type {
  WebhookEventListQueryResult,
  WebhookEventRow,
} from '../types/repository-rows.js'

export async function createWebhookEvent(input: WebhookEventCreateInput): Promise<WebhookEventRow | null> {
  const result = await query<WebhookEventRow>(
    `
      INSERT INTO webhook_events (
        provider,
        platform,
        shop_id,
        shop_name,
        event_type,
        event_key,
        signature_valid,
        headers_json,
        query_json,
        body_json,
        processed,
        process_error,
        related_order_id,
        created_at
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10::jsonb, $11, $12, $13, $14)
      RETURNING *
    `,
    [
      input.provider,
      input.platform,
      input.shopId || '',
      input.shopName || '',
      input.eventType,
      input.eventKey,
      Boolean(input.signatureValid),
      input.headersJson || '{}',
      input.queryJson || '{}',
      input.bodyJson || '{}',
      Boolean(input.processed),
      input.processError || '',
      input.relatedOrderId || null,
      input.createdAt,
    ],
  )

  return result.rows[0] || null
}

export async function updateWebhookEvent(
  eventId: number | string,
  patch: WebhookEventUpdatePatch,
): Promise<WebhookEventRow | null> {
  const current = await getWebhookEventById(eventId)
  if (!current) {
    return null
  }

  const next = { ...current, ...patch }
  const result = await query<WebhookEventRow>(
    `
      UPDATE webhook_events
      SET
        processed = $1,
        process_error = $2,
        related_order_id = $3
      WHERE id = $4
      RETURNING *
    `,
    [Boolean(next.processed), next.process_error || '', next.related_order_id || null, Number(eventId)],
  )

  return result.rows[0] || null
}

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

export async function listWebhookEvents({
  page = 1,
  pageSize = 20,
  provider = '',
  platform = '',
  platformOrderId = '',
  processed = '',
  visibility = 'important',
  relatedOrderId = '',
  dateFrom = '',
  dateTo = '',
}: WebhookEventListQueryInput = {}): Promise<WebhookEventListQueryResult> {
  const offset = (page - 1) * pageSize
  const filters: string[] = []
  const params: unknown[] = []

  if (provider) {
    params.push(provider)
    filters.push(`provider = $${params.length}`)
  }

  if (platform) {
    params.push(platform)
    filters.push(`platform = $${params.length}`)
  }

  if (platformOrderId) {
    params.push(`%${platformOrderId}%`)
    filters.push(`(event_key ILIKE $${params.length} OR body_json::text ILIKE $${params.length})`)
  }

  if (processed === '0' || processed === '1') {
    params.push(processed === '1')
    filters.push(`processed = $${params.length}`)
  }

  if (visibility === 'ignored') {
    filters.push(`process_error LIKE 'ignored_%'`)
  } else if (visibility === 'important') {
    filters.push(`(process_error = '' OR process_error NOT LIKE 'ignored_%')`)
  }

  if (relatedOrderId) {
    params.push(Number(relatedOrderId))
    filters.push(`related_order_id = $${params.length}`)
  }

  if (dateFrom) {
    params.push(dateFrom)
    filters.push(`created_at >= $${params.length}`)
  }

  if (dateTo) {
    params.push(dateTo)
    filters.push(`created_at <= $${params.length}`)
  }

  const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
  const totalResult = await query<{ [column: string]: unknown, total: number }>(
    `SELECT COUNT(*)::int AS total FROM webhook_events ${whereClause}`,
    params,
  )

  params.push(pageSize)
  params.push(offset)
  const itemsResult = await query<WebhookEventRow>(
    `
      SELECT *
      FROM webhook_events
      ${whereClause}
      ORDER BY id DESC
      LIMIT $${params.length - 1} OFFSET $${params.length}
    `,
    params,
  )

  return {
    items: itemsResult.rows,
    total: Number(totalResult.rows[0]?.total || 0),
  }
}

export async function listWebhookEventsByOrderId(orderId: number | string): Promise<WebhookEventRow[]> {
  const result = await query<WebhookEventRow>(
    `
      SELECT *
      FROM webhook_events
      WHERE related_order_id = $1
      ORDER BY id DESC
    `,
    [Number(orderId)],
  )

  return result.rows
}
