import { string } from 'alga-js'
import refreshTokenHelper from '../../utils/refreshTokenHelper'
import errorHandlingHelper from '../../utils/errorHandlingHelper'
import fetchHelper from '../../utils/fetchHelper'

const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const query = getQuery(event)
  const role = getCookie(event, 'logship_role')

  const newUserRole = JSON.parse(role ?? '{}')
  const organizationId = getCookie(event, 'logship_organization_id')
  const orgIdParam = query?.org_id as string

  let orgFilter = ''
  if (!newUserRole?.IsClientAdministrator) {
    orgFilter = ` AND AD_Org_ID eq ${orgIdParam || organizationId}`
  } else if (orgIdParam) {
    orgFilter = ` AND AD_Org_ID eq ${orgIdParam}`
  }

  // Determine selected month/year from query params (default: current month)
  const now = new Date()
  const queryMonth = query?.month ? Number(query.month) : null // 1-12
  const queryYear = query?.year ? Number(query.year) : null

  const selectedYear = queryYear || now.getFullYear()
  const selectedMonth = queryMonth ? queryMonth - 1 : now.getMonth() // 0-indexed

  // Selected month range
  const currentMonthStart = `${selectedYear}-${String(selectedMonth + 1).padStart(2, '0')}-01 00:00:00`
  const currentMonthEnd = `${selectedYear}-${String(selectedMonth + 1).padStart(2, '0')}-${new Date(selectedYear, selectedMonth + 1, 0).getDate()} 23:59:59`

  // Previous month range (month before selected)
  const prevMonth = selectedMonth === 0 ? 11 : selectedMonth - 1
  const prevYear = selectedMonth === 0 ? selectedYear - 1 : selectedYear
  const prevMonthStart = `${prevYear}-${String(prevMonth + 1).padStart(2, '0')}-01 00:00:00`
  const prevMonthEnd = `${prevYear}-${String(prevMonth + 1).padStart(2, '0')}-${new Date(prevYear, prevMonth + 1, 0).getDate()} 23:59:59`

  // Fetch current month commissioned shipments
  const currentFilter = string.urlEncode(
    `IsCommissioned eq true AND shipping_date ge '${currentMonthStart}' AND shipping_date le '${currentMonthEnd}'${orgFilter}`
  )
  const currentRes: any = await fetchHelper(
    event,
    `models/m_inout?$filter=${currentFilter}&$select=AD_Org_ID,shipping_date`,
    'GET',
    token,
    null
  )

  // Fetch previous month commissioned shipments
  const prevFilter = string.urlEncode(
    `IsCommissioned eq true AND shipping_date ge '${prevMonthStart}' AND shipping_date le '${prevMonthEnd}'${orgFilter}`
  )
  const prevRes: any = await fetchHelper(
    event,
    `models/m_inout?$filter=${prevFilter}&$select=AD_Org_ID,shipping_date`,
    'GET',
    token,
    null
  )

  // Fetch organizations for name mapping
  const orgsRes: any = await fetchHelper(event, 'models/ad_org', 'GET', token, null)
  const orgMap: Record<number, string> = {}
  if (orgsRes?.records) {
    orgsRes.records.forEach((org: any) => {
      orgMap[org.id] = org.Name || `Org-${org.id}`
    })
  }

  // Process current month data: group by date and org
  const currentRecords = currentRes?.records || []
  const prevRecords = prevRes?.records || []

  // Get all org names from the data
  const orgSet = new Set<string>()

  const processRecords = (records: any[]) => {
    const byDateAndOrg: Record<string, Record<string, number>> = {}
    records.forEach((record: any) => {
      if (!record.shipping_date) return
      const date = new Date(record.shipping_date)
      const day = date.getDate()
      const orgId = record.AD_Org_ID?.id || record.AD_Org_ID
      const orgName = orgMap[orgId] || record.AD_Org_ID?.identifier || `Org-${orgId}`
      orgSet.add(orgName)

      if (!byDateAndOrg[day]) {
        byDateAndOrg[day] = {}
      }
      byDateAndOrg[day][orgName] = (byDateAndOrg[day][orgName] || 0) + 1
    })
    return byDateAndOrg
  }

  const currentByDay = processRecords(currentRecords)
  const prevByDay = processRecords(prevRecords)

  const daysInCurrentMonth = new Date(selectedYear, selectedMonth + 1, 0).getDate()
  const daysInPrevMonth = new Date(prevYear, prevMonth + 1, 0).getDate()
  const orgNames = Array.from(orgSet).sort()

  // Build daily chart data for overview (all orgs combined)
  const overviewData: any[] = []
  for (let d = 1; d <= daysInCurrentMonth; d++) {
    const entry: any = { day: d, current: 0, previous: 0 }
    orgNames.forEach(org => {
      entry.current += currentByDay[d]?.[org] || 0
    })
    if (d <= daysInPrevMonth) {
      orgNames.forEach(org => {
        entry.previous += prevByDay[d]?.[org] || 0
      })
    }
    overviewData.push(entry)
  }

  // Build per-org chart data
  const perOrgData: Record<string, any[]> = {}
  orgNames.forEach(org => {
    const days: any[] = []
    for (let d = 1; d <= daysInCurrentMonth; d++) {
      days.push({
        day: d,
        current: currentByDay[d]?.[org] || 0,
        previous: d <= daysInPrevMonth ? (prevByDay[d]?.[org] || 0) : 0,
      })
    }
    perOrgData[org] = days
  })

  // Summary stats
  const currentTotal = currentRecords.length
  const prevTotal = prevRecords.length
  const orgTotals: Record<string, { current: number; previous: number }> = {}
  orgNames.forEach(org => {
    orgTotals[org] = {
      current: Object.values(currentByDay).reduce((sum, dayData) => sum + (dayData[org] || 0), 0),
      previous: Object.values(prevByDay).reduce((sum, dayData) => sum + (dayData[org] || 0), 0),
    }
  })

  const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

  // Determine if selected month is the current (live) month
  const isCurrentMonth = selectedYear === now.getFullYear() && selectedMonth === now.getMonth()

  return {
    overviewData,
    perOrgData,
    orgNames,
    orgTotals,
    currentMonth: monthNames[selectedMonth],
    previousMonth: monthNames[prevMonth],
    currentYear: selectedYear,
    prevYear,
    currentTotal,
    prevTotal,
    selectedMonth: selectedMonth + 1, // 1-indexed for frontend
    selectedYear,
    isCurrentMonth,
    daysElapsed: isCurrentMonth ? now.getDate() : daysInCurrentMonth,
    daysInMonth: daysInCurrentMonth,
  }
}

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

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

  return data
})
