import { query, withTransaction } from '../db/client.js'

type FulfillmentProfileRow = {
  id: number
  profile_key: string
  name: string
  executor_key: string
  requires_claim: boolean
  auto_dispatch: boolean
  inventory_strategy: string
  config_json: string | Record<string, unknown>
  created_at: string
  updated_at: string
}

type FulfillmentProfileRequirementRow = {
  id: number
  profile_id: number
  role_key: string
  roleKey?: string
  credential_type: string
  credentialType?: string
  quantity_per_unit: number
  is_required: boolean
  config_json: string | Record<string, unknown>
  created_at: string
  updated_at: string
}

type FulfillmentProfileUpsertInput = {
  profileKey: string
  name: string
  executorKey: string
  requiresClaim?: boolean
  autoDispatch?: boolean
  inventoryStrategy?: string
  configJson?: string | Record<string, unknown>
  createdAt: string
  updatedAt: string
}

export type FulfillmentProfileRequirementInput = {
  roleKey: string
  credentialType: string
  quantityPerUnit?: number | string
  isRequired?: boolean
  configJson?: string | Record<string, unknown>
}

export async function getFulfillmentProfileByKey(
  profileKey: string,
): Promise<FulfillmentProfileRow | null> {
  const result = await query<FulfillmentProfileRow>(
    'SELECT * FROM fulfillment_profiles WHERE profile_key = $1 LIMIT 1',
    [String(profileKey || '').trim()],
  )
  return result.rows[0] || null
}

export async function upsertFulfillmentProfile(
  input: FulfillmentProfileUpsertInput,
): Promise<FulfillmentProfileRow | null> {
  const result = await query<FulfillmentProfileRow>(
    `
      INSERT INTO fulfillment_profiles (
        profile_key,
        name,
        executor_key,
        requires_claim,
        auto_dispatch,
        inventory_strategy,
        config_json,
        created_at,
        updated_at
      ) VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9)
      ON CONFLICT (profile_key) DO UPDATE
      SET
        name = EXCLUDED.name,
        executor_key = EXCLUDED.executor_key,
        requires_claim = EXCLUDED.requires_claim,
        auto_dispatch = EXCLUDED.auto_dispatch,
        inventory_strategy = EXCLUDED.inventory_strategy,
        config_json = EXCLUDED.config_json,
        updated_at = EXCLUDED.updated_at
      RETURNING *
    `,
    [
      input.profileKey,
      input.name,
      input.executorKey,
      Boolean(input.requiresClaim),
      Boolean(input.autoDispatch),
      input.inventoryStrategy || 'static_pool',
      input.configJson || '{}',
      input.createdAt,
      input.updatedAt,
    ],
  )

  return result.rows[0] || null
}

export async function replaceFulfillmentProfileRequirements(
  profileId: number | string,
  requirements: FulfillmentProfileRequirementInput[] = [],
  timestamp: string,
): Promise<void> {
  await withTransaction(async (client) => {
    await client.query('DELETE FROM fulfillment_profile_requirements WHERE profile_id = $1', [
      Number(profileId),
    ])

    for (const requirement of requirements) {
      await client.query(
        `
          INSERT INTO fulfillment_profile_requirements (
            profile_id,
            role_key,
            credential_type,
            quantity_per_unit,
            is_required,
            config_json,
            created_at,
            updated_at
          ) VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7, $8)
        `,
        [
          Number(profileId),
          requirement.roleKey,
          requirement.credentialType,
          Number(requirement.quantityPerUnit || 1),
          requirement.isRequired !== false,
          requirement.configJson || '{}',
          timestamp,
          timestamp,
        ],
      )
    }
  })
}

export async function listFulfillmentProfileRequirements(
  profileId: number | string,
): Promise<FulfillmentProfileRequirementRow[]> {
  const result = await query<FulfillmentProfileRequirementRow>(
    `
      SELECT *
      FROM fulfillment_profile_requirements
      WHERE profile_id = $1
      ORDER BY id ASC
    `,
    [Number(profileId)],
  )

  return result.rows
}
