import { Worksheet, WorksheetDetail, WORKSHEET_STATUS, WORKSHEET_TYPE } from '@things-factory/worksheet-base'
import { User } from '@things-factory/auth-base'
import { Domain } from '@things-factory/biz-base'
import { ReleaseGood, OrderInventory, ORDER_STATUS } from '@things-factory/sales-base'
import { EntityManager, In } from 'typeorm'

export const activateWorksheetZonePicking = {
  async activateWorksheetZonePicking(_: any, { name }, context: any): Promise<Worksheet> {
    const { user, domain, tx }: { user: User; domain: Domain; tx: EntityManager } = context.state
    const type = WORKSHEET_TYPE.ZONE_PICKING

    return activateWorksheet({ tx, user, domain, name: [name], type })
  }
}

export const activateBulkWorksheetZonePicking = {
  async activateBulkWorksheetZonePicking(_: any, { names }, context: any): Promise<Worksheet[]> {
    const { user, domain, tx }: { user: User; domain: Domain; tx: EntityManager } = context.state
    const type = WORKSHEET_TYPE.ZONE_PICKING

    return activateWorksheet({ tx, user, domain, name: names, type })
  }
}

interface WorksheetActivationParams {
  tx: EntityManager
  user: User
  domain: Domain
  name: string[]
  type: string
}
async function activateWorksheet(params: WorksheetActivationParams): Promise<Worksheet[]> {
  const { tx, user, domain, name, type } = params

  try {
    //fetch worksheet(s)
    const worksheets: Worksheet[] = await tx.getRepository(Worksheet).find({
      where: {
        domain,
        status: WORKSHEET_STATUS.DEACTIVATED,
        name: In(name),
        type
      },
      relations: [
        'worksheetDetails',
        'worksheetDetails.targetInventory',
        'worksheetDetails.targetInventory.releaseGood'
      ]
    })

    if (!worksheets || worksheets.length === 0) {
      throw new Error('Worksheet(s) not found')
    }

    const updatedWorksheets = await Promise.all(
      worksheets.map(async worksheet => {
        //update worksheet
        await tx.getRepository(Worksheet).update(
          { id: worksheet.id },
          {
            status: WORKSHEET_STATUS.EXECUTING,
            startedAt: new Date(),
            updater: user
          }
        )

        //update worksheet details
        const wsdIds = worksheet.worksheetDetails.map(item => item.id)
        await tx.getRepository(WorksheetDetail).update(
          { id: In(wsdIds) },
          {
            status: WORKSHEET_STATUS.EXECUTING,
            updater: user,
            updatedAt: new Date()
          }
        )

        //update oi
        let targetInventoryIds = worksheet.worksheetDetails.map(item => item.targetInventory.id)
        const targetInventory: OrderInventory[] = await tx.getRepository(OrderInventory).find({
          where: { id: In(targetInventoryIds) },
          relations: ['releaseGood']
        })

        const oiIds = targetInventory.map(item => item.id)
        await tx.getRepository(OrderInventory).update(
          { id: In(oiIds) },
          {
            status: ORDER_STATUS.PROCESSING,
            updater: user,
            updatedAt: new Date()
          }
        )

        //update ro
        const roIds = [...new Set(targetInventory.map(item => item.releaseGood.id))]
        await tx.getRepository(ReleaseGood).update(
          { id: In(roIds) },
          {
            status: ORDER_STATUS.PROCESSING,
            updater: user,
            updatedAt: new Date()
          }
        )

        //fetch updated worksheet
        let updatedWorksheet: Worksheet = await tx.getRepository(Worksheet).findOne({
          where: { id: worksheet.id },
          relations: [
            'worksheetDetails',
            'worksheetDetails.targetInventory',
            'worksheetDetails.targetInventory.releaseGood'
          ]
        })

        return updatedWorksheet
      })
    )

    return updatedWorksheets
  } catch (error) {
    throw error
  }
}
