/**
 * PUT /api/zabbix/hosts/[hostid] — full update of an existing Zabbix host
 *
 * If companyId is provided (or changed), rebuilds host groups / macros / tags
 * via buildHostParams (same as creation flow). Otherwise applies fields directly.
 */

import { NextRequest, NextResponse } from 'next/server';
import { ZabbixClient } from '@/lib/services/zabbix-client';
import { postgresClient } from '@/lib/services/postgres-client';
import { ZabbixHostMacro, ZabbixHostTag } from '@/lib/types/zabbix';
import {
  sanitizeHostname,
  lookupIsp,
  buildHostParams,
  discoverIcmpTemplate,
} from '@/lib/services/zabbix-wan-utils';

interface UpdateBody {
  name: string;
  ip: string;
  description?: string;
  companyId?: number | null;
  tags?: ZabbixHostTag[];
  macros?: ZabbixHostMacro[];
  rebuildFromClient?: boolean;   // if true, fully re-run buildHostParams
}

export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ hostid: string }> }
) {
  try {
    const { hostid } = await params;
    const body: UpdateBody = await request.json();
    const { name, ip, description, companyId, tags, macros, rebuildFromClient } = body;

    if (!name || !ip) {
      return NextResponse.json({ error: 'name and ip are required' }, { status: 400 });
    }

    const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
    if (!ipv4Regex.test(ip)) {
      return NextResponse.json({ error: 'Invalid IPv4 address' }, { status: 400 });
    }

    if (!process.env.ZABBIX_API_URL || !process.env.ZABBIX_API_TOKEN) {
      return NextResponse.json({ error: 'Zabbix not configured' }, { status: 500 });
    }

    const zabbix = new ZabbixClient({
      apiUrl: process.env.ZABBIX_API_URL!,
      apiToken: process.env.ZABBIX_API_TOKEN!,
    });

    if (rebuildFromClient) {
      // Full rebuild: re-resolve ISP, rebuild groups/macros/tags from scratch
      let companyName: string | undefined;
      if (companyId) {
        const res = await postgresClient.query<{ company_name: string }>(
          'SELECT company_name FROM companies WHERE id = $1 LIMIT 1',
          [companyId]
        );
        companyName = res.rows[0]?.company_name;
      }

      const ispInfo = await lookupIsp(ip);
      const globalGroupId = await zabbix.ensureHostGroup('Datto RMM Sites');
      const icmpTemplateId = await discoverIcmpTemplate(zabbix);

      const hostParams = await buildHostParams({
        siteName: name,
        wanIp: ip,
        companyId: companyId ?? undefined,
        companyName,
        ispInfo,
        source: 'manual',
        icmpTemplateId,
        globalGroupId,
        zabbix,
      });

      await zabbix['rpc']('host.update', {
        hostid,
        host: sanitizeHostname(name),
        name,
        description: description ?? hostParams.description,
        groups: hostParams.groups,
        templates: hostParams.templates,
        macros: hostParams.macros,
        tags: hostParams.tags,
      });

      // Update IP interface separately
      const existingHost = await zabbix['rpc']<Array<{ interfaces: Array<{ interfaceid: string; main: number }> }>>('host.get', {
        output: ['hostid'],
        hostids: [hostid],
        selectInterfaces: ['interfaceid', 'main', 'type'],
      });
      const mainIface = existingHost[0]?.interfaces?.find((i: any) => i.main === 1 || i.main === '1');
      if (mainIface) {
        await zabbix['rpc']('hostinterface.update', {
          interfaceid: mainIface.interfaceid,
          ip,
          useip: 1,
          dns: '',
        });
      }
    } else {
      // Direct update — apply exactly what was sent
      await zabbix['rpc']('host.update', {
        hostid,
        host: sanitizeHostname(name),
        name,
        ...(description !== undefined ? { description } : {}),
        ...(tags !== undefined ? { tags } : {}),
        ...(macros !== undefined ? { macros } : {}),
      });

      // Update IP interface
      const existingHost = await zabbix['rpc']<Array<{ interfaces: Array<{ interfaceid: string; main: number }> }>>('host.get', {
        output: ['hostid'],
        hostids: [hostid],
        selectInterfaces: ['interfaceid', 'main', 'type'],
      });
      const mainIface = existingHost[0]?.interfaces?.find((i: any) => i.main === 1 || i.main === '1');
      if (mainIface) {
        await zabbix['rpc']('hostinterface.update', {
          interfaceid: mainIface.interfaceid,
          ip,
          useip: 1,
          dns: '',
        });
      }
    }

    return NextResponse.json({ updated: true, hostid });
  } catch (error) {
    console.error('[PUT /api/zabbix/hosts/[hostid]]', error);
    return NextResponse.json({ error: String(error) }, { status: 500 });
  }
}
