<template>
  <div class="map-page">
    <div class="page-header">
      <h2>Shop Floor Map</h2>
      <router-link v-if="authStore.isAuthenticated" to="/map/editor" class="btn btn-primary">
        Edit Map
      </router-link>
    </div>

    <div v-if="loading" class="loading">Loading...</div>

    <template v-else>
      <!-- Filter Controls -->
      <div class="map-filters">
        <select v-model="selectedType" @change="onTypeChange">
          <option value="">All Asset Types</option>
          <option v-for="t in assetTypes" :key="t.assettypeid" :value="t.assettype">
            {{ formatTypeName(t.assettype) }} ({{ getTypeCount(t.assettype) }})
          </option>
        </select>

        <select v-model="selectedSubtype" @change="updateMapLayers" :disabled="!selectedType || !currentSubtypes.length">
          <option value="">{{ subtypeLabel }}</option>
          <option v-for="st in currentSubtypes" :key="st.id" :value="st.id">
            {{ st.name }}
          </option>
        </select>

        <select v-model="selectedBusinessUnit" @change="updateMapLayers">
          <option value="">All Business Units</option>
          <option v-for="bu in businessunits" :key="bu.businessunitid" :value="bu.businessunitid">
            {{ bu.businessunit }}
          </option>
        </select>

        <select v-model="selectedStatus" @change="updateMapLayers">
          <option value="">All Statuses</option>
          <option v-for="s in statuses" :key="s.statusid" :value="s.statusid">
            {{ s.status }}
          </option>
        </select>

        <input
          type="text"
          v-model="searchQuery"
          placeholder="Search assets..."
          @input="debouncedSearch"
        />

        <button
          class="btn btn-secondary export-btn"
          @click="exportPdf"
          :disabled="exporting || !filteredAssets.length"
          :title="filteredAssets.length ? 'Export the filtered map to PDF' : 'No assets to export'"
        >
          {{ exporting ? 'Exporting...' : 'Export PDF' }}
        </button>

        <span class="result-count">{{ filteredAssets.length }} assets</span>
      </div>

      <ShopFloorMap
        :machines="filteredAssets"
        :machinetypes="[]"
        :businessunits="businessunits"
        :statuses="statuses"
        :assetTypeMode="true"
        :theme="currentTheme"
        :selectedAssetType="selectedType"
        :subtypeColors="subtypeColorMap"
        :subtypeNames="subtypeNameMap"
        @markerClick="handleMarkerClick"
      />
    </template>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import ShopFloorMap from '../components/ShopFloorMap.vue'
import { assetsApi } from '../api'
import { currentTheme } from '../stores/theme'
import { useAuthStore } from '../stores/auth'
import { loadMapConfig, state as mapConfig } from '../composables/mapConfig'
import { exportMapPdf } from '../utils/mapPdf'
import { assetTypeLabel, assetDetailRoute } from '../utils/assetTypes'
import { useToast } from '../composables/toast'
const toast = useToast()

const router = useRouter()
const authStore = useAuthStore()
const loading = ref(true)
const assets = ref([])
const assetTypes = ref([])
const businessunits = ref([])
const statuses = ref([])
const subtypes = ref({})

// Filter state
const selectedType = ref('')
const selectedSubtype = ref('')
const selectedBusinessUnit = ref('')
const selectedStatus = ref('')
const searchQuery = ref('')
const exporting = ref(false)

let searchTimeout = null

// Lookup helper for subtypes. Normalizes case AND underscores-vs-spaces, since
// the asset-type value is 'network_device' but the subtypes key is
// 'Network Device' - without normalizing, network subtypes never match.
function getSubtypesForType(typeName) {
  if (!typeName || !subtypes.value) return []
  // Try exact match first
  if (subtypes.value[typeName]) return subtypes.value[typeName]
  const norm = typeName.toLowerCase().replace(/_/g, ' ')
  for (const [key, value] of Object.entries(subtypes.value)) {
    if (key.toLowerCase().replace(/_/g, ' ') === norm) return value
  }
  return []
}

const currentSubtypes = computed(() => {
  if (!selectedType.value) return []
  return getSubtypesForType(selectedType.value)
})

const subtypeLabel = computed(() => {
  if (!selectedType.value) return 'Select type first'
  if (!currentSubtypes.value.length) return 'No subtypes'
  const labels = {
    'machine': 'All Machine Types',
    'computer': 'All Computer Types',
    'network device': 'All Device Types',
    'printer': 'All Printer Types'
  }
  return labels[selectedType.value.toLowerCase().replace(/_/g, ' ')] || 'All Subtypes'
})

// Generate distinct colors for subtypes
const subtypeColorPalette = [
  '#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5',
  '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50',
  '#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800',
  '#FF5722', '#795548', '#607D8B', '#00ACC1', '#5C6BC0'
]

// Map subtype IDs to colors: prefer each subtype's stored color; fall back to
// the auto palette (by index) for subtypes that have not been given one.
const subtypeColorMap = computed(() => {
  const colorMap = {}
  const allSubtypes = currentSubtypes.value
  allSubtypes.forEach((st, index) => {
    colorMap[st.id] = st.color || subtypeColorPalette[index % subtypeColorPalette.length]
  })
  return colorMap
})

// Map subtype IDs to names
const subtypeNameMap = computed(() => {
  const nameMap = {}
  currentSubtypes.value.forEach(st => {
    nameMap[st.id] = st.name
  })
  return nameMap
})

const filteredAssets = computed(() => {
  let result = assets.value

  // Filter by asset type (case-insensitive)
  if (selectedType.value) {
    const selectedLower = selectedType.value.toLowerCase()
    result = result.filter(a => a.assettype && a.assettype.toLowerCase() === selectedLower)
  }

  // Filter by subtype (normalize network_device -> network device)
  if (selectedSubtype.value) {
    const subtypeId = parseInt(selectedSubtype.value)
    const typeLower = (selectedType.value || '').toLowerCase().replace(/_/g, ' ')
    result = result.filter(a => {
      if (!a.typedata) return false
      // Check different ID fields based on asset type
      if (typeLower === 'machine') {
        return a.typedata.machinetypeid === subtypeId
      } else if (typeLower === 'computer') {
        return a.typedata.computertypeid === subtypeId
      } else if (typeLower === 'network device') {
        return a.typedata.networkdevicetypeid === subtypeId
      } else if (typeLower === 'printer') {
        return a.typedata.printertypeid === subtypeId
      }
      return false
    })
  }

  // Filter by business unit
  if (selectedBusinessUnit.value) {
    result = result.filter(a => a.businessunitid === parseInt(selectedBusinessUnit.value))
  }

  // Filter by status
  if (selectedStatus.value) {
    result = result.filter(a => a.statusid === parseInt(selectedStatus.value))
  }

  // Filter by search query
  if (searchQuery.value) {
    const q = searchQuery.value.toLowerCase()
    result = result.filter(a =>
      (a.assetnumber && a.assetnumber.toLowerCase().includes(q)) ||
      (a.name && a.name.toLowerCase().includes(q)) ||
      (a.displayname && a.displayname.toLowerCase().includes(q)) ||
      (a.serialnumber && a.serialnumber.toLowerCase().includes(q))
    )
  }

  return result
})

// Human-readable labels for the filters currently applied, for the PDF header.
function activeFilterLabels() {
  const labels = []
  if (selectedType.value) labels.push(`Type: ${formatTypeName(selectedType.value)}`)
  if (selectedSubtype.value) {
    const st = currentSubtypes.value.find(s => String(s.id) === String(selectedSubtype.value))
    if (st) labels.push(`Subtype: ${st.name}`)
  }
  if (selectedBusinessUnit.value) {
    const bu = businessunits.value.find(b => String(b.businessunitid) === String(selectedBusinessUnit.value))
    if (bu) labels.push(`Business Unit: ${bu.businessunit}`)
  }
  if (selectedStatus.value) {
    const s = statuses.value.find(x => String(x.statusid) === String(selectedStatus.value))
    if (s) labels.push(`Status: ${s.status}`)
  }
  if (searchQuery.value) labels.push(`Search: "${searchQuery.value}"`)
  return labels
}

async function exportPdf() {
  if (!filteredAssets.value.length) return
  exporting.value = true
  try {
    await loadMapConfig()
    await exportMapPdf({
      assets: filteredAssets.value,
      blueprintUrl: mapConfig.blueprintLight,
      mapWidth: mapConfig.width,
      mapHeight: mapConfig.height,
      selectedType: selectedType.value,
      subtypeColors: subtypeColorMap.value,
      subtypeNames: subtypeNameMap.value,
      filters: activeFilterLabels()
    })
  } catch (e) {
    console.error('Map PDF export failed:', e)
    toast.error('Failed to export map PDF. See console for details.')
  } finally {
    exporting.value = false
  }
}

onMounted(async () => {
  loadMapConfig()
  try {
    const response = await assetsApi.getMap()
    const data = response.data.data || {}

    assets.value = data.assets || []
    assetTypes.value = data.filters?.assettypes || []
    businessunits.value = data.filters?.businessunits || []
    statuses.value = data.filters?.statuses || []
    subtypes.value = data.filters?.subtypes || {}
  } catch (error) {
    console.error('Failed to load map data:', error)
  } finally {
    loading.value = false
  }
})

function formatTypeName(assettype) {
  return assetTypeLabel(assettype)
}

function getTypeCount(assettype) {
  if (!assettype) return 0
  const lowerType = assettype.toLowerCase()
  return assets.value.filter(a => a.assettype && a.assettype.toLowerCase() === lowerType).length
}

function onTypeChange() {
  // Reset subtype when type changes
  selectedSubtype.value = ''
  updateMapLayers()
}

function updateMapLayers() {
  // Filter is reactive via computed property
}

function debouncedSearch() {
  clearTimeout(searchTimeout)
  searchTimeout = setTimeout(() => {
    updateMapLayers()
  }, 300)
}

function handleMarkerClick(asset) {
  router.push(assetDetailRoute(asset))
}
</script>

<style scoped>
.map-page {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 2rem);
}

.map-page .page-header {
  flex-shrink: 0;
}

.map-filters {
  display: flex;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.75rem;
  flex-wrap: wrap;
  align-items: center;
}

.map-filters select,
.map-filters input {
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 0.875rem;
}

.map-filters select {
  min-width: 160px;
}

.map-filters select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.map-filters input {
  min-width: 180px;
}

.export-btn {
  margin-left: auto;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-card);
  color: var(--text);
  font-size: 0.875rem;
  cursor: pointer;
}

.export-btn:hover:not(:disabled) {
  border-color: var(--primary);
  color: var(--primary);
}

.export-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.result-count {
  color: var(--text-light);
  font-size: 0.875rem;
}

.map-page :deep(.shopfloor-map) {
  flex: 1;
}
</style>
