<?php

namespace App\Services;

use Exception;

class VsolManager2
{
    private $host;
    private $communityString;
    private $port;
    private $objectIdentities;

    public function __construct($host, $communityString, $objectIdentities, $port = 161)
    {
        $this->host = $host;
        $this->communityString = $communityString;
        $this->port = $port;
        $this->objectIdentities = $objectIdentities;
    }

    public function getOltName()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['oltName']);
        return $this->parseValueFromRawString(explode("\n", $rawResult)[0]);
    }

    public function getAllOnuInformation()
{
    $macWithVlan = collect($this->getAllMacWithVlan())->keyBy('onuId');
    $interfaceWithOnuId = collect($this->getInterfaceNameWithOnuId())->keyBy('onuId');
    $onuLaserWithOnuId = collect($this->getAllOnuLaserWithOnuId())->keyBy('onuId');

    return $interfaceWithOnuId->map(function ($interfaceItem, $onuId) use ($macWithVlan, $onuLaserWithOnuId) {
        $interfaceName = $interfaceItem['interfaceName'] ?? '';

        // Extract "pon:onu" like "2:36" from interfaceName e.g. "PON2:ONU36"
        if (preg_match('/PON(\d+):ONU(\d+)/', $interfaceName, $matches)) {
            $compositeId = $matches[1] . ':' . $matches[2]; // e.g., "2:36"
            $laserData = $compositeId ? $onuLaserWithOnuId->get($compositeId, []) : [];
        } else {
            $laserData = $onuLaserWithOnuId->get($interfaceName, []);
        }

        $macItem = $macWithVlan->get($onuId, []);

        return array_merge(
            ['onuId' => $onuId],
            $interfaceItem,
            $macItem,
            $laserData
        );
    })->toArray();
}


    private function parseValueFromRawString($rawString)
    {
        preg_match('/:\s(.+)$/', $rawString, $matches);
        return $matches[1] ?? null;
    }

    private function runCommandByOid($oid)
    {
        $snmpCommand = "snmpwalk -v 2c -c {$this->communityString} {$this->host}:{$this->port} $oid";
        exec($snmpCommand, $output, $returnVar);

        if ($returnVar !== 0) {
            throw new Exception("SNMP command failed");
        }

        return implode("\n", $output);
    }

    private function getAllMacWithVlan()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['vlanMac']);
        $splitted = explode("\n", $rawResult);

        return collect($splitted)->map(function ($row) {
            $macParts = explode("=", $row);
            $oid = trim($macParts[0]);
            $macString = trim($macParts[1]);

            $oidParts = explode(".", $oid);
            $lastNumber = end($oidParts);

            preg_match('/STRING:\s+"([0-9A-Fa-f:]+)"/', $macString, $stringMatches);
            $macAddress = isset($stringMatches[1]) ? str_replace(" ", ":", trim($stringMatches[1])) : null;

            $vLan = $this->extractVlanFromOid($row, $this->objectIdentities['vlanMac']);

            return [
                'onuId' => $lastNumber,
                'macAddress' => $macAddress,
                'vLan' => $vLan,
            ];
        })->toArray();
    }

    private function getInterfaceNameWithOnuId()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['onuInterfaceName']);
        $splitted = explode("\n", $rawResult);

        return collect($splitted)->map(function ($row) {
            preg_match('/\.(\d+) = STRING: "([^"]+)"/', $row, $matches);
            preg_match('/PON\d+:(\d+:\d+)/', $matches[2] ?? '', $laserMatches);

            return [
                'interfaceName' => $matches[2] ?? null,
                'onuId' => $matches[1] ?? null,
                // 'laserID' => $laserMatches[1] ?? null, // Extract laserID (e.g., "2:26")
            ];
        })->toArray();
    }

    private function getAllOnuLaserWithOnuId()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['onuLaser']);
        $splitted = explode("\n", $rawResult);
        // dd($splitted);

        return collect($splitted)->map(function ($row) {
            // Match the format: ".<onuId>.<subId> = STRING: "<laserValue>"
            preg_match('/\.(\d+\.\d+) = STRING: "(-?\d+\.\d+)"/', $row, $matches);

            return [
                'onuLaser' => $matches[2] ?? null, // Laser value
                'onuId' => isset($matches[1]) ? str_replace('.', ':', $matches[1]) : null, // Normalize ONU ID
            ];
        })->filter(function ($item) {
            // Ensure both onuLaser and onuId are not null
            return !is_null($item['onuLaser']) && !is_null($item['onuId']);
        })->toArray();
    }

    private function extractVlanFromOid($row, $baseOid)
    {
        return explode('.', str_replace($baseOid, '', $row))[1] ?? null;
    }
}
