<?php

namespace App\Console\Commands\Report;

use App\Models\Organisation;
use App\Models\PendingReport;
use App\Models\PendingReportStatus;
use App\Models\PendingReportType;
use App\Models\Webhook;
use App\Repositories\ReportRepository;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class ReportPendSingularThread extends \App\Console\Commands\BaseCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'report-pend:singular-thread {--as-max=} {--as-mod=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Thread to queue up the report for the notification pipeline...';

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

    public function iterateOverOrganisations($_as_max, $_as_mod, $_rr, $_potential_reports, $_validator)
    {
        $rr = $_rr;

        // We need to segregate things based upon ASN to keep things memory friendly and parameter size friendly
        Organisation::where(DB::raw('organisations.id % ' . $_as_max), '=', $_as_mod)->join('report_organisation_attributes', 'organisation_id', '=', 'organisations.id')->select(
            'organisations.id',
            'minimum_threshold_gbps',
            'minimum_threshold_mpps',
            'send_individual'
        )->where('send_individual', '=', 1)->whereIn('organisations.id', Webhook::select('organisation_id')->get()->pluck('organisation_id'))->each(function($organisation) use($rr, $_potential_reports, $_validator) {

            $potential_report_refs = $_potential_reports($rr, $organisation->id);

            if(sizeof($potential_report_refs['data']) === 0) {
                return 0;
            }

            // Select things we've had set to pending so we can keep track of them...
            $known_reports = PendingReport::where([
                ['organisation_id', '=', $organisation->id],
                ['created_at', '>', Carbon::now()->subDays(7)]
            ])->get()->keyBy('report_id');

            foreach($potential_report_refs['data'] as $x) {

                $xid = $x['report_id'];

                if(isset($known_reports[$xid])) {
                    continue;   
                }

                if($x['gbps'] >= ($organisation->minimum_threshold_gbps ?? 3)) {

                    $report_data = $_validator($rr, $xid, $organisation->id);
    
                    if($report_data !== false && $report_data['valid'] && $x['ready'] == 1 && $x['gbps'] >= ($organisation->minimum_threshold_gbps ?? 3)) {

                        $this->log_event("Creating a pending report.", [
                            'organisation' => $organisation->id,
                            'id' => $xid,
                            'report' => $report_data
                        ]);

                        (new PendingReport([
                            'organisation_id'   => $organisation->id,
                            'destination'       => $report_data['destination'],
                            'started_at'        => Carbon::parse($report_data['start']),
                            'finished_at'       => Carbon::parse($report_data['finish']),
                            'status'            => $organisation->send_individual ? PendingReportStatus::Pending : PendingReportStatus::NotForSend,
                            'report_type'       => PendingReportType::Singular,
                            'report_id'         => $xid
                        ]))->save();
                    }
                }
            }
        });
    }

    public function getPotentialReports($_rr, $_organisation_id)
    {

        $rows_to_return = [];

        $redis_entry = Redis::get("report-singular-$_organisation_id-list");

        if($redis_entry !== null) {
            foreach(json_decode($redis_entry, true)['data'] as $row) {

                if(Carbon::parse($row['finish_at'])->timestamp > Carbon::now()->subMinutes(30)->timestamp) {
                    $rows_to_return[] = $row;
                }
            }
        }

        return [
            'data' => $rows_to_return
        ];

    }

    public function validateReport($_rr, $_report_id, $_organisation_id)
    {
        return $_rr->validate_report_singular($_report_id);
    }

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

        $rr = new ReportRepository();

        $this->iterateOverOrganisations($this->option('as-max'), $this->option('as-mod'), $rr, fn($a, $b) => $this->getPotentialReports($a, $b), fn($a, $b, $c) => $this->validateReport($a, $b, $c));

        return 0;
    }
}