import { query } from '../../db/client.js'
import type { WorkProductMatchLogRow, WorkProductRuleMappingRow } from './types.js'

const MAPPING_SELECT = `
  SELECT
    wprm.*,
    wpr.rule_key,
    wpr.product_name
  FROM work_product_rule_mappings wprm
  INNER JOIN work_product_rules wpr ON wpr.id = wprm.rule_id
`

export async function listWorkProductRuleMappings(
  input: {
    enabled?: boolean | null
    sellerId?: string
    ruleId?: number | string | null
  } = {},
): Promise<WorkProductRuleMappingRow[]> {
  const conditions: string[] = []
  const params: unknown[] = []
  if (input.enabled !== undefined && input.enabled !== null) {
    params.push(input.enabled)
    conditions.push(`wprm.enabled = $${params.length}`)
  }
  const sellerId = String(input.sellerId || '')
    .trim()
    .toLowerCase()
  if (sellerId) {
    params.push(sellerId)
    conditions.push(`wprm.seller_ids_json ? $${params.length}`)
  }
  const ruleId = Number(input.ruleId)
  if (Number.isInteger(ruleId) && ruleId > 0) {
    params.push(ruleId)
    conditions.push(`wprm.rule_id = $${params.length}`)
  }
  const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''
  const result = await query<WorkProductRuleMappingRow>(
    `${MAPPING_SELECT}
     ${where}
     ORDER BY wprm.seller_ids_json::text ASC, wprm.rel_item_id ASC, wprm.item_title ASC,
       CASE WHEN wprm.mapping_type = 'product_default' THEN 0 ELSE 1 END ASC,
       wprm.id ASC`,
    params,
  )
  return result.rows
}

export async function listWorkProductRuleMappingsPage(
  input: {
    page?: number
    pageSize?: number
    enabled?: boolean | null
    keyword?: string
    ruleId?: number | string | null
  } = {},
): Promise<{ items: WorkProductRuleMappingRow[]; total: number }> {
  const page = Math.max(1, Math.floor(Number(input.page) || 1))
  const pageSize = Math.min(100, Math.max(1, Math.floor(Number(input.pageSize) || 20)))
  const conditions: string[] = []
  const params: unknown[] = []
  if (input.enabled !== undefined && input.enabled !== null) {
    params.push(input.enabled)
    conditions.push(`wprm.enabled = $${params.length}`)
  }
  const ruleId = Number(input.ruleId)
  if (Number.isInteger(ruleId) && ruleId > 0) {
    params.push(ruleId)
    conditions.push(`wprm.rule_id = $${params.length}`)
  }
  const keyword = String(input.keyword || '').trim()
  if (keyword) {
    params.push(`%${keyword}%`)
    const parameter = `$${params.length}`
    conditions.push(`(
      wpr.rule_key ILIKE ${parameter}
      OR wpr.product_name ILIKE ${parameter}
      OR wprm.item_title ILIKE ${parameter}
      OR wprm.rel_item_id ILIKE ${parameter}
      OR wprm.rel_sku_id ILIKE ${parameter}
      OR wprm.sku_nick ILIKE ${parameter}
    )`)
  }
  const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''
  const totalResult = await query<{ total: number }>(
    `SELECT COUNT(*)::int AS total FROM work_product_rule_mappings wprm
     INNER JOIN work_product_rules wpr ON wpr.id = wprm.rule_id ${where}`,
    params,
  )
  const offset = (page - 1) * pageSize
  const listParams = [...params, pageSize, offset]
  const result = await query<WorkProductRuleMappingRow>(
    `${MAPPING_SELECT}
     ${where}
     ORDER BY wprm.seller_ids_json::text ASC, wprm.rel_item_id ASC, wprm.item_title ASC,
       CASE WHEN wprm.mapping_type = 'product_default' THEN 0 ELSE 1 END ASC,
       wprm.id ASC
     LIMIT $${listParams.length - 1} OFFSET $${listParams.length}`,
    listParams,
  )
  return { items: result.rows, total: Number(totalResult.rows[0]?.total || 0) }
}

export async function upsertWorkProductRuleMapping(input: {
  mappingId?: number | null
  ruleId: number
  sellerIds: string[]
  relItemId: string
  itemTitle: string
  relSkuId: string
  skuNick: string
  skuMatchMode: 'fuzzy' | 'exact'
  mappingType: 'product_default' | 'sku_exact' | 'sku_series'
  enabled: boolean
  now: string
}): Promise<WorkProductRuleMappingRow | null> {
  if (input.mappingId) {
    const result = await query<WorkProductRuleMappingRow>(
      `
        UPDATE work_product_rule_mappings
        SET
          rule_id = $2,
          seller_ids_json = $3::jsonb,
          rel_item_id = $4,
          item_title = $5,
          rel_sku_id = $6,
          sku_nick = $7,
          sku_match_mode = $8,
          mapping_type = $9,
          enabled = $10,
          updated_at = $11
        WHERE id = $1
        RETURNING *
      `,
      [
        input.mappingId,
        input.ruleId,
        JSON.stringify(input.sellerIds),
        input.relItemId,
        input.itemTitle,
        input.relSkuId,
        input.skuNick,
        input.skuMatchMode,
        input.mappingType,
        input.enabled,
        input.now,
      ],
    )
    return result.rows[0] || null
  }

  const result = await query<WorkProductRuleMappingRow>(
    `
      INSERT INTO work_product_rule_mappings (
        rule_id, seller_ids_json, rel_item_id, item_title, rel_sku_id, sku_nick,
        sku_match_mode, mapping_type, enabled, created_at, updated_at
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $10)
      RETURNING *
    `,
    [
      input.ruleId,
      JSON.stringify(input.sellerIds),
      input.relItemId,
      input.itemTitle,
      input.relSkuId,
      input.skuNick,
      input.skuMatchMode,
      input.mappingType,
      input.enabled,
      input.now,
    ],
  )
  return result.rows[0] || null
}

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

export async function createWorkProductMatchLog(input: {
  orderId?: number | null
  orderItemId?: number | null
  source: string
  sellerId: string
  relItemId: string
  itemTitle: string
  relSkuId: string
  skuNick: string
  matchStatus: 'matched' | 'unmatched' | 'ambiguous'
  ruleId?: number | null
  mappingId?: number | null
  candidatesJson: string
  rawPayloadJson: string
  now: string
}): Promise<WorkProductMatchLogRow | null> {
  const result = await query<WorkProductMatchLogRow>(
    `
      INSERT INTO work_product_match_logs (
        order_id, order_item_id, source, seller_id, rel_item_id, item_title,
        rel_sku_id, sku_nick, match_status, rule_id, mapping_id,
        candidates_json, raw_payload_json, created_at
      ) VALUES (
        $1, $2, $3, $4, $5, $6,
        $7, $8, $9, $10, $11,
        $12::jsonb, $13::jsonb, $14
      )
      RETURNING *
    `,
    [
      input.orderId || null,
      input.orderItemId || null,
      input.source,
      input.sellerId,
      input.relItemId,
      input.itemTitle,
      input.relSkuId,
      input.skuNick,
      input.matchStatus,
      input.ruleId || null,
      input.mappingId || null,
      input.candidatesJson,
      input.rawPayloadJson,
      input.now,
    ],
  )
  return result.rows[0] || null
}

/** 匹配日志分页查询：表本身全量保留，可按结果状态、关键词（商品/SKU/店铺）与日期范围筛选。 */
export async function listWorkProductMatchLogs({
  page = 1,
  pageSize = 20,
  matchStatus = '',
  keyword = '',
  createdFrom = '',
  createdTo = '',
}: {
  page?: number
  pageSize?: number
  matchStatus?: string
  keyword?: string
  createdFrom?: string
  createdTo?: string
} = {}): Promise<{ items: WorkProductMatchLogRow[]; total: number }> {
  const conditions: string[] = []
  const params: unknown[] = []
  const status = String(matchStatus || '').trim()
  if (status) {
    params.push(status)
    conditions.push(`wpml.match_status = $${params.length}`)
  }
  const normalizedKeyword = String(keyword || '').trim()
  if (normalizedKeyword) {
    params.push(`%${normalizedKeyword}%`)
    conditions.push(
      `(wpml.item_title ILIKE $${params.length} OR wpml.rel_item_id ILIKE $${params.length} OR wpml.rel_sku_id ILIKE $${params.length} OR wpml.sku_nick ILIKE $${params.length} OR wpml.seller_id ILIKE $${params.length})`,
    )
  }
  if (createdFrom) {
    params.push(createdFrom)
    conditions.push(
      `wpml.created_at >= ($${params.length}::date)::timestamp AT TIME ZONE 'Asia/Shanghai'`,
    )
  }
  if (createdTo) {
    params.push(createdTo)
    conditions.push(
      `wpml.created_at < (($${params.length}::date + 1)::timestamp AT TIME ZONE 'Asia/Shanghai')`,
    )
  }
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''

  const totalResult = await query<{ total: number }>(
    `SELECT COUNT(*)::int AS total FROM work_product_match_logs wpml ${whereClause}`,
    params,
  )
  params.push(pageSize, (page - 1) * pageSize)
  const result = await query<WorkProductMatchLogRow>(
    `
      SELECT wpml.*, wpr.rule_key, wpr.product_name
      FROM work_product_match_logs wpml
      LEFT JOIN work_product_rules wpr ON wpr.id = wpml.rule_id
      ${whereClause}
      ORDER BY wpml.created_at DESC, wpml.id DESC
      LIMIT $${params.length - 1} OFFSET $${params.length}
    `,
    params,
  )
  return { items: result.rows, total: Number(totalResult.rows[0]?.total || 0) }
}
