import { datetimeToTime } from '@/utils/validate'
import { CSSProperties } from 'vue'
import { CommonData, MaybeRef } from '~/common'

interface TrackNode {
  nodeName: string
  nodeCode: string
  active: boolean
  labelWidth?: number
  descriptions: string[]
  sync?: boolean
}
interface CombinedTrackNode {
  active: boolean
  labelWidth?: number
  children: [TrackNode, TrackNode]
}
interface TrackAirport<T = TrackNode> {
  airport: string
  isDeparture: boolean
  trackSteps: T[]
}
interface TrackAirline<T = TrackNode> {
  flightNO: string
  flightDate: string
  airports: TrackAirport<T>[]
}

export function useTrackData(name: string, trackData: MaybeRef<CommonData[]>) {
  const isInternational = name.includes('International')
  const isTransfer = name.includes('Transfer')

  const computedTrackData = computed(() => {
    if (name !== 'DepartureWaybill') {
      return unref(trackData)
    }
    return unref(trackData).reduce((prevData, currentNode) => {
      if (currentNode.nodeCode === 'ACC_BUP') {
        return [
          ...prevData,
          currentNode,
          { ...currentNode, nodeCode: 'SECURITY' },
        ]
      }
      return [...prevData, currentNode]
    }, [] as CommonData[])
  })

  const trackAirlines = ref<TrackAirline<TrackNode | CombinedTrackNode>[]>([])
  const getTrackAirlines = () => {
    const airlines = unref(computedTrackData).reduce(
      (
        airlines,
        {
          flightNO,
          flightDate,
          departureAirport,
          arriveAirport,
          nodeCode,
          execPosition,
          // ConsignmentItemPackagingQuantityQuantity,
          execResult,
          execTime,
        }
      ) => {
        if (typeof nodeCode !== 'string' || nodeCode === '') {
          return airlines
        }
        const isDeparture =
          [
            ...NODE_CODE.departure,
            ...NODE_CODE.internationalDeparture,
            ...NODE_CODE.internationalDepartureTransfer,
          ].some(node => node.nodeCode === nodeCode) ||
          (name.includes('Departure') &&
            ![...NODE_CODE.arrival, ...NODE_CODE.internationalArrival].some(
              node => node.nodeCode === nodeCode
            ))
        const airport = isDeparture
          ? String(departureAirport ?? '')
          : String(arriveAirport ?? '')
        const trackNode = {
          active: Boolean(
            execPosition ||
              //   ConsignmentItemPackagingQuantityQuantity ||
              execResult ||
              execTime
          ),
          descriptions: [
            `位置：${String(execPosition ?? '--')}`,
            // String(ConsignmentItemPackagingQuantityQuantity ?? ''),
            `结果：${execResult ? '通过' : '未通过'}`,
            `时间：${datetimeToTime(execTime, flightDate)}`,
          ],
        }
        const nodeList = NODE_CODE[
          isTransfer
            ? 'internationalDepartureTransfer'
            : isDeparture
            ? isInternational
              ? 'internationalDeparture'
              : 'departure'
            : isInternational
            ? 'internationalArrival'
            : 'arrival'
        ].map(node => {
          if (node.nodeCode === nodeCode) {
            return {
              ...node,
              ...trackNode,
            }
          } else {
            return {
              ...node,
              active: false,
              descriptions: ['', '', ''],
            }
          }
        })
        const airline = airlines.find(
          airline =>
            airline.flightNO === String(flightNO ?? '') &&
            airline.flightDate === String(flightDate ?? '')
        )
        if (airline) {
          const trackAirport = airline.airports.find(
            trackAirport => trackAirport.isDeparture === isDeparture
          )
          if (trackAirport) {
            trackAirport.trackSteps = trackAirport.trackSteps.map(node => {
              if (node.nodeCode === nodeCode) {
                node = {
                  ...node,
                  ...trackNode,
                }
              }
              return node
            })
          } else {
            airline.airports.push({
              airport,
              isDeparture,
              trackSteps: nodeList,
            })
          }
        } else {
          airlines.push({
            flightNO: String(flightNO ?? ''),
            flightDate: String(flightDate ?? ''),
            airports: [
              {
                airport,
                isDeparture,
                trackSteps: nodeList,
              },
            ],
          })
        }
        return airlines
      },
      [] as TrackAirline[]
    )
    trackAirlines.value = airlines.map(airline => {
      const dealedAirports = airline.airports.map((airport, index) => ({
        ...airport,
        trackSteps: airport.trackSteps.reduce((prevSteps, node, i, steps) => {
          if (
            node.active ||
            (index > 0
              ? ['IMP_TALLY', 'FSU_DLV'].includes(node.nodeCode) &&
                steps.some(
                  node =>
                    ['IMP_TALLY', 'FSU_DLV'].includes(node.nodeCode) &&
                    node.active
                )
              : !['CARGOS_OFFLOAD', 'OFFLOAD_CONFIRM', 'BILL_RETURN'].includes(
                  node.nodeCode
                ))
          ) {
            if (node.sync && prevSteps.length > 0) {
              const lastNode = prevSteps.pop() as TrackNode | CombinedTrackNode
              if ('nodeCode' in lastNode) {
                const active = node.active || lastNode.active
                const labelWidth =
                  Math.max(node.labelWidth ?? 0, lastNode.labelWidth ?? 0) ||
                  undefined
                prevSteps.push({
                  active,
                  labelWidth,
                  children: [lastNode, node],
                })
              } else {
                prevSteps.push(lastNode, node)
              }
            } else {
              prevSteps.push(node)
            }
          }
          return prevSteps
        }, [] as (TrackNode | CombinedTrackNode)[]),
      }))
      const sortedAirports =
        name.includes('Departure') === airline.airports[0].isDeparture
          ? dealedAirports
          : dealedAirports.reverse()
      return {
        ...airline,
        airports: sortedAirports,
      }
    })
  }

  watch(computedTrackData, () => {
    getTrackAirlines()
  })

  const trackBoxStyle = computed(
    () => (
      airports: TrackAirport<TrackNode | CombinedTrackNode>[],
      index: number
    ) => {
      const style: CSSProperties = {}
      const totalLength = airports.reduce((pre, current) => {
        return pre + current.trackSteps.length - 1
      }, 0)
      style.width = totalLength
        ? `calc((100% - ${airports.length - 1} * 8px) * ${
            (airports[index].trackSteps.length - 1) / totalLength
          })`
        : '100%'
      style.minWidth = '300px'
      return style
    }
  )
  return {
    trackAirlines,
    trackBoxStyle,
  }
}
