<?php

namespace App\Console\Commands\Report;

use App\Helpers\ClickhouseHandler;
use App\Interfaces\AkvoradoRepositoryInterface;
use App\Repositories\AkvoradoRepository;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;

class ReportAttackCarpetEnrichThread extends \App\Console\Commands\BaseCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'report-attack:carpet-enrich-thread {--pool=} {--thread=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Correlates carpet bombs against Akvorado data and builds an enriched object.';

    /**
     * Reserve an akvorado interface
     */

    private AkvoradoRepositoryInterface $akv;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->akv = new AkvoradoRepository();
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {

        // Get list of relevant attack records
        $chh_reporting = new ClickhouseHandler(
            config('creatia.reporting.db'),
            config('creatia.reporting.host'),
            config('creatia.reporting.port'),
            config('creatia.reporting.user'),
            config('creatia.reporting.pass'),
            null,
            false
        );

        $pool       = $this->option('pool');
        $thread     = $this->option('thread');

        // Select the relevant carpet attacks - We'll then need to segregate these out by attacks clearly over, and attacks potentially ongoing.
        $carpet_attacks = collect($chh_reporting->selectUnpaged("
        SELECT
            id,
            destination_parent,
            MIN(start_at) as start_at,
            MAX(finish_at) as finish_at
        FROM (
            SELECT
                report_carpet.carpet_id AS id,
                start_at::int as start_at,
                finish_at::int as finish_at,
                report_carpet.destination_parent as destination_parent
            FROM
                report_carpet
            LEFT JOIN
                report_carpet_singular ON report_carpet.carpet_id = report_carpet_singular.carpet_id
            LEFT JOIN
                report_singular ON report_singular.singular_id = report_carpet_singular.singular_id
            WHERE (
                finish_at > :from AND finish_at < :to
                AND (report_carpet.carpet_id % $pool) = $thread
                AND report_carpet.carpet_id NOT IN (SELECT carpet_id FROM report_carpet_complete)
            )
        )
        GROUP BY id, destination_parent
        ORDER BY id DESC", [
            'from' => Carbon::now()->subMinutes(1440)->timestamp,
            'to' => Carbon::now()->subMinutes(10)->timestamp
        ])->get());

        $info_lookup = collect([]);

        foreach(array_chunk($carpet_attacks->pluck('id')->toArray(), 2500) as $chunk) {
            $info_lookup = $info_lookup->merge(collect($chh_reporting->selectUnpaged("SELECT
                carpet_id,
                start_at::int as start_at,
                finish_at::int as finish_at,
                destination_parent
                FROM
                    report_carpet_info
                LEFT JOIN
                    report_carpet ON report_carpet.carpet_id = report_carpet_info.carpet_id
                WHERE
                    carpet_id IN (:carpet)
            ", [ 'carpet' => $chunk ])->get()));
        }

        $info_lookup = $info_lookup->keyBy('destination_parent');

        $now = Carbon::now()->timestamp;

        foreach($carpet_attacks as $attack) {

            // Check whether attack is ongoing
            $ongoing = $attack['finish_at'] > ($now - 300);

            // Whether the attack is long
            $long = ($attack['finish_at'] - $attack['start_at'] > 3600);

            // Select an appropriate last window
            $last_window = $attack['start_at'];

            $specific_lookup = false;

            if(isset($info_lookup[$attack['destination_parent']])) {

                $specific_lookup = collect($info_lookup[$attack['destination_parent']]);

                $last_window = max($specific_lookup->pluck('finish_at')->toArray());

                if($last_window === null) {
                    $last_window = $specific_lookup['finish_at'];
                }
            }

            // Vars to pass into query
            $vars = [];

            // If it's ongoing, been more than an hour AND been more than an hour since last window...
            // Collect the last 50 minutes worth of data - Otherwise we can just wait
            if($ongoing && $long) {
                $hour_since = (Carbon::now()->timestamp - $last_window) > 3600;

                // Can collect if it's been an hour since...
                if($hour_since) {
                    \Log::debug("We've had an hour long collection event for carpets. Yay!");
                    \Log::debug(json_encode($attack));

                    $vars = [
                        $last_window == $attack['start_at'] ? ($last_window - 120) : $last_window, // Select two minutes before if first
                        $last_window + 3000,
                        $attack['destination_parent']
                    ];
                }
            }
            elseif(!$ongoing) { // Not ongoing
                $vars = [
                    $long ? $last_window : ($last_window - 120), // Select two minutes before if it'll be the first in the series
                    $attack['finish_at'] + 120,
                    $attack['destination_parent']
                ];
            }

            // We need to check whether the window is actually stored as well...
            if($specific_lookup && $specific_lookup->where('start_at', '=', $vars[0])->where('finish_at', '=', $vars[1])) {
                // Skipping
            }
            else {
                try {
                    Http::timeout(300)->withBasicAuth('creatia', config('creatia.reporting.microservice_password'))->withHeaders(['Content-Type' => 'application/json'])->post(config('creatia.reporting.microservice_url') . '/creatia-report/enrich-carpet', [ 
                        'attacks' => [[ 'id' => (int)$attack['id'], 'address' => str_replace('::ffff:', '', $vars[2]) . '/24', 'start' => $vars[0], 'end' => $vars[1] ]]
                    ]);
                }
                catch(\Exception $ex) {
                    \Log::debug("Error enriching carpet report");
                    \Log::debug($ex);
                }
            }
        }

        return 0;
    }
}