<template>
  <Section variant="plain">
    <Stack gap="8">
      <template v-if="hasOrderError">
        <div class="text-sm text-error">
          {{ orderError }}
        </div>
        <Button @click="loadOrder">{{ t('ordersDetail.errors.retry') }}</Button>
      </template>

      <div v-else-if="isLoadingOrder" class="text-sm text-base-content/60">
        {{ t('ordersDetail.states.loading') }}
      </div>

      <template v-else>
        <Card padding="lg" class="border border-base-300">
          <RouteSummaryHeader :title="orderTitle" :meta="orderMeta" />
        </Card>

        <Card v-if="orderRoutesForMap.length" padding="lg" class="border border-base-300">
          <Stack gap="4">
            <RouteStagesList
              :stages="orderStageItems"
              :empty-text="t('ordersDetail.sections.stages.empty')"
            />

            <div class="divider my-0"></div>

            <RequestRoutesMap :routes="orderRoutesForMap" :height="260" />
          </Stack>
        </Card>

        <div class="space-y-3">
          <Heading :level="3" weight="semibold">{{ t('ordersDetail.sections.timeline.title') }}</Heading>
          <GanttTimeline
            v-if="order?.stages"
            :stages="order.stages"
            :showLoading="showLoading"
            :showUnloading="showUnloading"
          />
          <Text v-else tone="muted">{{ t('ordersDetail.sections.timeline.empty') }}</Text>
        </div>
      </template>
    </Stack>
  </Section>
</template>

<script setup lang="ts">
import { GetOrderDocument } from '~/composables/graphql/team/orders-generated'
import type { RouteStageItem } from '~/components/RouteStagesList.vue'

definePageMeta({
  layout: 'topnav',
  middleware: ['auth-oidc']
})

const route = useRoute()
const { t } = useI18n()

const order = ref<any>(null)
const isLoadingOrder = ref(true)
const hasOrderError = ref(false)
const orderError = ref('')
const showLoading = ref(true)
const showUnloading = ref(true)

const orderTitle = computed(() => {
  const source = order.value?.sourceLocationName || t('ordersDetail.labels.source_unknown')
  const destination = order.value?.destinationLocationName || t('ordersDetail.labels.destination_unknown')
  return `${source} → ${destination}`
})

const orderMeta = computed(() => {
  const meta: string[] = []
  const orderName = order.value?.name || (route.params.id as string)
  if (orderName) meta.push(`#${orderName}`)

  const line = order.value?.orderLines?.[0]
  if (line?.quantity) {
    meta.push(`${line.quantity} ${line.unit || t('ordersDetail.labels.unit_tons')}`)
  }
  if (line?.productName) {
    meta.push(line.productName)
  }
  if (order.value?.totalAmount) {
    meta.push(formatPrice(order.value.totalAmount, order.value?.currency))
  }

  const durationDays = getOrderDuration()
  if (durationDays) {
    meta.push(`${durationDays} ${t('ordersDetail.labels.delivery_days')}`)
  }

  return meta
})

const orderRoutesForMap = computed(() => {
  const stages = (order.value?.stages || [])
    .filter(Boolean)
    .map((stage: any) => {
      if (stage.stageType === 'transport') {
        if (!stage.sourceLatitude || !stage.sourceLongitude || !stage.destinationLatitude || !stage.destinationLongitude) return null
        return {
          fromLat: stage.sourceLatitude,
          fromLon: stage.sourceLongitude,
          fromName: stage.sourceLocationName,
          toLat: stage.destinationLatitude,
          toLon: stage.destinationLongitude,
          toName: stage.destinationLocationName,
          transportType: stage.transportType
        }
      }
      return null
    })
    .filter(Boolean)

  if (!stages.length) return []
  return [{ stages }]
})

const orderStageItems = computed<RouteStageItem[]>(() => {
  return (order.value?.stages || []).map((stage: any) => {
    const isTransport = stage.stageType === 'transport'
    const from = isTransport ? stage.sourceLocationName : stage.locationName
    const to = isTransport ? stage.destinationLocationName : stage.locationName

    const meta: string[] = []
    const dateRange = getStageDateRange(stage)
    if (dateRange) {
      meta.push(dateRange)
    }

    const companies = getCompaniesSummary(stage)
    companies.forEach((company: any) => {
      meta.push(
        `${company.name} · ${company.totalWeight || 0}${t('ordersDetail.labels.weight_unit')} · ${company.tripsCount || 0} ${t('ordersDetail.labels.trips')}`
      )
    })

    return {
      key: stage.uuid,
      from,
      to,
      label: stage.name,
      meta
    }
  })
})

const loadOrder = async () => {
  try {
    isLoadingOrder.value = true
    hasOrderError.value = false
    const orderUuid = route.params.id as string
    const { data, error: orderErrorResp } = await useServerQuery('order-detail', GetOrderDocument, { orderUuid }, 'team', 'orders')
    if (orderErrorResp.value) throw orderErrorResp.value
    order.value = data.value?.getOrder
  } catch (err: any) {
    hasOrderError.value = true
    orderError.value = err.message || t('ordersDetail.errors.load_failed')
  } finally {
    isLoadingOrder.value = false
  }
}

const formatPrice = (price: number, currency?: string | null) => {
  if (!price) return t('ordersDetail.labels.price_zero')
  return new Intl.NumberFormat('ru-RU', {
    style: 'currency',
    currency: currency || 'RUB',
    minimumFractionDigits: 0
  }).format(price)
}

const getCompaniesSummary = (stage: any) => {
  const companies = []
  if (stage.stageType === 'service' && stage.selectedCompany) {
    companies.push({
      name: stage.selectedCompany.name,
      totalWeight: 0,
      tripsCount: 0,
      company: stage.selectedCompany
    })
    return companies
  }

  if (stage.stageType === 'transport' && stage.trips?.length) {
    const companiesMap = new Map()
    stage.trips.forEach((trip: any) => {
      const companyName = trip.company?.name || t('ordersDetail.labels.company_unknown')
      const weight = trip.plannedWeight || 0
      if (companiesMap.has(companyName)) {
        const existing = companiesMap.get(companyName)
        existing.totalWeight += weight
        existing.tripsCount += 1
      } else {
        companiesMap.set(companyName, {
          name: companyName,
          totalWeight: weight,
          tripsCount: 1,
          company: trip.company
        })
      }
    })
    return Array.from(companiesMap.values())
  }
  return []
}

const getOrderDuration = () => {
  if (!order.value?.stages?.length) return 0
  let minDate: Date | null = null
  let maxDate: Date | null = null
  order.value.stages.forEach((stage: any) => {
    stage.trips?.forEach((trip: any) => {
      const startDate = new Date(trip.plannedLoadingDate || trip.actualLoadingDate)
      const endDate = new Date(trip.plannedUnloadingDate || trip.actualUnloadingDate)
      if (!minDate || startDate < minDate) minDate = startDate
      if (!maxDate || endDate > maxDate) maxDate = endDate
    })
  })
  if (!minDate || !maxDate) return 0
  const diffTime = Math.abs((maxDate as Date).getTime() - (minDate as Date).getTime())
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24))
}

const getStageDateRange = (stage: any) => {
  if (!stage.trips?.length) return t('ordersDetail.labels.dates_undefined')
  let minDate: Date | null = null
  let maxDate: Date | null = null
  stage.trips.forEach((trip: any) => {
    const startDate = new Date(trip.plannedLoadingDate || trip.actualLoadingDate)
    const endDate = new Date(trip.plannedUnloadingDate || trip.actualUnloadingDate)
    if (!minDate || startDate < minDate) minDate = startDate
    if (!maxDate || endDate > maxDate) maxDate = endDate
  })
  if (!minDate || !maxDate) return t('ordersDetail.labels.dates_undefined')
  const formatDate = (date: Date) => date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' })
  if ((minDate as Date).toDateString() === (maxDate as Date).toDateString()) return formatDate(minDate as Date)
  return `${formatDate(minDate as Date)} - ${formatDate(maxDate as Date)}`
}

await loadOrder()
</script>
