import { EntityManager } from 'typeorm'

import { User } from '@things-factory/auth-base'
import { Bizplace } from '@things-factory/biz-base'
import { ListParam } from '@things-factory/shell'

import { rawProductsQuery } from '../../../utils'

export const releaseInventoryReport = {
  async releaseInventoryReport(_: any, params: ListParam, context: any) {
    try {
      const { tx }: { tx: EntityManager } = context.state
      // let bizplaceFilter = { name: '', operator: '', value: '' }
      // let userFilter = params.filters.find(data => data.name === 'user')
      let order = params.filters.find(data => data.name === 'order')
      let orderDate = params.filters.find(data => data.name === 'orderDate')
      let product = params.filters.find(data => data.name === 'product')
      let bizplace = params.filters.find(data => data.name === 'bizplace')
      let palletId = params.filters.find(data => data.name === 'palletId')
      let cartonId = params.filters.find(data => data.name === 'cartonId')

      // if (userFilter) {
      //   const user: User = await tx.getRepository(User).findOne({
      //     where: { id: userFilter.value },
      //     relations: ['bizplaces']
      //   })

      //   const bizplace: Bizplace = user.bizplaces[0]

      if (!bizplace) throw 'Invalid input'

      //   bizplaceFilter = { name: 'bizplace', operator: 'eq', value: bizplace.id }
      // } else {
      //   bizplaceFilter = params.filters.find(data => data.name === 'bizplace')
      // }

      // if (!bizplaceFilter) throw 'Invalid input'
      let roFilter = '',
        ccFilter = '',
        queryFilter = ''
      if (order) {
        let orderValue = order.value
          .toLowerCase()
          .split(',')
          .map(prod => {
            return "'%" + prod.trim().replace(/'/g, "''") + "%'"
          })
          .join(',')
        roFilter += `AND (
          Lower(od.name) LIKE ANY(ARRAY[${orderValue}])
          OR Lower(od.ref_no) LIKE ANY(ARRAY[${orderValue}])
          OR Lower(od.ref_no_2) LIKE ANY(ARRAY[${orderValue}])
          OR Lower(od.ref_no_3) LIKE ANY(ARRAY[${orderValue}])
        )`
        ccFilter += `AND (
          Lower(od.name) LIKE ANY(ARRAY[${orderValue}])
        )`
      }
      if (orderDate) {
        queryFilter += ` AND od.created_at between '${orderDate.value}'::timestamp and '${orderDate.value}'::timestamp + INTERVAL '1 day'`
      }

      if (palletId) {
        queryFilter += ` AND lower(i.pallet_id) like '%${palletId.value.toLowerCase()}%'`
      }

      if (cartonId) {
        queryFilter += ` AND lower(i.carton_id) like '%${cartonId.value.toLowerCase()}%'`
      }

      if (bizplace) {
        queryFilter += ` AND od.bizplace_id = '${bizplace.value}'`
      }

      const bizplaceObj: Bizplace = await tx.getRepository(Bizplace).findOne({
        id: bizplace.value
      })
      await rawProductsQuery(tx, params, bizplaceObj)

      // let productQuery = ''
      // if (product) {
      //   let productValue = product.value
      //     .toLowerCase()
      //     .split(',')
      //     .map(prod => {
      //       return "'%" + prod.trim().replace(/'/g, "''") + "%'"
      //     })
      //     .join(',')
      //   queryFilter = `AND (
      //     Lower(p.name) LIKE ANY(ARRAY[${productValue}])
      //     OR Lower(p.sku) LIKE ANY(ARRAY[${productValue}])
      //     OR Lower(p.description) LIKE ANY(ARRAY[${productValue}])
      //     OR Lower(p.brand_sku) LIKE ANY(ARRAY[${productValue}])
      //     OR Lower(p.brand) LIKE ANY(ARRAY[${productValue}])
      //   )`
      // }

      await tx.query(
        `
        create temp table data_src on commit drop as (
          select * from (
            select p.sku as product_sku, p.name as product_name, p.description as product_description, p.brand as product_brand, 
            b.id as bizplace_id, b.name as bizplace_name, b.description as bizplace_description, i.packing_type,
            oi.release_qty as assigned_qty, oi.release_uom_value as uom_value, i.uom,
            od.name as order_no, od.type::varchar as "type", od.status, od.created_at as order_at, od.release_date,
            i.pallet_id, i.carton_id, i.batch_id, i.batch_id_ref, i.expiration_date, i.manufacture_date, l.name as location_name
            from (
              select inventory_id, release_good_id, sum(release_qty) as release_qty, sum(release_uom_value) as release_uom_value from order_inventories oi
              inner join release_goods od on od.id = oi.release_good_id  
              where release_good_id is not null
              and od.status in ('PENDING', 'PENDING_RECEIVE', 'PENDING_CANCEL', 'PENDING_WORKSHEET', 'READY_TO_PICK', 'PICKING')
              and od.domain_id = $1
              and oi.status not in ('REPLACED', 'MISSING')
              group by inventory_id, release_good_id
            ) oi 
            inner join release_goods od on od.id = oi.release_good_id  
            inner join bizplaces b on b.id = od.bizplace_id
            inner join inventories i on i.id = oi.inventory_id 
            inner join locations l on l.id = i.location_id  
            inner join temp_products p on p.id = i.product_id
            where 1 = 1
            ${roFilter}
            ${queryFilter}
            union all
            select p.sku as product_sku, p.name as product_name, p.description as product_description, p.brand as product_brand, 
            b.id as bizplace_id, b.name as bizplace_name, b.description as bizplace_description, i.packing_type,
            oi.release_qty as assigned_qty, oi.release_uom_value as uom_value, i.uom,
            od.name as order_no, 'cc' as "type", od.status, od.created_at as order_at, od.execution_date,
            i.pallet_id, i.carton_id, i.batch_id, i.batch_id_ref, i.expiration_date, i.manufacture_date, l.name as location_name
            from order_inventories oi 
            inner join bizplaces b on b.id = oi.bizplace_id
            inner join inventory_checks od on od.id = oi.inventory_check_id
            inner join inventories i on i.id = oi.inventory_id 
            inner join locations l on l.id = i.location_id  
            inner join temp_products p on p.id = i.product_id
            where od.status <> 'DONE'
            and od.domain_id = $1
            ${ccFilter}
            ${queryFilter}
          ) src
          order by product_sku, packing_type, order_no 
        );
        `,
        [context.state.domain.id]
      )

      const total: any = await tx.query(`
        select count(*) from data_src
      `)

      const result: any = await tx.query(
        `
        select * from data_src
        offset $1 limit $2
      `,
        [(params.pagination.page - 1) * params.pagination.limit, params.pagination.limit]
      )

      let items = result.map(itm => {
        let data = {
          bizplace: {
            id: itm.bizplace_id,
            name: itm.bizplace_name,
            description: itm.bizplace_description
          },
          product: {
            id: itm.product_id,
            sku: itm.product_sku,
            name: itm.product_name,
            description: itm.product_description,
            brand: itm.product_brand
          },
          location: {
            name: itm.location_name
          },
          packingType: itm.packing_type,
          assignedQty: itm.assigned_qty,
          assignedUomValue: itm.uom_value,
          assignedUom: itm.uom,
          orderNo: itm.order_no,
          type: itm.type,
          status: itm.status,
          orderAt: itm.order_at,
          releaseDate: itm.release_date,
          palletId: itm.pallet_id,
          cartonId: itm.carton_id,
          batchId: itm.batch_id,
          batchIdRef: itm.batch_id_ref,
          expirationDate: itm.expiration_date,
          manufactureDate: itm.manufacture_date
        }

        return data
      })

      return {
        items,
        total: total[0].count
      }
    } catch (error) {
      throw error
    }
  }
}
