<?php

namespace App\Console\Commands\Utility;

use App\Console\Commands\BaseCommand;
use Illuminate\Support\Facades\DB;

use App\Models\Prefixes;

use App\Models\Asns;

use App\Helpers\Utility\UtilPrefix;
use App\Models\Organisation;

class AuditPrefixOwnership extends BaseCommand
{
    protected $signature = 'audit:prefix-ownership';

    protected $description = 'Audit the ownership of prefixes and determine whether the owner of a prefix SHOULD be the owner of a given prefix. This is limited in that we can only do this using announced prefixes.';

    public function handle()
    {

        // Get a list of prefixes that belong to a given ASN - We're essentially creating an ASN to prefix dictionary...
        $asn_organisation_lookup = Asns::select('asn', 'organisation_id')->get()->keyBy('asn');        
        $organisation_prefix_list = [];
        $dubious_prefixes = [];
        $asn_unlisted = [];
        $organisation_lookup = Organisation::select('id', 'name')->get()->keyBy('id');

        foreach(UtilPrefix::get_detailed() as $announced_prefix) {

            if(!isset($asn_organisation_lookup["$announced_prefix->asn_originator"])) {
                $asn_unlisted[] = $announced_prefix->asn_originator;
                continue;
            }

            $organisation_id = $asn_organisation_lookup["$announced_prefix->asn_originator"]->organisation_id;

            if(isset($organisation_prefix_list[$organisation_id])) {
                $organisation_prefix_list[$organisation_id][] = $announced_prefix->prefix;
            }
            else {
                $organisation_prefix_list[$organisation_id] = [ $announced_prefix->prefix ];
            }

        }

        foreach($organisation_prefix_list as $organisation_id => $prefix) {

            $x = Prefixes::where([[DB::raw('CONCAT(address, \'/\', mask)::cidr'), '<<', $prefix], ['organisation_id', '!=', $organisation_id]])->select(
                DB::raw('CONCAT(address, \'/\', mask)::cidr AS prefix'),
                'organisation_id'
            )->get();

            foreach($x as $y) {
                if(isset($dubious_prefixes[$organisation_lookup[$y->organisation_id]->name])) {
                    $dubious_prefixes['Dubiously owned by ' . $organisation_lookup[$y['organisation_id']]->name][] = $y['prefix'] . ' in supernet owned by ' . $organisation_lookup[$organisation_id]->name;
                }
                else {
                    $dubious_prefixes['Dubiously owned by ' . $organisation_lookup[$y['organisation_id']]->name] = [ $y['prefix'] . ' in supernet owned by ' . $organisation_lookup[$organisation_id]->name ];
                }
            }
        }
        
        echo "\nKeep in mind this cannot be 100% accurate - Confirm before acting. \n\n";

        dd([
            'Missing ASNs' => array_unique($asn_unlisted),
            'Dubious prefixes' => $dubious_prefixes
        ]);

        return 0;
    }
}
