import { ref } from 'vue'
import { HUB_URL } from 'src/config/hub'

const THRESHOLDS = {
  meshSignal: { critical: 60, warning: 80 },
  clientSignal: { critical: 50, warning: 70 },
  packetLoss: { critical: 10, warning: 5 },
  backhaulUtil: 80,
  cpu: 80,
  preferred2gChannels: [1, 6, 11],
}

const cache = new Map()
const CACHE_TTL = 120_000

const loading = ref(false)
const error = ref(null)
const data = ref(null)

async function fetchDiagnostic(ip, pass, user = 'superadmin') {
  if (!ip || !pass) { error.value = 'IP et mot de passe requis'; return null }

  const cached = cache.get(ip)
  if (cached && (Date.now() - cached.ts) < CACHE_TTL) {
    data.value = cached.data
    return cached.data
  }

  loading.value = true
  error.value = null

  try {
    const params = new URLSearchParams({ ip, user, pass })
    const res = await fetch(`${HUB_URL}/modem/diagnostic?${params}`)
    const json = await res.json()

    if (!res.ok || json.error) throw new Error(json.error || `HTTP ${res.status}`)

    const processed = processDiagnostic(json)
    cache.set(ip, { data: processed, ts: Date.now() })
    data.value = processed
    return processed
  } catch (e) {
    error.value = e.message
    return null
  } finally {
    loading.value = false
  }
}

/**
 * Auto-fetch diagnostic by serial number — credentials resolved server-side from ERPNext.
 * No password required from the user.
 */
async function fetchDiagnosticAuto(serial) {
  if (!serial) { error.value = 'Numero de serie requis'; return null }

  const cached = cache.get(`auto:${serial}`)
  if (cached && (Date.now() - cached.ts) < CACHE_TTL) {
    data.value = cached.data
    return cached.data
  }

  loading.value = true
  error.value = null

  try {
    const res = await fetch(`${HUB_URL}/modem/diagnostic/auto?serial=${encodeURIComponent(serial)}`)
    const json = await res.json()

    if (!res.ok || json.error) throw new Error(json.error || `HTTP ${res.status}`)

    const processed = processDiagnostic(json)
    cache.set(`auto:${serial}`, { data: processed, ts: Date.now() })
    data.value = processed
    return processed
  } catch (e) {
    error.value = e.message
    return null
  } finally {
    loading.value = false
  }
}

/**
 * Process unified diagnostic data from backend.
 * Backend normalizes both TP-Link and Raisecom into the same shape.
 * Frontend adds client-side issue detection on top.
 */
function processDiagnostic(raw) {
  const issues = [...(raw.issues || [])]

  const online = raw.online || null
  const wanIPs = raw.wanIPs || []
  const radios = raw.radios || []
  const meshNodes = raw.meshNodes || []
  const wifiClients = raw.wifiClients || []
  const ethernetPorts = raw.ethernetPorts || []
  const dhcpLeases = raw.dhcpLeases || []
  const wiredEquipment = raw.wiredEquipment || []
  const device = raw.device || null
  const gpon = raw.gpon || null

  // Client-side issue detection
  checkMeshIssues(meshNodes, issues)
  checkClientIssues(wifiClients, meshNodes, issues)
  checkRadioIssues(radios, issues)

  const severityOrder = { critical: 0, warning: 1, info: 2 }
  issues.sort((a, b) => (severityOrder[a.severity] ?? 9) - (severityOrder[b.severity] ?? 9))

  return {
    fetchedAt: raw.fetchedAt, durationMs: raw.durationMs, modemType: raw.modemType,
    issues, meshNodes, wifiClients, radios, wanIPs, online,
    ethernetPorts, dhcpLeases, wiredEquipment, device, gpon,
  }
}

function checkMeshIssues(meshNodes, issues) {
  for (const node of meshNodes) {
    if (!node.isController && node.active && node.backhaul?.type === 'Wi-Fi') {
      const sig = node.backhaul.signal
      const name = node.hostname
      if (sig < THRESHOLDS.meshSignal.critical) {
        issues.push({
          severity: 'critical',
          message: `${name}: signal mesh tres faible (${sig})`,
          detail: `Le noeud "${name}" a un signal de backhaul de ${sig}/255. Lien a ${node.backhaul.linkRate} Mbps.`,
          action: `Rapprocher le noeud "${name}" du routeur principal ou ajouter un noeud intermediaire.`,
        })
      } else if (sig < THRESHOLDS.meshSignal.warning) {
        issues.push({
          severity: 'warning',
          message: `${name}: signal mesh faible (${sig})`,
          detail: `Backhaul a ${node.backhaul.linkRate} Mbps, utilisation ${node.backhaul.utilization}%.`,
          action: `Envisager de rapprocher "${name}" du routeur pour ameliorer la vitesse.`,
        })
      }
      if (node.backhaul.utilization > THRESHOLDS.backhaulUtil) {
        issues.push({
          severity: 'warning',
          message: `${name}: backhaul sature (${node.backhaul.utilization}%)`,
          detail: `Le lien entre "${name}" et le routeur est utilise a ${node.backhaul.utilization}%.`,
          action: `Reduire le nombre d'appareils sur ce noeud ou connecter "${name}" en Ethernet.`,
        })
      }
    }
    if (node.cpu > THRESHOLDS.cpu) {
      issues.push({
        severity: 'warning',
        message: `${node.hostname}: CPU eleve (${node.cpu}%)`,
        detail: `Le processeur du noeud est a ${node.cpu}% d'utilisation.`,
        action: `Redemarrer le noeud "${node.hostname}" si le probleme persiste.`,
      })
    }
  }
}

function checkClientIssues(wifiClients, meshNodes, issues) {
  for (const c of wifiClients) {
    if (!c.active) continue
    const label = c.hostname || c.mac
    if (c.signal > 0 && c.signal < THRESHOLDS.clientSignal.critical) {
      issues.push({
        severity: 'critical',
        message: `${label}: signal tres faible (${c.signal}/255)`,
        detail: `Appareil "${label}" sur ${c.band || '?'}, lien ${Math.round((c.linkDown || 0) / 1000)} Mbps.`,
        action: `Rapprocher l'appareil du noeud mesh le plus proche ou verifier les obstacles.`,
      })
    } else if (c.signal > 0 && c.signal < THRESHOLDS.clientSignal.warning) {
      issues.push({
        severity: 'warning',
        message: `${label}: signal faible (${c.signal}/255)`,
        detail: `Vitesse reduite a ${Math.round((c.linkDown || 0) / 1000)} Mbps.`,
        action: `Verifier le placement de l'appareil par rapport au noeud "${c.meshNode || 'principal'}".`,
      })
    }
    if (c.lossPercent > THRESHOLDS.packetLoss.critical) {
      issues.push({
        severity: 'critical',
        message: `${label}: ${c.lossPercent}% perte de paquets`,
        detail: `Retransmissions detectees.`,
        action: `Interference probable. Verifier le canal WiFi, les appareils voisins, ou changer la bande.`,
      })
    } else if (c.lossPercent > THRESHOLDS.packetLoss.warning) {
      issues.push({
        severity: 'warning',
        message: `${label}: ${c.lossPercent}% perte de paquets`,
        detail: `Performance reduite.`,
        action: `Envisager de changer de canal ou rapprocher l'appareil.`,
      })
    }
  }
}

function checkRadioIssues(radios, issues) {
  for (const r of radios) {
    if (r.band === '2.4GHz' && !r.autoChannel && r.channel > 0
      && THRESHOLDS.preferred2gChannels.indexOf(r.channel) === -1) {
      issues.push({
        severity: 'warning',
        message: `Canal 2.4GHz non optimal (${r.channel})`,
        detail: `Le canal ${r.channel} chevauche les canaux voisins. Les canaux 1, 6 ou 11 sont recommandes.`,
        action: `Changer le canal 2.4GHz a 1, 6 ou 11, ou activer le canal automatique.`,
      })
    }
  }
}

export function useModemDiagnostic() {
  return { fetchDiagnostic, fetchDiagnosticAuto, loading, error, data }
}

// Keep backward-compatible export
export function useWifiDiagnostic() {
  return { fetchDiagnostic, fetchDiagnosticAuto, loading, error, data }
}
