<?php

namespace App\Http\Controllers\Owner\Provider;

use App\Http\Controllers\Controller;
use App\Http\Helpers\ParamsValidator;
use App\Http\Helpers\ResponseBuilder;
use App\Modules\Shared\Validator\Infraestructure\LaravelValidator;
use App\Providers\ProvidersReview\ProvidersReviewListReport\ProvidersReviewListReport;
use App\Providers\ProvidersReview\ProvidersReviewSingleReport\ProvidersReviewSingleReport;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ProviderListReviewScoreReportListGeneralController extends Controller
{
    private $oDomain;

    public function __construct()
    {
        $this->oDomain = "Provider";
    }

    public function __invoke(Request $Request, $Id)
    {
        $validations = [
            'DateStart' => 'required|string|date',
            'DateEnd' => 'required|string|date',
        ];
        (new LaravelValidator())->validate($Request->all(), $this->oDomain, $validations);

        $oResponse = ParamsValidator::Validate_Id($Id, $this->oDomain);

        $page = 1;
        $pageSize = 1000;
        $dateStart = $Request->input('DateStart') . ' 00:00:00';
        $dateEnd = $Request->input('DateEnd') . ' 23:59:59';
        $search = $Request->input('Search', '');
        $idProvider = $Request->input('IdProvider', 0);

        $providerList = DB::select('CALL sp_provider_list_review_score(?,?,?,?,?)', [$Id, $idProvider, $page, $pageSize, $search]);

        if (empty($providerList)) {
            $oResponse["Response_Status"] = 200;
            $oResponse["Response_Code"] = 200;
            $oResponse["Response_Data"] = [];
            $oResponse["Response_Count"] = 0;
            return ResponseBuilder::Response($oResponse);
        }

        $providerIds = implode(',', array_map(fn($p) => $p->Id_Provider, $providerList));

        $externalReviewScore = DB::select('CALL sp_internal_provider_external_review_score_monthly(?,?,?,@sts,@cod,@msg)', [
            $providerIds, $dateStart, $dateEnd
        ]);
        $passengerReviewScore = DB::select('CALL sp_internal_provider_passenger_review_score_monthly(?,?,?,@sts,@cod,@msg)', [
            $providerIds, $dateStart, $dateEnd
        ]);
        $groupData = DB::select('CALL sp_internal_provider_group_passenger_count_monthly(?,?,?,@sts,@cod,@msg)', [
            $providerIds, $dateStart, $dateEnd
        ]);

        $mergedProviders = $this->indexProvider($providerList, $externalReviewScore, $passengerReviewScore, $groupData);

        $groupedByType = $this->groupByTypeProvider($mergedProviders);

        if ($idProvider == 0) {
            (new ProvidersReviewListReport())->exportToExcel($groupedByType);
        } else {
            (new ProvidersReviewSingleReport())->exportToExcel($groupedByType);
        }
    }

    private function indexProvider($providerListScore, $externalReviewScore, $passengerReviewScore, $groupData)
    {
        $map = [];

        // Agrupamos los datos por Id_Provider
        $externalMap = collect($externalReviewScore)->groupBy('Id_Provider');
        $passengerMap = collect($passengerReviewScore)->groupBy('Id_Provider');
        $groupMap = collect($groupData)->groupBy('Id_Provider');

        foreach ($providerListScore as $provider) {
            $id = $provider->Id_Provider;

            // Obtenemos los meses de cada tipo de revisión, decodificando JSON de manera segura
            $externalMonths = !empty($externalMap[$id][0]->Months)
                ? json_decode($externalMap[$id][0]->Months, true, 512, JSON_INVALID_UTF8_IGNORE)
                : [];

            $passengerMonths = !empty($passengerMap[$id][0]->Months)
                ? json_decode($passengerMap[$id][0]->Months, true, 512, JSON_INVALID_UTF8_IGNORE)
                : [];

            $groupMonths = !empty($groupMap[$id][0]->Months)
                ? json_decode($groupMap[$id][0]->Months, true, 512, JSON_INVALID_UTF8_IGNORE)
                : [];

            $months = [];

            // Creamos la lista de todos los meses únicos
            $allMonths = [];

            foreach ($externalMonths as $m) {
                if (!empty($m['Month'])) $allMonths[$m['Month']] = true;
            }
            foreach ($passengerMonths as $m) {
                if (!empty($m['Month'])) $allMonths[$m['Month']] = true;
            }
            foreach ($groupMonths as $m) {
                if (!empty($m['Month'])) $allMonths[$m['Month']] = true;
            }

            $allMonths = array_keys($allMonths);

            // Inicializamos la estructura de cada mes
            foreach ($allMonths as $monthKey) {
                $months[$monthKey] = [
                    'Month' => $monthKey,
                    'RISum' => 0,
                    'Groups' => 0,
                    'Paxs' => 0,
                    'RI' => [5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0],
                    'TA' => [5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0],
                ];
            }

            // Sumamos los valores de PassengerReview
            foreach ($passengerMonths as $m) {
                $month = $m['Month'] ?? null;
                if ($month && isset($m['PassengerReview_Score'])) {
                    $score = (int)$m['PassengerReview_Score'];
                    $amount = $m['Amount'] ?? 0;
                    if (in_array($score, [1, 2, 3, 4, 5])) {
                        $months[$month]['RI'][$score] += $amount;
                        $months[$month]['RISum'] += $amount;
                    } else if ($score == 0) {
                        $months[$month]['RISum'] += $amount;
                    }
                }
            }

            // Sumamos los valores de ExternalReview
            foreach ($externalMonths as $m) {
                $month = $m['Month'] ?? null;
                if ($month && isset($m['ExternalReview_Score'])) {
                    $score = (int)$m['ExternalReview_Score'];
                    $amount = $m['Amount'] ?? 0;
                    if (in_array($score, [1, 2, 3, 4, 5])) {
                        $months[$month]['TA'][$score] += $amount;
                    }
                }
            }

            // Sumamos los grupos
            foreach ($groupMonths as $m) {
                $month = $m['Month'] ?? null;
                if ($month) {
                    $months[$month]['Groups'] += $m['Group_Amount'] ?? 0;
                    $months[$month]['Paxs'] += $m['GroupPassenger_Amount'] ?? 0;
                }
            }

            ksort($months); // Ordenamos los meses por clave
            $provider->Months = array_values($months); // Convertimos a array indexado
            $provider->Total_Pax = array_sum(array_column($provider->Months, 'Paxs'));

            // Totales
            $provider->Total_RI = 0;
            $provider->Total_TA = 0;

            $provider->Total_RI_percentage = 0;
            $provider->Total_SRI_percentage = 0;
            $provider->Total_TA_percentage = 0;
            $provider->Total_STA_percentage = 0;

            $provider->Total_Satisfaction_percentage = 0;
            $provider->Total_Logro_percentage = 0;

            // Arrays dinámicos para RI y TA del 1 al 5
            $provider->Total_RI_Scores = array_fill(1, 5, 0);
            $provider->Total_TA_Scores = array_fill(1, 5, 0);

            // Recorrer meses y sumar
            foreach ($provider->Months as $month) {

                $ri = $month['RI'];
                $ta = $month['TA'];

                foreach ($ri as $s => $amt) {
                    $provider->Total_RI_Scores[$s] += $amt;
                }
                $provider->Total_RI += array_sum($ri);

                foreach ($ta as $s => $amt) {
                    $provider->Total_TA_Scores[$s] += $amt;
                }
                $provider->Total_TA += array_sum($ta);
            }


            // Cálculos finales
            $provider->Total_RI_percentage = $provider->Total_Pax > 0 ? ($provider->Total_RI * 100) / $provider->Total_Pax : 0;

            $provider->Total_SRI_percentage = $provider->Total_RI > 0 ? ($provider->Total_RI_Scores[5] * 100) / $provider->Total_RI : 0;

            $provider->Total_TA_percentage = $provider->Total_Pax > 0 ? ($provider->Total_TA * 100) / $provider->Total_Pax : 0;

            $provider->Total_STA_percentage = $provider->Total_TA > 0 ? ($provider->Total_TA_Scores[5] * 100) / $provider->Total_TA : 0;

            // Final global scores
            $provider->Total_Satisfaction_percentage =
                ($provider->Total_SRI_percentage * 70 + $provider->Total_STA_percentage * 30) / 100;

            $provider->Total_Logro_percentage =
                ($provider->Total_RI_percentage * 70 + $provider->Total_TA_percentage * 30) / 100;

            $map[] = $provider;
        }

        return $map;
    }

    private function groupByTypeProvider($providers)
    {
        $grouped = [];
        foreach ($providers as $provider) {
            $type = $provider->TypeProvider_Name ?? 'Unknown';
            if (!isset($grouped[$type])) {
                $grouped[$type] = [
                    "Id_TypeProvider" => $provider->Id_TypeProvider ?? null,
                    "TypeProvider_Name" => $provider->TypeProvider_Name ?? $type,
                    "Providers" => []
                ];
            }

            $objProvider = clone $provider;

            $grouped[$type]["Providers"][] = $objProvider;

        }

        return array_values($grouped);
    }

}
