<template>
  <div>
    <CatalogPage
      :items="mapPoints"
      :loading="isLoadingOrder"
      :use-server-clustering="false"
      map-id="order-detail-map"
      point-color="#6366f1"
      :show-panel="false"
      :hide-view-toggle="true"
    />

    <!-- Bottom Sheet with slide-up animation -->
    <Transition name="slide-up" appear>
      <div class="fixed inset-x-0 bottom-0 z-50 flex flex-col" style="height: 70vh">
      <!-- Glass sheet -->
      <div class="relative flex-1 bg-black/40 backdrop-blur-xl rounded-t-2xl border-t border-white/20 shadow-2xl overflow-hidden">
        <!-- Drag handle -->
        <div class="flex justify-center py-2">
          <div class="w-12 h-1.5 bg-white/30 rounded-full" />
        </div>

        <!-- Header -->
        <div class="px-6 pb-4 border-b border-white/10">
          <!-- Back button -->
          <NuxtLink :to="localePath('/clientarea/orders')" class="inline-flex items-center gap-1 text-white/60 hover:text-white text-sm mb-3">
            <Icon name="lucide:arrow-left" size="16" />
            {{ t('common.back') }}
          </NuxtLink>

          <template v-if="hasOrderError">
            <div class="bg-error/20 border border-error/30 rounded-lg p-4">
              <div class="font-semibold text-white mb-2">{{ t('common.error') }}</div>
              <div class="text-sm text-white/70 mb-3">{{ orderError }}</div>
              <button class="btn btn-sm bg-white/10 border-white/20 text-white" @click="loadOrder">
                {{ t('ordersDetail.errors.retry') }}
              </button>
            </div>
          </template>

          <template v-else-if="!isLoadingOrder && order">
            <div class="flex items-center gap-3">
              <div class="w-12 h-12 rounded-xl bg-indigo-500/20 flex items-center justify-center">
                <Icon name="lucide:package" size="24" class="text-indigo-400" />
              </div>
              <div class="flex-1 min-w-0">
                <div class="font-bold text-lg text-white truncate">{{ orderTitle }}</div>
                <div class="flex items-center gap-2 flex-wrap">
                  <span v-for="(meta, idx) in orderMeta" :key="idx" class="text-xs text-white/50">
                    {{ meta }}{{ idx < orderMeta.length - 1 ? ' · ' : '' }}
                  </span>
                </div>
              </div>
            </div>
          </template>

          <template v-else>
            <div class="animate-pulse">
              <div class="h-12 bg-white/10 rounded-xl w-48" />
            </div>
          </template>
        </div>

        <!-- Scrollable content -->
        <div v-if="!hasOrderError && order" class="overflow-y-auto h-[calc(70vh-140px)] px-6 py-4 space-y-4">
          <!-- Route stages -->
          <div v-if="orderStageItems.length" class="bg-white/5 rounded-xl p-4 border border-white/10">
            <div class="font-semibold text-white mb-3 flex items-center gap-2">
              <Icon name="lucide:route" size="18" />
              {{ t('ordersDetail.sections.stages.title', 'Маршрут') }}
            </div>
            <div class="space-y-3">
              <div
                v-for="(stage, idx) in orderStageItems"
                :key="stage.key || idx"
                class="flex gap-3"
              >
                <div class="flex flex-col items-center">
                  <div class="w-3 h-3 rounded-full bg-indigo-500" />
                  <div v-if="idx < orderStageItems.length - 1" class="w-0.5 flex-1 bg-white/20 my-1" />
                </div>
                <div class="flex-1 pb-3">
                  <div class="text-sm text-white font-medium">{{ stage.from }}</div>
                  <div v-if="stage.to && stage.to !== stage.from" class="text-xs text-white/50 mt-0.5">
                    → {{ stage.to }}
                  </div>
                  <div v-if="stage.meta?.length" class="text-xs text-white/40 mt-1">
                    {{ stage.meta.join(' · ') }}
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- Timeline -->
          <div v-if="order.stages?.length" class="bg-white/5 rounded-xl p-4 border border-white/10">
            <div class="font-semibold text-white mb-3 flex items-center gap-2">
              <Icon name="lucide:calendar" size="18" />
              {{ t('ordersDetail.sections.timeline.title') }}
            </div>
            <GanttTimeline
              :stages="order.stages"
              :showLoading="showLoading"
              :showUnloading="showUnloading"
            />
          </div>

          <!-- Map preview (small) -->
          <div v-if="orderRoutesForMap.length" class="bg-white/5 rounded-xl p-4 border border-white/10">
            <div class="font-semibold text-white mb-3 flex items-center gap-2">
              <Icon name="lucide:map" size="18" />
              {{ t('ordersDetail.sections.map.title', 'Карта') }}
            </div>
            <RequestRoutesMap :routes="orderRoutesForMap" :height="200" />
          </div>
        </div>
      </div>
    </div>
    </Transition>
  </div>
</template>

<style scoped>
.slide-up-enter-active,
.slide-up-leave-active {
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.slide-up-enter-from,
.slide-up-leave-to {
  transform: translateY(100%);
}
</style>

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

// Types from GraphQL
type OrderType = NonNullable<GetOrderQueryResult['getOrder']>
type StageType = NonNullable<NonNullable<OrderType['stages']>[number]>
type CompanyType = NonNullable<StageType['selectedCompany']>

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

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

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

// Map points for route visualization
const mapPoints = computed(() => {
  if (!order.value) return []

  const points: Array<{ uuid: string; name: string; latitude: number; longitude: number }> = []

  // Add source
  if (order.value.sourceLatitude && order.value.sourceLongitude) {
    points.push({
      uuid: 'source',
      name: order.value.sourceLocationName || t('ordersDetail.labels.source'),
      latitude: order.value.sourceLatitude,
      longitude: order.value.sourceLongitude
    })
  }

  // Add destination
  if (order.value.destinationLatitude && order.value.destinationLongitude) {
    points.push({
      uuid: 'destination',
      name: order.value.destinationLocationName || t('ordersDetail.labels.destination'),
      latitude: order.value.destinationLatitude,
      longitude: order.value.destinationLongitude
    })
  }

  return points
})

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((stage): stage is StageType => stage !== null)
    .map((stage) => {
      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 }]
})

// Company summary type
interface CompanySummary {
  name: string | null | undefined
  totalWeight: number
  tripsCount: number
  company: CompanyType | null | undefined
}

const orderStageItems = computed<RouteStageItem[]>(() => {
  return (order.value?.stages || [])
    .filter((stage): stage is StageType => stage !== null)
    .map((stage) => {
      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: CompanySummary) => {
        meta.push(
          `${company.name} · ${company.totalWeight || 0}${t('ordersDetail.labels.weight_unit')} · ${company.tripsCount || 0} ${t('ordersDetail.labels.trips')}`
        )
      })

      return {
        key: stage.uuid ?? undefined,
        from: from ?? undefined,
        to: to ?? undefined,
        label: stage.name ?? undefined,
        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 ?? null
  } catch (err: unknown) {
    hasOrderError.value = true
    orderError.value = err instanceof Error ? 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: StageType): CompanySummary[] => {
  const companies: CompanySummary[] = []
  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<string, CompanySummary>()
    stage.trips.forEach((trip) => {
      if (!trip) return
      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) => {
    if (!stage) return
    stage.trips?.forEach((trip) => {
      if (!trip) return
      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: StageType) => {
  if (!stage.trips?.length) return t('ordersDetail.labels.dates_undefined')
  let minDate: Date | null = null
  let maxDate: Date | null = null
  stage.trips.forEach((trip) => {
    if (!trip) return
    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>
