import { EntityManager } from 'typeorm'

import { Bizplace } from '@things-factory/biz-base'
import {
  Domain,
  ListParam
} from '@things-factory/shell'

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

export const analysisPickingPackingReport = {
  async analysisPickingPackingReport(_: any, params: ListParam, context: any) {
    try {
      const { tx, domain }: { tx: EntityManager; domain: Domain } = context.state
      let bizplace = params.filters.find((data: { name: string }) => data.name === 'bizplace')
      let fromDate = params.filters.find((data: { name: string }) => data.name == 'fromDate')
      let toDate = params.filters.find((data: { name: string }) => data.name == 'toDate')
      let name = params.filters.find((data: { name: string }) => data.name === 'name')
      let rate = params.filters.find((data: { name: string }) => data.name === 'rate')
      let type = params.filters.find((data: any) => data.name === 'type')

      // throw error bizplace filter missing
      if (!bizplace) throw 'Invalid input'

      let queryFilter = ''
      if (name) {
        let nameValue = name.value
          .toLowerCase()
          .split(',')
          .map((prod: string) => {
            return "'%" + prod.trim().replace(/'/g, "''") + "%'"
          })
          .join(',')
        queryFilter += `AND (
          Lower(u.name) LIKE ANY(ARRAY[${nameValue}])
        )`
      }

      let sortingTypes = ''
      if(type){
        let typeValue = type.value
        if(typeValue === 'packing' || typeValue === 'picking'){
          sortingTypes = `AND ih.transaction_type = '${typeValue.toUpperCase()}'` 
        }
      }

      let sortingOptions = ''
      if(rate) {
        let rateValue = rate.value
        if (rateValue === 'asc' || rateValue === 'desc') {
          sortingOptions = `ORDER BY packing_rates."packingRate" ${rateValue.toUpperCase()}`
        }
      }

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

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

      await rawProductsQuery(tx, params, bizplaceObj)

      const fromDateValue = new Date(fromDate.value)
      const toDateValue = new Date(toDate.value)

      // Check if the date objects are valid
      if (isNaN(fromDateValue.getTime()) || isNaN(toDateValue.getTime())) {
        throw new Error('Invalid date format. Please provide valid date values.')
      }

      const sqlQuery = `
      WITH packing_rates AS (
        SELECT
            u.name,
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 7 THEN 1 ELSE 0 END) AS "7",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 8 THEN 1 ELSE 0 END) AS "8",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 9 THEN 1 ELSE 0 END) AS "9",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 10 THEN 1 ELSE 0 END) AS "10",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 11 THEN 1 ELSE 0 END) AS "11",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 12 THEN 1 ELSE 0 END) AS "12",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 13 THEN 1 ELSE 0 END) AS "13",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 14 THEN 1 ELSE 0 END) AS "14",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 15 THEN 1 ELSE 0 END) AS "15",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 16 THEN 1 ELSE 0 END) AS "16",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 17 THEN 1 ELSE 0 END) AS "17",
            SUM(CASE WHEN EXTRACT(HOUR FROM (ih.created_at + INTERVAL '8 HOUR')) = 18 THEN 1 ELSE 0 END) AS "18",
            COUNT(DISTINCT DATE(ih.created_at)) AS "totalDaysWorked",
            COUNT(DISTINCT DATE_TRUNC('hour', (ih.created_at + INTERVAL '8 HOUR'))) AS "totalHoursWorked",
            COUNT(*) AS "totalPacks",
            ROUND(COUNT(*) / COUNT(DISTINCT DATE_TRUNC('hour', (ih.created_at + INTERVAL '8 HOUR')))) AS "packingRate"
        FROM
            inventory_histories ih
        INNER JOIN
            users u ON ih.creator_id = u.id
        WHERE
            ih.domain_id = $1
            AND ih.created_at BETWEEN $2 AND $3
            ${queryFilter}
            ${sortingTypes}
        GROUP BY 
            u.name
    )
    SELECT
        "name",
        "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18",
        packing_rates."totalDaysWorked",
        "totalPacks",
        packing_rates."totalHoursWorked",
        packing_rates."packingRate"
    FROM
        packing_rates  
        ${sortingOptions}
    `
    
    const result = await tx.query(sqlQuery, [domain.id, fromDate.value, toDate.value])
      return {
        items: result.map((data: { [x: string]: any }) => {
          return {
            ...data,
            name: data.name,
            hourlyData: JSON.stringify({
              7: data["7"],
              8: data["8"],
              9: data["9"],
              10: data["10"],
              11: data["11"],
              12: data["12"],
              13: data["13"],
              14: data["14"],
              15: data["15"],
              16: data["16"],
              17: data["17"],
              18: data["18"],
            })
          }
        }),
        total: result.length
      }

    } catch (error) {
      throw error
    }
  }
}
