import { CreateInventoryLevelInput, ExecArgs } from "@medusajs/framework/types"
import { ContainerRegistrationKeys, Modules } from "@medusajs/framework/utils"
import {
  createInventoryLevelsWorkflow,
  linkSalesChannelsToStockLocationWorkflow,
} from "@medusajs/medusa/core-flows"

type StoreRecord = {
  id: string
  default_location_id?: string | null
}

type StockLocationRecord = {
  id: string
}

type InventoryItemRecord = {
  id: string
}

type InventoryLevelRecord = {
  inventory_item_id: string
}

export default async function fixSalesChannelStock({ container }: ExecArgs) {
  const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
  const query = container.resolve(ContainerRegistrationKeys.QUERY)
  const salesChannelModuleService = container.resolve(Modules.SALES_CHANNEL)

  let [defaultSalesChannel] = await salesChannelModuleService.listSalesChannels({
    name: "Default Sales Channel",
  })

  if (!defaultSalesChannel) {
    const channels = await salesChannelModuleService.listSalesChannels({}, { take: 1 })
    defaultSalesChannel = channels[0]
  }

  if (!defaultSalesChannel) {
    throw new Error("No sales channel found.")
  }

  const { data: stores } = await query.graph({
    entity: "store",
    fields: ["id", "default_location_id"],
  })

  const store = (stores?.[0] || null) as StoreRecord | null

  let stockLocationId = store?.default_location_id || null

  if (!stockLocationId) {
    const { data: stockLocations } = await query.graph({
      entity: "stock_location",
      fields: ["id"],
      pagination: { take: 1 },
    })

    stockLocationId = (stockLocations?.[0] as StockLocationRecord | undefined)?.id || null
  }

  if (!stockLocationId) {
    throw new Error("No stock location found. Create a stock location first.")
  }

  await linkSalesChannelsToStockLocationWorkflow(container).run({
    input: {
      id: stockLocationId,
      add: [defaultSalesChannel.id],
    },
  })

  logger.info(
    `Linked sales channel ${defaultSalesChannel.id} to stock location ${stockLocationId}.`
  )

  const { data: inventoryItems } = await query.graph({
    entity: "inventory_item",
    fields: ["id"],
  })

  const allItems = (inventoryItems || []) as InventoryItemRecord[]

  if (!allItems.length) {
    logger.info("No inventory items found. Nothing else to fix.")
    return
  }

  const { data: levelsAtLocation } = await query.graph({
    entity: "inventory_level",
    fields: ["inventory_item_id"],
    filters: {
      location_id: stockLocationId,
    },
  })

  const existingItemIds = new Set(
    ((levelsAtLocation || []) as InventoryLevelRecord[]).map((level) => level.inventory_item_id)
  )

  const inventoryLevels: CreateInventoryLevelInput[] = allItems
    .filter((item) => !existingItemIds.has(item.id))
    .map((item) => ({
      location_id: stockLocationId as string,
      inventory_item_id: item.id,
      stocked_quantity: 1000000,
    }))

  if (!inventoryLevels.length) {
    logger.info("All inventory items already have levels at this stock location.")
    return
  }

  await createInventoryLevelsWorkflow(container).run({
    input: {
      inventory_levels: inventoryLevels,
    },
  })

  logger.info(`Created ${inventoryLevels.length} missing inventory levels.`)
}
