<?php

namespace App\Console\Commands;

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

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

        if(checkAPI()){
            $activeClients = mikrotikOnlineAndOfflineUsers();
            $usersByMac = collect($activeClients['allOnlineUsersWithoutMap'])->keyBy("caller-id");
        }else{
            $activeClients = DB::table('radacct')
                ->select('username', 'callingstationid')
                ->where('acctstoptime', null)
                ->get();
            $usersByMac = $activeClients->keyBy('callingstationid');
        }


        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
                        );
                    }
                }elseif($manager->olt_company == 'Cdata'){
                    $snmpManager = new CdataService(
                        $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, $manager);
                }

                $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, $manager)
    {
        try {
            if($manager->olt_company == 'BDCom'){
                $onu['macAddress'] = strtoupper(implode(':', str_split($onu['macAddress'], 2)));
            }
            $onuInfo = OltOnuInformation::firstOrNew(
                [
                    'mac' => $onu['macAddress'],
                ]
            );

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

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

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

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

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