'use strict'
const { log, json, parseBody, erpRequest } = require('./helpers')
const { broadcast } = require('./sse')
// Oktopus auto-provision was a "best effort" extra step on /on-scan; with the
// stack gone we leave the rest of the provision flow (ERPNext sync,
// equipment swap, etc.) intact and just no-op the oktopus calls. Any caller
// that still expects oktopus_provisioned will see the action recorded as
// "oktopus_skipped" instead.
const OKTOPUS_DISABLED = process.env.OKTOPUS_DISABLED !== '0'
let oktopus = null
if (!OKTOPUS_DISABLED) {
  try { oktopus = require('./oktopus') } catch (e) { log('Oktopus module not loaded:', e.message) }
}

async function handle (req, res, method, path) {
  try {
    const action = path.replace('/provision/', '').split('/').filter(Boolean)[0]

    if (action === 'pre-authorize' && method === 'POST') {
      const body = await parseBody(req)
      const { gpon_serial, olt_ip, frame, slot, port, ont_id, equipment_name } = body
      const vlans = body.vlans || {}
      if (!gpon_serial || !olt_ip || frame === undefined || slot === undefined || port === undefined) {
        return json(res, 400, { error: 'Missing required fields: gpon_serial, olt_ip, frame, slot, port' })
      }

      const vlanCmd = (vlan, gemport) => vlan
        ? `service-port auto vlan ${vlan} gemport ${gemport} gpon ${frame}/${slot}/${port} ont ${ont_id} transparent`
        : `# no vlan for gemport ${gemport}`
      const commands = [
        `# OLT: ${olt_ip} — Pre-authorize ONT`,
        `interface gpon ${frame}/${slot}`,
        `ont add ${port} sn-auth "${gpon_serial}" omci ont-lineprofile-id ${body.line_profile || 10} ont-srvprofile-id ${body.service_profile || 10} desc "pre-auth-${equipment_name || 'unknown'}"`,
        `ont confirm ${port} ont ${ont_id}`,
        `quit`,
        `# Service ports (VLANs)`,
        vlanCmd(vlans.internet, 1), vlanCmd(vlans.manage, 2), vlanCmd(vlans.telephone, 3), vlanCmd(vlans.tv, 4),
      ]

      if (equipment_name) {
        try { await erpRequest('PUT', `/api/resource/Service Equipment/${encodeURIComponent(equipment_name)}`, { gpon_serial, status: 'Actif' }) }
        catch (e) { log('ERPNext update error:', e.message) }
      }

      log(`[provision] Pre-authorize ${gpon_serial} on ${olt_ip} ${frame}/${slot}/${port} ONT:${ont_id}`)
      return json(res, 200, { status: 'commands_generated', gpon_serial, olt_ip, port: `${frame}/${slot}/${port}`, ont_id, commands, note: 'Execute via n8n SSH node or manual SSH to OLT' })
    }

    if (action === 'on-scan' && method === 'POST') {
      const body = await parseBody(req)
      const { serial, equipment_name, service_location } = body
      if (!serial) return json(res, 400, { error: 'Missing serial' })

      const result = { serial, actions: [] }

      if (equipment_name) {
        try {
          await erpRequest('PUT', `/api/resource/Service Equipment/${encodeURIComponent(equipment_name)}`, { serial_number: serial, mac_address: body.mac || null, status: 'Actif' })
          result.actions.push({ action: 'equipment_updated', equipment_name, serial })
        } catch (e) { result.actions.push({ action: 'equipment_update_failed', error: e.message }) }
      }

      if (service_location && (body.equipment_type === 'ONT' || serial.startsWith('TPLG') || serial.startsWith('RCMG'))) {
        try {
          const locRes = await erpRequest('GET', `/api/resource/Service Location/${encodeURIComponent(service_location)}?fields=["olt_ip","olt_port","ont_id","vlan_internet","vlan_manage","vlan_telephone","vlan_tv"]`)
          const loc = locRes.data || {}
          if (loc.olt_ip && loc.olt_port) {
            const m = (loc.olt_port || '').match(/(\d+)\/(\d+)\/(\d+)/)
            if (m) {
              result.olt_pre_auth = { gpon_serial: serial, olt_ip: loc.olt_ip, frame: +m[1], slot: +m[2], port: +m[3], ont_id: loc.ont_id || 0, vlans: { internet: loc.vlan_internet, manage: loc.vlan_manage, telephone: loc.vlan_telephone, tv: loc.vlan_tv } }
              result.actions.push({ action: 'olt_pre_auth_ready', message: 'OLT commands generated, send to n8n for SSH execution' })
            }
          }
        } catch (e) { result.actions.push({ action: 'location_lookup_failed', error: e.message }) }
      }

      if (oktopus && body.mac && (body.equipment_type === 'ONT' || serial.startsWith('TPLG') || serial.startsWith('RCMG'))) {
        try {
          const oktRes = await oktopus.provisionDevice({
            mac: body.mac,
            serial,
            service_location: body.service_location,
            equipment_name: body.equipment_name,
            customer: body.customer,
          })
          result.oktopus = oktRes
          result.actions.push(...(oktRes.actions || []))
        } catch (e) {
          result.actions.push({ action: 'oktopus_provision_failed', error: e.message })
        }
      }

      if (body.customer) broadcast('customer:' + body.customer, 'equipment-scanned', { serial, equipment_type: body.equipment_type, job: body.job_name })
      log(`[provision] Scan: ${serial} → ${result.actions.length} actions`)
      return json(res, 200, result)
    }

    if (action === 'swap' && method === 'POST') {
      const body = await parseBody(req)
      const { old_equipment_name, new_serial, equipment_type, customer, service_location } = body
      const swapType = body.swap_type || 'permanent'
      if (!old_equipment_name || !new_serial) return json(res, 400, { error: 'Missing old_equipment_name and new_serial' })

      const result = { old_equipment: old_equipment_name, new_serial, swap_type: swapType, actions: [] }
      const oldStatus = { permanent: 'Défectueux', diagnostic: 'En diagnostic', upgrade: 'Retourné' }[swapType] || 'Défectueux'

      let oldEquip = {}
      try {
        const r = await erpRequest('GET', `/api/resource/Service Equipment/${encodeURIComponent(old_equipment_name)}`)
        oldEquip = r.data?.data || r.data || {}
      } catch { return json(res, 404, { error: 'Old equipment not found: ' + old_equipment_name }) }

      try {
        await erpRequest('PUT', `/api/resource/Service Equipment/${encodeURIComponent(old_equipment_name)}`, {
          status: oldStatus,
          notes: `${oldEquip.notes || ''}\n[${new Date().toISOString()}] ${swapType === 'diagnostic' ? 'Swap diagnostic' : 'Remplacé'} par ${new_serial}. Raison: ${body.reason || swapType}`.trim(),
        })
        result.actions.push({ action: 'old_status_updated', name: old_equipment_name, status: oldStatus })
      } catch (e) { result.actions.push({ action: 'status_update_failed', error: e.message }) }

      const newName = 'EQ-SWAP-' + new_serial.substring(0, 10).replace(/[^A-Za-z0-9]/g, '')
      try {
        await erpRequest('POST', '/api/resource/Service Equipment', {
          name: newName, equipment_type: equipment_type || oldEquip.equipment_type,
          serial_number: new_serial, mac_address: body.new_mac || null,
          brand: oldEquip.brand, model: oldEquip.model,
          customer: customer || oldEquip.customer, service_location: service_location || oldEquip.service_location,
          subscription: oldEquip.subscription, status: 'Actif', ownership: 'Gigafibre',
          wifi_ssid: oldEquip.wifi_ssid, wifi_password: oldEquip.wifi_password,
          sip_username: oldEquip.sip_username, sip_password: oldEquip.sip_password,
          fibre_line_profile: oldEquip.fibre_line_profile, fibre_service_profile: oldEquip.fibre_service_profile,
          parent_device: oldEquip.parent_device,
          notes: `Remplacement de ${old_equipment_name} (${oldEquip.serial_number || 'N/A'}). Raison: ${body.reason || 'défectueux'}`,
        })
        result.actions.push({ action: 'new_equipment_created', name: newName, serial: new_serial })
      } catch (e) { result.actions.push({ action: 'create_new_failed', error: e.message }) }

      if ((equipment_type || oldEquip.equipment_type) === 'ONT' && (service_location || oldEquip.service_location)) {
        try {
          const locRes = await erpRequest('GET', `/api/resource/Service Location/${encodeURIComponent(service_location || oldEquip.service_location)}?fields=["olt_ip","olt_port","ont_id","vlan_internet","vlan_manage","vlan_telephone","vlan_tv"]`)
          const loc = locRes.data || {}
          const m = (loc.olt_port || '').match(/(\d+)\/(\d+)\/(\d+)/)
          if (loc.olt_ip && m) {
            result.olt_swap_commands = [
              `# OLT: ${loc.olt_ip} — Swap ONT on ${m[0]}`,
              `interface gpon ${m[1]}/${m[2]}`,
              `ont delete ${m[3]} ${loc.ont_id || 0}`,
              `ont add ${m[3]} sn-auth "${new_serial}" omci ont-lineprofile-id ${oldEquip.fibre_line_profile || 10} ont-srvprofile-id ${oldEquip.fibre_service_profile || 10} desc "swap-${newName}"`,
              `ont confirm ${m[3]} ont ${loc.ont_id || 0}`, `quit`,
              loc.vlan_internet ? `service-port auto vlan ${loc.vlan_internet} gemport 1 gpon ${m[1]}/${m[2]}/${m[3]} ont ${loc.ont_id || 0} transparent` : '',
              loc.vlan_manage ? `service-port auto vlan ${loc.vlan_manage} gemport 2 gpon ${m[1]}/${m[2]}/${m[3]} ont ${loc.ont_id || 0} transparent` : '',
            ].filter(Boolean)
            result.actions.push({ action: 'olt_swap_commands_ready', message: 'Execute via n8n SSH node' })
          }
        } catch (e) { result.actions.push({ action: 'olt_swap_lookup_failed', error: e.message }) }
      }

      if (customer || oldEquip.customer) {
        broadcast('customer:' + (customer || oldEquip.customer), 'equipment-swapped', { old: old_equipment_name, new_serial, reason: body.reason })
      }
      log(`[provision] Swap: ${old_equipment_name} → ${new_serial} (${result.actions.length} actions)`)
      return json(res, 200, result)
    }

    if (action === 'equipment' && method === 'GET') {
      const serial = decodeURIComponent(path.replace('/provision/', '').split('/').filter(Boolean)[1] || '')
      if (!serial) return json(res, 400, { error: 'Missing serial' })
      try {
        const r = await erpRequest('GET', `/api/resource/Service Equipment?filters=[["serial_number","=","${serial}"]]&fields=["name","serial_number","mac_address","wifi_ssid","wifi_password","sip_username","sip_password","fibre_line_profile","fibre_service_profile","customer","service_location","equipment_type"]&limit_page_length=1`)
        const equips = r.data || []
        if (!equips.length) return json(res, 404, { error: 'Equipment not found for serial: ' + serial })
        return json(res, 200, equips[0])
      } catch (e) { return json(res, 502, { error: 'ERPNext lookup failed: ' + e.message }) }
    }

    return json(res, 400, { error: 'Unknown provision endpoint: ' + action })
  } catch (e) {
    log('Provisioning error:', e.message)
    return json(res, 500, { error: 'Provisioning error: ' + e.message })
  }
}

module.exports = { handle }
