<template>
  <div class="h-screen flex flex-col bg-monokai-bg">
    <!-- Header -->
    <header class="bg-monokai-bg border-b-2 border-monokai-comment p-4">
      <div class="flex items-center justify-between">
        <div class="flex items-center gap-4">
          <h1 class="text-3xl font-bold text-monokai-green">IPWatch</h1>
          <div class="flex flex-col">
            <span class="text-monokai-comment">Ports & Services</span>
          </div>
        </div>

        <div class="flex items-center gap-6">
          <SystemStats />

          <div class="h-8 w-px bg-monokai-comment"></div>

          <button
            @click="goToDashboard"
            class="px-4 py-2 rounded bg-monokai-yellow text-monokai-bg font-bold hover:bg-monokai-orange transition-colors"
            title="Retour au dashboard"
          >
            <span class="mdi mdi-arrow-left"></span> Dashboard
          </button>

          <button
            @click="openSettings"
            class="px-4 py-2 rounded bg-monokai-purple text-monokai-bg text-sm hover:bg-monokai-pink transition-colors"
            title="Ouvrir les paramètres"
          >
            <span class="mdi mdi-cog"></span> Paramètres
          </button>
        </div>
      </div>
    </header>

    <!-- Layout 3 colonnes -->
    <div class="flex-1 flex overflow-hidden">

      <!-- Volet gauche : Liste des services -->
      <div class="w-80 flex-shrink-0 border-r border-monokai-comment flex flex-col">
        <div class="p-4 border-b border-monokai-comment">
          <h2 class="text-lg font-bold text-monokai-cyan flex items-center gap-2">
            <span class="mdi mdi-server-network"></span>
            Services
            <span class="text-xs text-monokai-comment font-normal">({{ selectedCount }}/{{ services.length }})</span>
          </h2>
        </div>

        <!-- Liste scrollable des services -->
        <div class="flex-1 overflow-auto p-2">
          <div
            v-for="service in services"
            :key="service.name + service.port"
            class="flex items-center gap-2 px-3 py-1.5 rounded hover:bg-monokai-comment/20 cursor-pointer transition-colors"
            @click="toggleService(service)"
          >
            <input
              type="checkbox"
              :checked="isSelected(service)"
              class="form-checkbox accent-monokai-cyan"
              @click.stop
              @change="toggleService(service)"
            />
            <span class="flex-1 text-sm text-monokai-text truncate">{{ service.name }}</span>
            <span class="text-xs px-1.5 py-0.5 rounded bg-monokai-comment/30 text-monokai-comment font-mono">
              {{ service.port }}
            </span>
            <span v-if="service.protocol" class="text-xs text-monokai-purple">
              {{ service.protocol }}
            </span>
          </div>
          <div v-if="services.length === 0" class="text-center text-monokai-comment text-sm p-4">
            Aucun service configuré dans config.yaml
          </div>
        </div>

        <!-- Boutons de sélection -->
        <div class="p-3 border-t border-monokai-comment flex gap-2">
          <button
            @click="selectAll"
            class="flex-1 px-2 py-1.5 rounded text-xs font-bold bg-monokai-comment/30 text-monokai-text hover:bg-monokai-comment/50 transition-colors"
          >
            Tout cocher
          </button>
          <button
            @click="selectNone"
            class="flex-1 px-2 py-1.5 rounded text-xs font-bold bg-monokai-comment/30 text-monokai-text hover:bg-monokai-comment/50 transition-colors"
          >
            Tout décocher
          </button>
        </div>
      </div>

      <!-- Zone centrale : Scan et résultats -->
      <div class="flex-1 flex flex-col overflow-hidden">

        <!-- Barre d'action -->
        <div class="p-4 border-b border-monokai-comment">
          <div class="flex items-center gap-4">
            <button
              @click="launchScan"
              :disabled="selectedCount === 0 || isScanning"
              class="px-4 py-2 rounded font-bold transition-colors"
              :class="selectedCount === 0 || isScanning
                ? 'bg-monokai-comment/30 text-monokai-comment cursor-not-allowed'
                : 'bg-monokai-cyan text-monokai-bg hover:bg-monokai-green'"
            >
              <span class="mdi mdi-magnify-scan"></span>
              {{ isScanning ? 'Scan en cours...' : 'Lancer le scan' }}
            </button>

            <!-- Progression -->
            <div v-if="isScanning" class="flex items-center gap-3 flex-1">
              <div class="flex-1 h-2 bg-monokai-comment/30 rounded-full overflow-hidden">
                <div
                  class="h-full bg-monokai-cyan transition-all duration-300 rounded-full"
                  :style="{ width: progressPercent + '%' }"
                ></div>
              </div>
              <span class="text-xs text-monokai-cyan whitespace-nowrap">
                {{ scanProgress.current }} / {{ scanProgress.total }}
              </span>
              <span v-if="scanProgress.ip" class="text-xs text-monokai-comment">
                {{ scanProgress.ip }}
              </span>
            </div>

            <!-- Stats résultat -->
            <div v-if="!isScanning && results.length > 0" class="text-sm text-monokai-comment">
              {{ filteredResults.length }} service(s) détecté(s)
              <span v-if="filterText" class="text-monokai-purple">(filtré)</span>
            </div>
          </div>

          <!-- Message informatif sous le scan -->
          <div v-if="isScanning" class="mt-2 text-xs text-monokai-comment flex items-center gap-2">
            <span class="mdi mdi-information-outline text-monokai-cyan"></span>
            Scan de {{ selectedCount }} service(s) sur l'ensemble des IPs connues du réseau.
            Chaque IP est testée avec un timeout de {{ scanTimeout }}s.
            <span v-if="scanProgress.total > 0" class="text-monokai-yellow">
              Temps estimé : ~{{ estimatedTime }}
            </span>
          </div>
        </div>

        <!-- Tableau de résultats -->
        <div v-if="results.length > 0 || isScanning" class="flex-1 overflow-auto">
          <!-- Filtre texte -->
          <div class="px-4 py-2 sticky top-0 bg-monokai-bg border-b border-monokai-comment/50 z-10">
            <input
              v-model="filterText"
              type="text"
              placeholder="Filtrer les résultats (IP, nom, service...)"
              class="w-full px-3 py-1.5 rounded bg-monokai-comment/20 text-monokai-text text-sm border border-monokai-comment/30 focus:border-monokai-cyan focus:outline-none"
            />
          </div>

          <table class="w-full text-sm">
            <thead class="sticky top-[41px] bg-monokai-bg z-10">
              <tr class="text-monokai-comment border-b border-monokai-comment">
                <th class="text-left px-4 py-2 cursor-pointer hover:text-monokai-text" @click="sortBy('ip')">
                  IP {{ sortIcon('ip') }}
                </th>
                <th class="text-left px-4 py-2 cursor-pointer hover:text-monokai-text" @click="sortBy('name')">
                  Nom {{ sortIcon('name') }}
                </th>
                <th class="text-left px-4 py-2 cursor-pointer hover:text-monokai-text" @click="sortBy('service_name')">
                  Service {{ sortIcon('service_name') }}
                </th>
                <th class="text-left px-4 py-2 cursor-pointer hover:text-monokai-text" @click="sortBy('port')">
                  Port {{ sortIcon('port') }}
                </th>
                <th class="text-left px-4 py-2">Lien</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="(row, index) in filteredResults"
                :key="row.ip + '-' + row.port"
                class="border-b border-monokai-comment/20 hover:bg-monokai-comment/10 transition-colors"
                :class="index % 2 === 0 ? 'bg-monokai-bg' : 'bg-monokai-comment/5'"
              >
                <td class="px-4 py-2 font-mono text-monokai-cyan">{{ row.ip }}</td>
                <td class="px-4 py-2 text-monokai-text">{{ row.name || row.hostname || '-' }}</td>
                <td class="px-4 py-2">
                  <span class="px-2 py-0.5 rounded text-xs font-bold"
                    :class="serviceColor(row.protocol)">
                    {{ row.service_name }}
                  </span>
                </td>
                <td class="px-4 py-2 font-mono text-monokai-purple">{{ row.port }}</td>
                <td class="px-4 py-2">
                  <a
                    v-if="row.url"
                    :href="row.url"
                    target="_blank"
                    rel="noopener noreferrer"
                    class="text-monokai-green hover:text-monokai-yellow underline flex items-center gap-1"
                  >
                    <span class="mdi mdi-open-in-new text-xs"></span>
                    {{ row.url }}
                  </a>
                  <span v-else-if="row.protocol" class="text-monokai-comment text-xs">
                    {{ row.protocol }}://{{ row.ip }}:{{ row.port }}
                  </span>
                  <span v-else class="text-monokai-comment text-xs">{{ row.ip }}:{{ row.port }}</span>
                </td>
              </tr>
              <!-- Message pendant le scan si pas encore de résultats -->
              <tr v-if="filteredResults.length === 0 && isScanning">
                <td colspan="5" class="px-4 py-8 text-center text-monokai-comment">
                  <span class="mdi mdi-magnify-scan text-2xl block mb-2 animate-pulse"></span>
                  Scan en cours, en attente de résultats...
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <!-- État vide -->
        <div v-else-if="!isScanning" class="flex-1 flex items-center justify-center">
          <div class="text-center text-monokai-comment">
            <span class="mdi mdi-lan-check text-6xl block mb-4 opacity-30"></span>
            <div class="text-lg">Sélectionnez des services et lancez un scan</div>
            <div class="text-sm mt-2 opacity-60">
              Les résultats afficheront les services actifs sur chaque IP du réseau
            </div>
          </div>
        </div>
      </div>

      <!-- Volet droit : Logs -->
      <div
        class="relative flex-shrink-0 border-l border-monokai-comment"
        :style="{ width: `${rightPanelWidth}px` }"
      >
        <!-- Poignée de redimensionnement -->
        <div
          class="absolute left-0 top-0 bottom-0 w-2 cursor-ew-resize"
          @mousedown.prevent="startResize"
        ></div>
        <div class="absolute left-1 top-1/2 -translate-y-1/2 flex flex-col gap-1 opacity-70 pointer-events-none">
          <span class="w-1.5 h-1.5 rounded-full bg-monokai-comment/70"></span>
          <span class="w-1.5 h-1.5 rounded-full bg-monokai-comment/70"></span>
          <span class="w-1.5 h-1.5 rounded-full bg-monokai-comment/70"></span>
          <span class="w-1.5 h-1.5 rounded-full bg-monokai-comment/70"></span>
        </div>

        <div class="p-4 h-full flex flex-col">
          <h2 class="text-lg font-bold text-monokai-pink flex items-center gap-2">
            <span class="mdi mdi-text-box-outline"></span>
            Logs du scan
          </h2>
          <div class="mt-3 bg-monokai-bg border border-monokai-comment rounded flex-1 min-h-0 overflow-auto">
            <pre class="text-xs text-monokai-text font-mono p-3 whitespace-pre-wrap">{{ logs.length ? logs.join('\n') : 'Aucun log pour le moment.' }}</pre>
          </div>
          <button
            v-if="logs.length > 0"
            @click="clearLogs"
            class="mt-2 px-3 py-1 rounded text-xs bg-monokai-comment/30 text-monokai-comment hover:bg-monokai-comment/50 transition-colors"
          >
            Effacer les logs
          </button>
        </div>
      </div>
    </div>

    <!-- Modal Paramètres -->
    <SettingsModal
      :isOpen="showSettings"
      @close="showSettings = false"
      @configReloaded="handleConfigReloaded"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import { useRouter } from 'vue-router'
import { useIPStore } from '@/stores/ipStore'
import SystemStats from '@/components/SystemStats.vue'
import SettingsModal from '@/components/SettingsModal.vue'
import axios from 'axios'

const router = useRouter()
const ipStore = useIPStore()
const showSettings = ref(false)

// --- Données ---
const services = ref([])
const selectedPorts = ref(new Set())
const results = ref([])
const isScanning = ref(false)
const scanProgress = ref({ current: 0, total: 0, ip: '' })
const logs = ref([])
const filterText = ref('')
const sortColumn = ref('ip')
const sortAsc = ref(true)

// --- Panneau droit redimensionnable ---
const rightPanelWidth = ref(384)
const minPanelWidth = 288
const maxPanelWidth = 576
let isResizing = false
let startX = 0
let startWidth = 0

// --- Computed ---
const selectedCount = computed(() => selectedPorts.value.size)

const progressPercent = computed(() => {
  if (scanProgress.value.total === 0) return 0
  return Math.round((scanProgress.value.current / scanProgress.value.total) * 100)
})

const scanTimeout = ref(1.0)

const estimatedTime = computed(() => {
  const total = scanProgress.value.total
  const remaining = total - scanProgress.value.current
  const seconds = Math.ceil(remaining * scanTimeout.value)
  if (seconds < 60) return `${seconds}s`
  const min = Math.floor(seconds / 60)
  const sec = seconds % 60
  return sec > 0 ? `${min}min ${sec}s` : `${min}min`
})

const filteredResults = computed(() => {
  let data = [...results.value]

  // Filtre texte
  if (filterText.value) {
    const search = filterText.value.toLowerCase()
    data = data.filter(r =>
      r.ip.includes(search) ||
      (r.name || '').toLowerCase().includes(search) ||
      (r.hostname || '').toLowerCase().includes(search) ||
      r.service_name.toLowerCase().includes(search) ||
      String(r.port).includes(search) ||
      (r.protocol || '').toLowerCase().includes(search)
    )
  }

  // Tri
  data.sort((a, b) => {
    let va = a[sortColumn.value]
    let vb = b[sortColumn.value]

    // Tri numérique pour IP
    if (sortColumn.value === 'ip') {
      const toNum = ip => ip.split('.').reduce((acc, oct) => acc * 256 + parseInt(oct), 0)
      va = toNum(va)
      vb = toNum(vb)
    }

    // Tri numérique pour port
    if (sortColumn.value === 'port') {
      va = Number(va)
      vb = Number(vb)
    }

    if (va < vb) return sortAsc.value ? -1 : 1
    if (va > vb) return sortAsc.value ? 1 : -1

    // Tri secondaire : par port si même IP, par IP si même colonne
    if (sortColumn.value === 'ip') return a.port - b.port
    const toNum = ip => ip.split('.').reduce((acc, oct) => acc * 256 + parseInt(oct), 0)
    return toNum(a.ip) - toNum(b.ip)
  })

  return data
})

// --- Méthodes ---
function isSelected(service) {
  return selectedPorts.value.has(service.port)
}

function toggleService(service) {
  const ports = new Set(selectedPorts.value)
  if (ports.has(service.port)) {
    ports.delete(service.port)
  } else {
    ports.add(service.port)
  }
  selectedPorts.value = ports
}

function selectAll() {
  selectedPorts.value = new Set(services.value.map(s => s.port))
}

function selectNone() {
  selectedPorts.value = new Set()
}

function sortBy(column) {
  if (sortColumn.value === column) {
    sortAsc.value = !sortAsc.value
  } else {
    sortColumn.value = column
    sortAsc.value = true
  }
}

function sortIcon(column) {
  if (sortColumn.value !== column) return ''
  return sortAsc.value ? '▲' : '▼'
}

function serviceColor(protocol) {
  if (!protocol) return 'bg-monokai-comment/30 text-monokai-comment'
  switch (protocol) {
    case 'http':
    case 'https':
      return 'bg-monokai-green/20 text-monokai-green'
    case 'ssh':
      return 'bg-monokai-cyan/20 text-monokai-cyan'
    case 'rdp':
      return 'bg-monokai-orange/20 text-monokai-orange'
    case 'smb':
    case 'ftp':
      return 'bg-monokai-yellow/20 text-monokai-yellow'
    default:
      return 'bg-monokai-purple/20 text-monokai-purple'
  }
}

async function loadServices() {
  try {
    const response = await axios.get('/api/services/list')
    services.value = response.data.services || []
  } catch (error) {
    console.error('Erreur chargement services:', error)
    addLog('Erreur chargement de la liste des services')
  }
}

function addLog(message) {
  const now = new Date().toLocaleTimeString('fr-FR')
  logs.value.push(`[${now}] ${message}`)
}

function clearLogs() {
  logs.value = []
}

async function launchScan() {
  if (selectedCount.value === 0 || isScanning.value) return

  isScanning.value = true
  results.value = []
  scanProgress.value = { current: 0, total: 0, ip: '' }

  const ports = Array.from(selectedPorts.value)
  const serviceNames = ports.map(p => {
    const svc = services.value.find(s => s.port === p)
    return svc ? svc.name : `Port ${p}`
  })
  addLog(`Scan lancé pour ${ports.length} service(s) : ${serviceNames.join(', ')}`)

  try {
    const response = await axios.post('/api/services/scan', { ports })
    if (response.data.status === 'error') {
      addLog(`Erreur : ${response.data.message}`)
      isScanning.value = false
    }
    // Les résultats arrivent via WebSocket (service_scan_complete)
  } catch (error) {
    console.error('Erreur scan services:', error)
    addLog(`Erreur : ${error.response?.data?.detail || error.message}`)
    isScanning.value = false
  }
}

// --- WebSocket : écouter la progression du scan ---
function handleWsMessage(event) {
  try {
    const data = JSON.parse(event.data)
    if (data.type === 'service_scan_progress') {
      scanProgress.value = {
        current: data.current || 0,
        total: data.total || 0,
        ip: data.ip || ''
      }
    } else if (data.type === 'service_scan_start') {
      addLog(data.message || 'Scan de services démarré')
    } else if (data.type === 'service_scan_log') {
      addLog(data.message || '')
    } else if (data.type === 'service_scan_result') {
      // Résultat individuel en temps réel
      if (data.result) {
        results.value.push(data.result)
      }
    } else if (data.type === 'service_scan_complete') {
      addLog(data.message || 'Scan de services terminé')
      // Mettre à jour avec les résultats finaux (triés)
      if (data.results) {
        results.value = data.results
      }
      isScanning.value = false
      scanProgress.value = { current: 0, total: 0, ip: '' }
    }
  } catch {
    // Message non-JSON, ignorer
  }
}

// --- Navigation ---
function goToDashboard() {
  router.push('/')
}

function openSettings() {
  showSettings.value = true
}

async function handleConfigReloaded() {
  await ipStore.fetchIPs()
  ipStore.bumpConfigReload()
  await loadServices()
}

// --- Redimensionnement panneau droit ---
function clampWidth(value) {
  return Math.max(minPanelWidth, Math.min(maxPanelWidth, value))
}

function onMouseMove(event) {
  if (!isResizing) return
  const delta = startX - event.clientX
  rightPanelWidth.value = clampWidth(startWidth + delta)
}

function stopResize() {
  if (!isResizing) return
  isResizing = false
  window.removeEventListener('mousemove', onMouseMove)
  window.removeEventListener('mouseup', stopResize)
}

function startResize(event) {
  isResizing = true
  startX = event.clientX
  startWidth = rightPanelWidth.value
  window.addEventListener('mousemove', onMouseMove)
  window.addEventListener('mouseup', stopResize)
}

// --- Lifecycle ---
onMounted(async () => {
  await loadServices()

  // Écouter les messages WebSocket pour la progression
  if (ipStore.ws) {
    ipStore.ws.addEventListener('message', handleWsMessage)
  }
})

onBeforeUnmount(() => {
  stopResize()
  if (ipStore.ws) {
    ipStore.ws.removeEventListener('message', handleWsMessage)
  }
})
</script>
