<?php

namespace App\Services;

use Exception;

class EcomService
{
    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) {
            if (!isset($macItem['clientId'])) {
                return null;
            }

            $matchingOnuId = $onuId->firstWhere('clientId', $macItem['clientId']);
            $matchingLaser = $onuLaser->firstWhere('clientId', $macItem['clientId']);

            if (!$matchingOnuId || !isset($matchingOnuId['onuId'])) {
                return null;
            }

            return [
                'macAddress' => $macItem['macAddress'] ?? null,
                'onuId' => $matchingOnuId['onuId'],
                'onuLaser' => isset($matchingLaser['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);
            // Client Id Part
            $clientId = trim($macParts[1] ?? '');
            preg_match('/Gauge32:\s*(\d+)/', $clientId, $matches);
            $clientId = $matches[1] ?? null;
            // Mac Part
            $clientMacPart = trim($macParts[0] ?? '');
            preg_match('/\.((?:\d+\.)+\d+)$/', $clientMacPart, $matches);
            $fullIndex = $matches[1] ?? null;
            $parts = explode('.', $fullIndex);
            $mac = '';
            foreach ($parts as $index => $part) {
                if ($index == 14 || $index == 15 || $index == 16 || $index == 17 || $index == 18 || $index == 19) {
                    $mac .= $part. '.';
                }
            }
            // Convert decimal MAC parts to hex
            $macParts = explode('.', $mac);
            $macAddress = implode(':', array_slice(array_map(function($part) {
                return sprintf('%02X', intval($part)); // Convert string to integer before hex conversion
            }, $macParts), 0, 6)); // Only take first 6 parts for MAC address

            return [
                'clientId' => $clientId,
                'macAddress' => $macAddress,
            ];
        })->toArray();
    }

    private function geOnuId()
    {
        $rawResult = $this->runCommandByOid($this->objectIdentities['onuId']);
        $splitted = explode("\n", $rawResult);
        // dd($splitted);
        return collect($splitted)->map(function ($row) {
            $onuIdParts = explode("=", $row);
            $clientId = trim($onuIdParts[0] ?? '');
            preg_match('/\.(\d+)$/', $clientId, $matches);
            $clientId = $matches[1] ?? null;
            $onuId = trim($onuIdParts[1] ?? '');
            preg_match('/"([^"]+)"/', $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);
            $clientId = trim($onuLaserParts[0] ?? '');
            preg_match('/\.(\d{8})\.\d+\.\d+$/', $clientId, $matches);
            $clientId = $matches[1] ?? null;

            $onuLaser = trim($onuLaserParts[1] ?? '');
            preg_match('/INTEGER:\s*(-\d+)/', $onuLaser, $matches);
            $onuLaser = $matches[1] ?? null;
            return [
                'clientId' => $clientId,
                'onuLaser' => $onuLaser
            ];
        })->toArray();
    }
}
