<?php

namespace App\Console\Commands\Network;

use App\Console\Commands\BaseCommand;

use Illuminate\Support\Facades\DB;
use App\Models\Asns;
use App\Models\Prefixes;
use App\Models\Goliath\GoliathAsnAttributes;
use App\Models\Goliath\GoliathOrganisationSpecial;
use App\Models\PrefixCommunity;
use Illuminate\Support\Facades\Log;
use Throwable;

class GoliathSetup extends BaseCommand
{

    protected $signature = 'goliath:setup';

    protected $description = 'Sets up goliath objects for all prefixes.';

    public function handle()
    {
        try {
            $special = GoliathOrganisationSpecial::all()->keyBy('organisation_id');

            Asns::select('id')->chunk(config('creatia.constant.chunk_large', 10), function($asn_chunk) use($special) {
                foreach($asn_chunk->pluck('id') as $asn) {
                    Prefixes::leftJoin('prefix_goliath_flags', 'prefix_goliath_flags.prefix_id', '=', 'prefixes.id')
                        ->leftJoin('prefix_goliath_inline', 'prefix_goliath_inline.prefix_id', '=', 'prefixes.id')
                        ->leftJoin('prefix_goliath_loose', 'prefix_goliath_loose.prefix_id', '=', 'prefixes.id')
                        ->select(
                            'address',
                            'prefixes.id as relevant_id',
                            'prefixes.organisation_id',
                            DB::raw('prefix_goliath_flags.id as flag_id'),
                            DB::raw('prefix_goliath_inline.id as inline_id'),
                            DB::raw('prefix_goliath_loose.id as loose_id'),
                            'setup_required',
                            'prefixes.asn_id'
                        )
                        ->where('asn_id', '=', $asn)
                        ->where('setup_required', '=', 1)
                        ->where('setup_required', '!=', 2)
                        ->chunk(config('creatia.constant.chunk_medium'), function($prefix_chunk) use($asn, $special) {

                            $goliath_defaults = GoliathAsnAttributes::where('asn_id', '=', $asn)->first() ?? collect([
                                'default_synproxy' => 0,
                                'default_chain' => null,
                                'default_inline' => 0,
                                'default_heuristics' => 3,
                                'default_loose' => 1,
                                'is_fallback' => 1
                            ]);
                            
                            $to_insert = [];
                            $to_insert_inline = [];
                            $to_insert_oah = [];

                            foreach($prefix_chunk as $prefix) {

                                if($prefix->flag_id == null) {

                                    $to_insert[] = isset($goliath_defaults['is_fallback']) ? [
                                        'prefix_id' => $prefix->relevant_id,
                                        'flag_synproxy' => 0,
                                        'flag_heuristics' => 1,
                                        'flag_heuristics_level' => 3,
                                        'flag_special' => isset($special[$prefix->organisation_id]) ? $special[$prefix->organisation_id]->special : null,
                                        'region_id' => null,
                                        'subregion_id' => null,
                                        'metro_id' => null
                                    ] : [
                                        'prefix_id' => $prefix->relevant_id,
                                        'flag_synproxy' => $goliath_defaults['default_synproxy'],
                                        'flag_heuristics' => $goliath_defaults['default_heuristics'] != 0 ? 1 : 0,
                                        'flag_heuristics_level' => $goliath_defaults['default_heuristics'],
                                        'flag_special' => isset($special[$prefix->organisation_id]) ? $special[$prefix->organisation_id]->special : null,
                                        'region_id' => null,
                                        'subregion_id' => null,
                                        'metro_id' => null
                                    ];

                                }

                                if($prefix->inline_id == null) {

                                    $to_insert_inline[] = [
                                        'prefix_id' => $prefix->relevant_id,
                                        'forced' => $goliath_defaults['default_inline']
                                    ];

                                }

                                if($prefix->loose_id == null) {

                                    $to_insert_oah[] = [
                                        'prefix_id' => $prefix->relevant_id,
                                        'loose' => $goliath_defaults['default_loose']
                                    ];
                                    
                                }

                            }

                            DB::table('prefix_goliath_flags')->insert($to_insert);
                            DB::table('prefix_goliath_inline')->insert($to_insert_inline);
                            DB::table('prefix_goliath_loose')->insert($to_insert_oah);

                            Log::debug('GOLIATH/SETUP - Flags: ' . sizeof($to_insert) . ', Inline: ' . sizeof($to_insert_inline) . ', Loose: ' . sizeof($to_insert_oah));
                        });
                    
                }
            });
        }
        catch(Throwable $ex) {
            Log::debug($ex);
        }

        return 0;
    }
}