<?php

namespace App\Services;

use Exception;

class CdataService
{
    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]);
    }

    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);
    }

    public function getAllOnuInformation()
    {
        $macWithVlan = collect($this->getAllMacWithVlan());
        $onuId = collect($this->geOnuId());
        $onuLaser = collect($this->getAllOnuLaserWithOnuId());
        $result = $macWithVlan->map(function ($macItem) use ($onuId, $onuLaser) {
            // Find matching o  nuId record by clientId
            $matchingOnuId = $onuId->first(function ($onuIdItem) use ($macItem) {
                // dd($onuIdItem, $macItem);
                return $onuIdItem['clientId'] === $macItem['clientId'];
            });

            if (!$matchingOnuId) {
                return null;
            }

            // Find matching laser record by onuId
            $matchingLaser = $onuLaser->first(function ($laserItem) use ($matchingOnuId) {
                // dd($laserItem, $matchingOnuId);
                return $laserItem['onuId'] === $matchingOnuId['onuId'];
            });

            return [
                'macAddress' => $macItem['macAddress'],
                'onuId' => $matchingOnuId['onuId'],
                'vLan' => $macItem['vlan'],
                'onuLaser' => $matchingLaser['onuLaser'] / 100 ?? null
            ];
        })->filter()->values()->toArray();

        return $result;
    }

    private function getAllMacWithVlan()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['vlanMac']);
        $splitted = explode("\n", $rawResult);
        return collect($splitted)->map(function ($row) {
            $macParts = explode("=", $row);
            $clientId = trim($macParts[0] ?? '');
            preg_match('/\.(\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+)$/', $clientId, $matches);
            $clientId = $matches[1] ?? null;
            $vlan = trim($macParts[0] ?? '');
            preg_match('/\.(\d+)$/', $vlan, $matches);
            $vlan = $matches[1] ?? null;
            $macString = trim($macParts[1] ?? '');
            preg_match('/Hex-STRING:\s+([0-9A-F ]+)/i', $macString, $matches);
            $macAddress = isset($matches[1]) ? str_replace(" ", ":", trim($matches[1])) : null;
            return [
                'clientId' => $clientId,
                'macAddress' => $macAddress,
                'vlan' => $vlan
            ];
        })->toArray();
    }

    private function geOnuId()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['onuId']);
        $splitted = explode("\n", $rawResult);
        return collect($splitted)->map(function ($row) {
            $onuIdParts = explode("=", $row);
            $clientId = trim($onuIdParts[0] ?? '');
            preg_match('/\.(\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+)$/', $clientId, $matches);
            $clientId = $matches[1] ?? null;
            $onuId = trim($onuIdParts[1] ?? '');
            preg_match('/Gauge32:\s*(\d+)/', $onuId, $matches);
            $onuId = $matches[1] ?? null;
            return [
                'clientId' => $clientId,
                'onuId' => $onuId
            ];
        })->toArray();
    }

    private function getAllOnuLaserWithOnuId()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['onuLaser']);
        $splitted = explode("\n", $rawResult);
        return collect($splitted)->map(function ($row) {
            $onuLaserParts = explode("=", $row);
            $onuId = trim($onuLaserParts[0] ?? '');
            preg_match('/\.(\d+)\.0\.0$/', $onuId, $matches);
            $onuId = $matches[1] ?? null;
            $onuLaser = trim($onuLaserParts[1] ?? '');
            preg_match('/INTEGER:\s*(-?\d+)/', $onuLaser, $matches);
            $onuLaser = $matches[1] ?? null;
            return [
                'onuId' => $onuId,
                'onuLaser' => $onuLaser
            ];
        })->toArray();
    }
}