import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../../utils/errorHandlingHelper"
import getTokenHelper from "../../../utils/getTokenHelper"

// Helper function to generate range
const generateRange = (from: string, to: string): string[] => {
  const range: string[] = []

  // Check if numeric range (both values are purely numeric)
  const isNumeric = /^\d+$/.test(from) && /^\d+$/.test(to)
  // Check if single letter range (both are single A-Z letters)
  const isSingleLetter = from.length === 1 && to.length === 1 &&
    /^[A-Za-z]$/.test(from) && /^[A-Za-z]$/.test(to)

  if (isNumeric) {
    // Numeric range with padding
    const fromNum = parseInt(from)
    const toNum = parseInt(to)
    const padding = Math.max(2, from.length, to.length)
    for (let i = fromNum; i <= toNum; i++) {
      range.push(String(i).padStart(padding, '0'))
    }
  } else if (isSingleLetter) {
    // Single letter alphabetic range (A-Z)
    const fromChar = from.toUpperCase().charCodeAt(0)
    const toChar = to.toUpperCase().charCodeAt(0)
    for (let i = fromChar; i <= toChar; i++) {
      range.push(String.fromCharCode(i))
    }
  } else {
    // Multi-character or mixed values - treat as static
    // If from equals to, it's a single static value
    if (from === to) {
      range.push(from)
    } else {
      // Different values - return both (no range expansion for complex patterns)
      range.push(from)
      range.push(to)
    }
  }

  return range
}

const handleFunc = async (event: any, authToken: any = null) => {
  let data: any = {
    status: 500,
    message: 'Generation failed',
    created: 0,
    skipped: 0
  }

  try {
    const token = authToken ?? await getTokenHelper(event)
    const body = await readBody(event)
    const {
      warehouseId,
      organizationId,
      xFrom,
      xTo,
      yFrom,
      yTo,
      zFrom,
      zTo,
      priorityNo = 50,
      isActive = true,
      locatorTypeId = null
    } = body

    if(!warehouseId || !organizationId) {
      return {
        status: 400,
        message: 'Warehouse ID and Organization ID are required',
        created: 0,
        skipped: 0
      }
    }

    if(!xFrom || !xTo || !yFrom || !yTo || !zFrom || !zTo) {
      return {
        status: 400,
        message: 'All range fields (X, Y, Z) are required',
        created: 0,
        skipped: 0
      }
    }

    // Generate ranges
    const xRange = generateRange(xFrom, xTo)
    const yRange = generateRange(yFrom, yTo)
    const zRange = generateRange(zFrom, zTo)

    // Get existing locators
    const existingRes: any = await event.context.fetch(
      `models/m_locator?$filter=M_Warehouse_ID eq ${warehouseId}`,
      'GET',
      token,
      null
    )

    const existingCoords = new Set()
    if(existingRes?.records) {
      existingRes.records.forEach((loc: any) => {
        const coordKey = `${loc.X}|${loc.Y}|${loc.Z}`
        existingCoords.add(coordKey)
      })
    }

    let created = 0
    let skipped = 0

    // Generate all combinations
    for(const x of xRange) {
      for(const y of yRange) {
        for(const z of zRange) {
          const coordKey = `${x}|${y}|${z}`

          // Skip if already exists
          if(existingCoords.has(coordKey)) {
            skipped++
            continue
          }

          // Create locator
          const value = `${x}-${y}-${z}`
          const createPayload: any = {
            M_Warehouse_ID: { id: warehouseId, tableName: 'M_Warehouse' },
            AD_Org_ID: { id: organizationId, tableName: 'AD_Org' },
            X: x,
            Y: y,
            Z: z,
            Value: value,
            PriorityNo: priorityNo,
            IsActive: isActive,
            IsDefault: false,
            tableName: 'M_Locator'
          }

          // Add locator type if specified
          if (locatorTypeId) {
            createPayload.M_LocatorType_ID = { id: locatorTypeId, tableName: 'M_LocatorType' }
          }

          const createRes: any = await event.context.fetch(
            'models/m_locator',
            'POST',
            token,
            createPayload
          )

          if(createRes?.id) {
            created++
            existingCoords.add(coordKey)
          } else {
            skipped++
          }
        }
      }
    }

    data = {
      status: 200,
      message: `Successfully generated ${created} locators, ${skipped} skipped`,
      created,
      skipped,
      totalCombinations: xRange.length * yRange.length * zRange.length
    }
  } catch(err: any) {
    data = {
      status: err?.status || 500,
      message: err?.message || 'Error generating locators',
      created: 0,
      skipped: 0
    }
  }

  return data
}

export default defineEventHandler(async (event) => {
  let data: any = {}

  try {
    data = await handleFunc(event)
  } catch(err: any) {
    try {
      let authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch(error) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      forceLogoutHelper(event, data)
    }
  }

  return data
})
