<template>
  <Transition name="order-slide">
    <div
      v-if="isOpen && orderUuid"
      class="fixed inset-x-0 bottom-0 z-50 flex flex-col"
      style="height: 70vh"
    >
      <!-- Backdrop (clickable to close) -->
      <div
        class="absolute inset-0 -top-[30vh] bg-black/30"
        @click="emit('close')"
      />

      <!-- Sheet content -->
      <div class="relative flex-1 bg-black/40 backdrop-blur-xl rounded-t-2xl border-t border-white/20 shadow-2xl overflow-hidden">
        <!-- Header with drag handle and close -->
        <div class="sticky top-0 z-10 bg-black/30 backdrop-blur-md border-b border-white/10">
          <div class="flex justify-center py-2">
            <div class="w-12 h-1.5 bg-white/30 rounded-full" />
          </div>
          <div class="flex items-center justify-between px-6 pb-4">
            <template v-if="hasOrderError">
              <div class="flex-1">
                <div class="font-semibold text-white">{{ t('common.error') }}</div>
                <div class="text-sm text-white/50">{{ orderError }}</div>
              </div>
            </template>

            <template v-else-if="!isLoadingOrder && order">
              <div class="flex items-center gap-3 flex-1 min-w-0">
                <div class="w-10 h-10 bg-indigo-500/20 rounded-xl flex items-center justify-center flex-shrink-0">
                  <Icon name="lucide:package" size="24" class="text-indigo-400" />
                </div>
                <div class="min-w-0">
                  <div class="font-bold text-white truncate">{{ orderTitle }}</div>
                  <div class="flex items-center gap-2 mt-0.5">
                    <span class="badge badge-primary badge-sm">#{{ order.name }}</span>
                    <span v-if="order.status" class="badge badge-outline badge-sm text-white/60">{{ order.status }}</span>
                  </div>
                </div>
              </div>
            </template>

            <template v-else>
              <div class="flex items-center gap-3 flex-1">
                <div class="w-10 h-10 bg-white/10 rounded-xl animate-pulse" />
                <div class="flex-1">
                  <div class="h-5 bg-white/10 rounded w-48 animate-pulse" />
                  <div class="h-4 bg-white/10 rounded w-32 mt-1 animate-pulse" />
                </div>
              </div>
            </template>

            <button class="btn btn-ghost btn-sm btn-circle text-white/60 hover:text-white flex-shrink-0" @click="emit('close')">
              <Icon name="lucide:x" size="20" />
            </button>
          </div>
        </div>

        <!-- Error state -->
        <div v-if="hasOrderError" class="px-6 py-8 text-center">
          <div class="text-white/70 mb-4">{{ orderError }}</div>
          <button class="btn btn-sm bg-white/10 border-white/20 text-white" @click="loadOrder">
            {{ t('ordersDetail.errors.retry') }}
          </button>
        </div>

        <!-- Scrollable content -->
        <div v-else-if="order" class="overflow-y-auto h-[calc(70vh-100px)] px-6 py-4 space-y-4">
          <!-- Order meta -->
          <div class="flex flex-wrap gap-2 text-sm">
            <span v-for="(meta, idx) in orderMeta" :key="idx" class="px-3 py-1 bg-white/10 rounded-full text-white/70">
              {{ meta }}
            </span>
          </div>

          <!-- 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="true"
              :showUnloading="true"
            />
          </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>

        <!-- Loading state -->
        <div v-else class="px-6 py-4 space-y-4">
          <div class="h-20 bg-white/5 rounded-xl animate-pulse" />
          <div class="h-32 bg-white/5 rounded-xl animate-pulse" />
          <div class="h-48 bg-white/5 rounded-xl animate-pulse" />
        </div>
      </div>
    </div>
  </Transition>
</template>

<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']>

const props = defineProps<{
  isOpen: boolean
  orderUuid: string | null
}>()

const emit = defineEmits<{
  'close': []
}>()

const { t } = useI18n()

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

// Load order when uuid changes
watch(() => props.orderUuid, async (uuid) => {
  if (uuid && props.isOpen) {
    await loadOrder()
  }
}, { immediate: true })

// Also load when opening
watch(() => props.isOpen, async (open) => {
  if (open && props.orderUuid) {
    await loadOrder()
  } else if (!open) {
    // Reset state when closing
    order.value = null
    hasOrderError.value = false
    orderError.value = ''
  }
})

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 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 () => {
  if (!props.orderUuid) return

  try {
    isLoadingOrder.value = true
    hasOrderError.value = false
    const { data, error: orderErrorResp } = await useServerQuery('order-detail-sheet', GetOrderDocument, { orderUuid: props.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)}`
}
</script>

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

.order-slide-enter-from,
.order-slide-leave-to {
  transform: translateY(100%);
  opacity: 0;
}

.order-slide-enter-to,
.order-slide-leave-from {
  transform: translateY(0);
  opacity: 1;
}
</style>
