<script setup lang="ts">
type CalendarCheckpoint = {
  code: string
  name: string
  plannedDate?: string | null
  actualDate?: string | null
  completed: boolean
  current: boolean
}

type CalendarOrder = {
  id: string
  status: string
  quotationId?: string | null
  totalAmount: number
  currency: string
  createdAt: string
  pickupDate?: string | null
  fromAddress: {
    city: string
    country: string
  }
  toAddress: {
    city: string
    country: string
  }
  currentCheckpoint?: {
    code: string
    name: string
    plannedDate?: string | null
    completed: boolean
    current: boolean
  } | null
  checkpoints: CalendarCheckpoint[]
}

const props = defineProps<{
  orders: CalendarOrder[]
}>()

const emit = defineEmits<{
  select: [orderId: string]
}>()

const weekdayLabels = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']

function startOfMonthUtc(value: Date) {
  return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), 1))
}

function addMonthsUtc(value: Date, diff: number) {
  return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth() + diff, 1))
}

function formatDateKey(value: Date) {
  return value.toISOString().slice(0, 10)
}

function toDateOnlyDate(value?: string | null) {
  if (!value) return null
  const normalized = String(value).trim()
  if (!normalized) return null
  const date = new Date(`${normalized}T00:00:00.000Z`)
  if (Number.isNaN(date.getTime())) return null
  return date
}

function orderAnchorCheckpoint(order: CalendarOrder) {
  const plannedCurrent = order.checkpoints.find(checkpoint => checkpoint.current && checkpoint.plannedDate)
  if (plannedCurrent) return plannedCurrent

  const firstPending = order.checkpoints.find(checkpoint => !checkpoint.completed && checkpoint.plannedDate)
  if (firstPending) return firstPending

  const lastPlanned = [...order.checkpoints].reverse().find(checkpoint => checkpoint.plannedDate)
  if (lastPlanned) return lastPlanned

  return order.currentCheckpoint || null
}

function orderCalendarDate(order: CalendarOrder) {
  const checkpointDate = orderAnchorCheckpoint(order)?.plannedDate
  if (checkpointDate) return checkpointDate
  if (order.pickupDate) return order.pickupDate
  return order.createdAt.slice(0, 10)
}

function orderCalendarLabel(order: CalendarOrder) {
  const checkpoint = orderAnchorCheckpoint(order)
  if (checkpoint?.name) return checkpoint.name
  return 'Дата уточняется'
}

function orderPersonLabel(order: CalendarOrder) {
  if (order.quotationId) {
    return `Клиент ${order.quotationId.slice(-6).toUpperCase()}`
  }

  return `Клиент ${order.id.slice(-6).toUpperCase()}`
}

function orderAvatarSeed(order: CalendarOrder) {
  return order.quotationId || order.id
}

const initialMonth = computed(() => {
  const firstOrderDate = props.orders
    .map(order => toDateOnlyDate(orderCalendarDate(order)))
    .find(Boolean)

  return startOfMonthUtc(firstOrderDate || new Date())
})

const visibleMonth = ref(startOfMonthUtc(initialMonth.value))

watch(initialMonth, (nextValue) => {
  visibleMonth.value = startOfMonthUtc(nextValue)
})

const monthLabel = computed(() => {
  return new Intl.DateTimeFormat('ru-RU', {
    month: 'long',
    year: 'numeric',
    timeZone: 'UTC',
  }).format(visibleMonth.value)
})

const calendarOrdersByDay = computed(() => {
  return props.orders.reduce<Record<string, CalendarOrder[]>>((acc, order) => {
    const dateKey = orderCalendarDate(order)
    if (!dateKey) return acc
    if (!acc[dateKey]) acc[dateKey] = []
    acc[dateKey].push(order)
    return acc
  }, {})
})

const monthCells = computed(() => {
  const firstDay = visibleMonth.value
  const firstWeekday = (firstDay.getUTCDay() + 6) % 7
  const gridStart = new Date(firstDay.getTime())
  gridStart.setUTCDate(gridStart.getUTCDate() - firstWeekday)

  return Array.from({ length: 42 }, (_, index) => {
    const date = new Date(gridStart.getTime())
    date.setUTCDate(gridStart.getUTCDate() + index)
    const dateKey = formatDateKey(date)
    return {
      key: dateKey,
      date,
      dateKey,
      inCurrentMonth: date.getUTCMonth() === visibleMonth.value.getUTCMonth(),
      isToday: dateKey === formatDateKey(new Date()),
      orders: calendarOrdersByDay.value[dateKey] || [],
    }
  })
})

function previousMonth() {
  visibleMonth.value = addMonthsUtc(visibleMonth.value, -1)
}

function nextMonth() {
  visibleMonth.value = addMonthsUtc(visibleMonth.value, 1)
}

function openOrder(orderId: string) {
  emit('select', orderId)
}
</script>

<template>
  <section class="rounded-[28px] bg-white p-4 md:p-5">
    <div class="flex items-center justify-between gap-3">
      <div>
        <p class="text-xs font-bold uppercase tracking-[0.14em] text-[#8c7b67]">Orders calendar</p>
        <p class="mt-1 text-lg font-black capitalize text-[#2f2418]">{{ monthLabel }}</p>
      </div>

      <div class="inline-flex items-center rounded-full bg-[#f6f1ea] p-1">
        <button
          type="button"
          class="flex h-9 w-9 items-center justify-center rounded-full text-[#5f4b33] transition hover:bg-white"
          aria-label="Previous month"
          @click="previousMonth"
        >
          <svg viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="m15 18-6-6 6-6" />
          </svg>
        </button>
        <button
          type="button"
          class="flex h-9 w-9 items-center justify-center rounded-full text-[#5f4b33] transition hover:bg-white"
          aria-label="Next month"
          @click="nextMonth"
        >
          <svg viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="m9 6 6 6-6 6" />
          </svg>
        </button>
      </div>
    </div>

    <div class="mt-4 grid grid-cols-7 gap-2">
      <div
        v-for="weekday in weekdayLabels"
        :key="weekday"
        class="px-1 text-center text-[11px] font-bold uppercase tracking-[0.12em] text-[#8c7b67]"
      >
        {{ weekday }}
      </div>

      <article
        v-for="cell in monthCells"
        :key="cell.key"
        class="flex min-h-[132px] flex-col rounded-[22px] border border-[#e6ddd1] bg-[#fbf8f4] p-2.5"
        :class="[
          cell.inCurrentMonth ? 'opacity-100' : 'opacity-45',
          cell.isToday ? 'ring-2 ring-[#8bc7f2]/70' : '',
        ]"
      >
        <div class="mb-2 flex items-center justify-between gap-2">
          <span class="text-sm font-black text-[#2f2418]">{{ cell.date.getUTCDate() }}</span>
          <span v-if="cell.orders.length" class="rounded-full bg-white px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.1em] text-[#5f4b33]">
            {{ cell.orders.length }}
          </span>
        </div>

        <div class="flex flex-1 flex-col gap-1.5">
          <button
            v-for="order in cell.orders.slice(0, 3)"
            :key="order.id"
            type="button"
            class="rounded-[16px] bg-white px-2.5 py-2 text-left transition hover:shadow-[0_12px_30px_rgba(38,29,18,0.14)]"
            @click="openOrder(order.id)"
          >
            <div class="flex items-start gap-2">
              <UserAvatar
                :seed="orderAvatarSeed(order)"
                :label="orderPersonLabel(order)"
                :size="26"
              />
              <div class="min-w-0">
                <p class="truncate text-[11px] font-black text-[#2f2418]">
                  {{ orderPersonLabel(order) }}
                </p>
                <p class="truncate text-xs font-black text-[#2f2418]">
                  {{ order.fromAddress.city }} • {{ order.toAddress.city }}
                </p>
                <p class="mt-0.5 truncate text-[11px] text-[#7c6d5d]">
                  {{ orderCalendarLabel(order) }}
                </p>
              </div>
            </div>
          </button>

          <div
            v-if="cell.orders.length > 3"
            class="rounded-[16px] bg-white/70 px-2.5 py-2 text-[11px] font-semibold text-[#7c6d5d]"
          >
            Ещё {{ cell.orders.length - 3 }}
          </div>
        </div>
      </article>
    </div>
  </section>
</template>
