import { EntityManager } from 'typeorm'

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

export const inventoryExpiryMonitorResolver = {
  async inventoryExpiryMonitor(_: any, params: ListParam, context: any) {
    const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
    const bizplaceId: string = params.filters.find((filter: any) => filter.name === 'bizplace')?.value || 'ALL'
    const v4 = new RegExp(/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i)
    let bizplaceIds: string

    if (bizplaceId && (bizplaceId == 'ALL' || bizplaceId.match(v4))){
        let bizplaces: string[] = bizplaceId && bizplaceId != 'ALL' ? [bizplaceId] : await getPermittedBizplaceIds(domain, user)
        bizplaceIds = bizplaces.map(bizplace => {
                    return "'" + bizplace?.trim() + "'"
                  }).join(',')
    } else throw new Error('invalid bizplaceId')

    const expInventories: {
      location: string
      expired: number
      thirtyDays: number
      fortyFiveDays: number
      sixtyDays: number
    }[] = await tx.query(
      `
      SELECT "location", sum("expired") AS "expired", SUM("threeMonths") AS "threeMonths", sum("sixMonths") AS "sixMonths", sum("nineMonths") AS "nineMonths" FROM (
        SELECT 
          CASE WHEN l.TYPE IN ('QUARANTINE','RESERVE') THEN 'QUARANTINED' ELSE 'IN SHELF' END AS "location",
          CASE WHEN i.expiration_date - now()::date <= 0 THEN 1 ELSE 0 END AS "expired",
          CASE WHEN i.expiration_date - now()::date > 0 AND i.expiration_date - now()::date <= 90 THEN 1 ELSE 0 END AS "threeMonths",
          CASE WHEN i.expiration_date - now()::date > 90 AND i.expiration_date - now()::date <= 180 THEN 1 ELSE 0 END AS "sixMonths",
          CASE WHEN i.expiration_date - now()::date > 180 AND i.expiration_date - now()::date <= 270 THEN 1 ELSE 0 END AS "nineMonths"
        FROM inventories i
        INNER JOIN locations l ON i.location_id = l.id
        WHERE i.expiration_date - now()::date <= 270
        AND i.expiration_date NOTNULL
        AND i.status = 'STORED'
        AND i.domain_id = $1
        AND i.bizplace_id in (${bizplaceIds})
      ) AS foo
      GROUP BY "location"
    `,
      [domain.id]
    )

    return {
      quarantined: getExpiryCountByStatus(expInventories, 'QUARANTINED'),
      inShelf: getExpiryCountByStatus(expInventories, 'IN SHELF')
    }
  }
}

function getExpiryCountByStatus(expInventories, location) {
  let matchedInv: any = expInventories.find(inv => inv.location == location)

  if (matchedInv) return (({ location, ...inv }) => inv)(matchedInv)
  else return { expired: 0, threeMonths: 0, sixMonths: 0, nineMonths: 0 }
}
