<template>
  <div class="cpSeatMap" :style="seatMapDynamicStyle" :class="seatMapClasses">
    <cp-seat-map-plane
      :key="seatMap.aircraft"
      class="cpSeatMap__plane"
      :is-large="isLargePlane"
      :map-key="seatMap.ref_id_segment"
      :transition-direction="transitionDirection"
    >
      <cp-seat-map-zone v-for="zone in zones" :key="zone.id" class="cpSeatMap__zone" :title="zone.title">
        <cp-seat-map-grid class="cpSeatMap__grid" :layout="zone.layout" :style="getGridDynamicStyle(zone.layout)">
          <cp-seat-map-row
            v-for="row in getZoneRows(seatMap, zone.id)"
            :key="row.number"
            class="cpSeatMap__row"
            :config="config"
            :row="row"
            :seat-block-size="getSeatBlockSize(zone.layout)"
          >
            <cp-seat-map-seat-wrapper
              v-for="seat in row.seats"
              :key="seat.id"
              :config="config"
              :is-highlighted="isSeatHighlighted(seat)"
              :is-selection-enabled="isSelectionEnabled"
              :row-number="row.number"
              :seat="seat"
              :selection="getSeatSelection(row.number, seat.column)"
              :style="getSeatDynamicStyle(seat)"
              @select="handleSelectSeat"
            />
            <template v-if="hasHallway(zone.layout)">
              <span
                v-for="hallway in getHallways(zone.layout)"
                :key="hallway.index"
                class="cpSeatMap__hallway"
                :style="getHallwayDynamicStyle(hallway.index)"
              >
                {{ row.number }}
              </span>
            </template>
          </cp-seat-map-row>
        </cp-seat-map-grid>
      </cp-seat-map-zone>
    </cp-seat-map-plane>

    <cp-seat-map-emergency-exit-dialog
      v-model:is-visible="isEmergencyExitDialogVisible"
      :config="config"
      @close="handleCloseEmergencyExitDialog"
      @confirm="handleConfirmEmergencyExit"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'

import type { CpSeatMapConfig } from '@/constants/seatMap/CpSeatMapConfig'
import type { CpSeatMapSeatSelection } from '@/constants/seatMap/CpSeatMapSeatSelection'
import type { Seat } from '@/constants/seatMap/Seat'
import type { SeatMap } from '@/constants/seatMap/SeatMap'

import { DEFAULT_CP_SEAT_MAP_CONFIG } from '@/constants/seatMap/CpSeatMapConfig'
import { CpSeatMapTransitionDirections } from '@/constants/seatMap/CpSeatMapTransitionDirections'
import {
  displaySeat,
  getGridTemplateAreas,
  getGridTemplateColumns,
  getHallways,
  getSeatBlockSize,
  getSeatMapZones,
  getZoneRows,
  hasHallway,
  isLargeSeatMap,
  type SeatMapLayout,
} from '@/helpers/seatMap'
import CpSeatMapEmergencyExitDialog from './CpSeatMapEmergencyExitDialog.vue'
import CpSeatMapGrid from './CpSeatMapGrid.vue'
import CpSeatMapPlane from './CpSeatMapPlane.vue'
import CpSeatMapRow from './CpSeatMapRow.vue'
import CpSeatMapSeatWrapper from './CpSeatMapSeatWrapper.vue'
import CpSeatMapZone from './CpSeatMapZone.vue'

interface Props {
  config?: CpSeatMapConfig
  highlightedSeatId?: number | null
  isSelectionEnabled?: boolean
  seatMap: SeatMap
  selections?: Record<string, CpSeatMapSeatSelection>
  transitionDirection?: CpSeatMapTransitionDirections
}

const props = withDefaults(defineProps<Props>(), {
  config: () => DEFAULT_CP_SEAT_MAP_CONFIG,
  highlightedSeatId: null,
  isSelectionEnabled: true,
  selections: () => ({}),
  transitionDirection: CpSeatMapTransitionDirections.FORWARD,
})

const emit = defineEmits<{ select: [seat: Seat, rowNumber: number] }>()

const isEmergencyExitDialogVisible = ref(false)
const pendingExitRowSeat = ref<{ rowNumber: number; seat: Seat } | null>(null)

const zones = computed(() => getSeatMapZones(props.seatMap))

const isLargePlane = computed(() => isLargeSeatMap(zones.value))

const seatMapClasses = computed(() => {
  return { 'cpSeatMap--isLarge': isLargePlane.value }
})

const seatMapDynamicStyle = computed(() => {
  return {
    '--seat-mobile-width': isLargePlane.value ? '32px' : '40px',
    '--hallway-mobile-width': isLargePlane.value ? '16px' : '32px',
  }
})

const getGridDynamicStyle = (layout: SeatMapLayout) => {
  return {
    '--columns-count': layout.length,
    '--grid-template-areas': `"${getGridTemplateAreas(layout)}"`,
    '--grid-template-columns': getGridTemplateColumns(layout),
  }
}

const getSeatSelection = (rowNumber: number, column: string) => {
  return props.selections[displaySeat({ row: rowNumber, column })] ?? null
}

const getSeatDynamicStyle = (seat: Seat) => {
  return {
    gridColumn: seat.column,
  }
}

const getHallwayDynamicStyle = (hallwayIndex: number) => {
  return {
    gridArea: `HALLWAY-${hallwayIndex}`,
  }
}

const isSeatHighlighted = (seat: Seat) => props.highlightedSeatId === seat.id

const handleSelectSeat = (seat: Seat, rowNumber: number) => {
  if (seat.is_exit_row) {
    pendingExitRowSeat.value = { rowNumber, seat }
    isEmergencyExitDialogVisible.value = true
    return
  }

  emit('select', seat, rowNumber)
}

const handleCloseEmergencyExitDialog = () => {
  isEmergencyExitDialogVisible.value = false
  pendingExitRowSeat.value = null
}

const handleConfirmEmergencyExit = () => {
  if (pendingExitRowSeat.value) {
    const { seat, rowNumber } = pendingExitRowSeat.value
    emit('select', seat, rowNumber)
  }

  handleCloseEmergencyExitDialog()
}
</script>

<style lang="scss">
.cpSeatMap {
  --hallway-width: 32px;
  --seat-width: 32px;

  position: relative;
  min-height: 75vh;

  &__grid > div {
    grid-template-areas: var(--grid-template-areas);
    grid-template-columns: var(--grid-template-columns);
  }

  &__hallway {
    font-size: fn.px-to-em(12);
    font-weight: 700;
    letter-spacing: fn.px-to-rem(2);
    line-height: fn.px-to-rem(24);
    text-transform: uppercase;
  }

  &__row:has(.cpSeatMapRowFacility--isTop) .cpSeatMap__hallway {
    grid-row: 2 !important;
    place-self: end center;
  }

  &__zone {
    position: relative;
    z-index: 1;
  }
}

@include mx.media-query-max(551px) {
  .cpSeatMap {
    --seat-width: var(--seat-mobile-width);
    --hallway-width: var(--hallway-mobile-width);

    &:not(&--isLarge) &__grid > div {
      gap: var(--cp-spacing-md);
    }

    &__plane .cpSeatMapPlane__plane {
      display: none;
    }

    &__hallway {
      font-size: fn.px-to-em(10);
    }
  }
}
</style>
