<?php

namespace App\Console\Commands;

use App\Models\OltInfo;
use App\Services\SnmpManager;
use App\Services\VsolManager;
use App\Services\VsolManager2;
use Illuminate\Console\Command;
use Symfony\Component\Yaml\Yaml;
use App\Models\OltOnuInformation;

class ProcessSnmpManagers extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'snmp:process';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Process SNMP managers and update ONU information in the database.';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $oltInfoRecords = OltInfo::all();

        if (!$oltInfoRecords) {
            $this->error("Configuration Data not found: $oltInfoRecords");
            return Command::FAILURE;
        }

        $activeClients = mikrotikOnlineAndOfflineUsers();
        $usersByMac = collect($activeClients['allOnlineUsersWithoutMap'])->keyBy("caller-id");

        try {
            $config = $oltInfoRecords;

            foreach ($config as $manager) {
                $this->info("Processing SNMP Manager: {$manager->olt_address}");

                $oids = [
                    'oltName' => $manager->olt_name,
                    'vlanMac' => $manager->vlan_mac,
                    'onuId' => $manager->onu_id,
                    'onuInterfaceName' => $manager->onu_interface_name,
                    'onuLaser' => $manager->onu_laser,
                ];

                if($manager->olt_company == 'Vsol'){
                    if($manager->olt_type == 'Epon'){
                        $snmpManager = new VsolManager(
                            $manager->olt_address,
                            $manager->community,
                            $oids,
                            $manager->port
                        );
                    }else{
                        $snmpManager = new VsolManager2(
                            $manager->olt_address,
                            $manager->community,
                            $oids,
                            $manager->port
                        );
                    }
                }else{
                    $snmpManager = new SnmpManager(
                        $manager->olt_address,
                        $manager->community,
                        $oids,
                        $manager->port
                    );
                }

                $oltName = $snmpManager->getOltName();
                $onuData = $snmpManager->getAllOnuInformation();

                foreach ($onuData as $onu) {
                    $this->updateDatabase($manager->olt_address, $oltName, $onu, $usersByMac);
                }

                $this->info("Successfully processed SNMP Manager: {$manager->olt_address}");
            }
        } catch (\Exception $e) {
            $this->error("Error processing SNMP managers: {$e->getMessage()}");
            return Command::FAILURE;
        }

        return Command::SUCCESS;
    }

    private function updateDatabase($oltAddress, $oltName, $onu, $usersByMac)
    {
        try {
            $onuInfo = OltOnuInformation::firstOrNew(
                [
                    'mac' => $onu['macAddress'],
                ]
            );

            $userExist = $usersByMac[strtoupper(implode(':', str_split($onu['macAddress'], 2)))] ?? null;

            if(!$userExist){
                $userExist = $usersByMac[$onu['macAddress']] ?? null;
            }

            if ($userExist) {
                $onuInfo->username = $userExist["name"];
            }

            $onuInfo->fill([
                'oltaddress' => $oltAddress,
                'onuid' => $onu['onuId'],
                'Vlan' => $onu['vLan'],
                'interface' => $onu['interfaceName'],
                'laser' => $onu['onuLaser'],
                'oltName' => $oltName,
                'username' => $userExist ? $userExist["name"] : null
            ]);

            $onuInfo->save();
        } catch (\Exception $e) {
            $this->error("Error updating database for ONU ID: {$onu['onuId']}, Error: {$e->getMessage()}");
        }
    }
}
