<?php

namespace App\Console\Commands\Report;

use App\Helpers\ClickhouseHandler;
use App\Models\Goliath\ReportAwareness;
use App\Models\ReportOrganisationAttribute;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class AttackTrackCarpetCompletion extends \App\Console\Commands\BaseCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'attack-track:carpet-completion';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Thread to allow selection of all carpet reports and determine whether or not they are concluded...';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    public function getCompletedAttacks($chh) {
        return collect($chh->select("SELECT 
                s.carpet_id,
                s.destination_parent,
                s.creatia_organisation_id AS organisation_id,
                min(i.start_at) AS attack_start,
                max(i.finish_at) AS attack_finish,
                max(i.max_in_gbps) AS gbps,
                max(i.max_in_mpps) AS mpps
            FROM report_carpet s
                LEFT JOIN report_carpet_info i ON s.carpet_id = i.carpet_id
            WHERE 
                s.carpet_id NOT IN (
                    SELECT carpet_id 
                    FROM report_carpet_complete
                    WHERE carpet_id != 0
                )
                AND i.finish_at > subtractMinutes(now(), 120)
                AND now() > addMinutes(i.finish_at, 5)
                AND i.direction = 0
            GROUP BY 
                s.carpet_id,
                s.destination_parent,
                s.creatia_organisation_id
            HAVING
                countDistinct(i.type) = 9", 0, 500, []
            )->get());
    }

    public function storeCompletedAttacks($chh, $reporting, $creatia) {
        $chh->insert('report_carpet_complete', function($r) { return true; }, $reporting);

        ReportAwareness::insert($creatia);
    }

    public function iterateOverComplete($chh, $get_attacks, $store_attacks) {
        $completed_attacks = $get_attacks($chh);

        if(sizeof($completed_attacks) == 0) {
            return 0;
        }

        $to_insert = [];
        $to_insert_aware = [];

        $now = Carbon::now();

        // We also need to take a precaution whereby we do NOT reinsert awareness if we already have it - I don't know how this could happen but lets be defensive...
        $aware_of = ReportAwareness::where('type', '=', 'carpet-finish')->whereIn('report_id', $completed_attacks->pluck('carpet_id'))->get()->keyBy('report_id');
        $start_aware_of = ReportAwareness::where('type', '=', 'carpet-start')->whereIn('report_id', $completed_attacks->pluck('carpet_id'))->get()->keyBy('report_id');

        foreach($completed_attacks as $x) {

            $to_insert[] = [
                'carpet_id'         => $x['carpet_id'],
                'attack_start'      => $x['attack_start'],
                'attack_finish'     => $x['attack_finish']
            ];

            if(isset($aware_of[$x['carpet_id']])) {
                continue;
            }

            // There must be a start notification in place, otherwise we don't want to track awareness.
            if(!isset($start_aware_of[$x['carpet_id']])) {
                continue;
            }

            $to_insert_aware[] = [
                'created_at'        => $now,
                'updated_at'        => $now,
                'type'              => 'carpet-finish',
                'status'            => 'pending',
                'detected_at'       => Carbon::parse($x['attack_finish']),
                'report_id'         => $x['carpet_id'],
                'organisation_id'   => $x['organisation_id'],
                'gbps'              => $x['gbps'],
                'mpps'              => $x['mpps'],
                'address'           => ltrim($x['destination_addr'], '::ffff:')
            ];

        }

        if($to_insert !== []) {
            $store_attacks($chh, $to_insert, $to_insert_aware);
        }
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->iterateOverComplete(new ClickhouseHandler(
                config('creatia.reporting.db'),
                config('creatia.reporting.host'),
                config('creatia.reporting.port'),
                config('creatia.reporting.user'),
                config('creatia.reporting.pass'),
                null,
                false
            ),
            fn($a) => $this->getCompletedAttacks($a), 
            fn($a, $b, $c) => $this->storeCompletedAttacks($a, $b, $c)
        );

        return 0;
    }
}