<?php

namespace App\Http\Controllers\Owner\Analytic;

use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Helpers\ResponseBuilder;
use App\Modules\Shared\Validator\Infraestructure\LaravelDTOGenerator;
use App\Http\Controllers\Owner\Analytic\Dto\AnalyticAgencyListYearDTO;

use App\Modules\Analytics\Sales\Application\Reports\AnalyticAgencyReport;


class AnalyticAgencyListYearController extends Controller
{
	private $oDomain;


	public function __construct
	(
		private LaravelDTOGenerator $oLaravelDTOGenerator
	)
	{
        $this->oDomain = "Analytic Income List Year";
    }


	public function __invoke(Request $request)
    {
		//------------------------------------------------------------------------------
		//	VALIDATE
		//------------------------------------------------------------------------------
		$oDTO = $this->oLaravelDTOGenerator->generate($request->all(), $this->oDomain, AnalyticAgencyListYearDTO::class);


		//------------------------------------------------------------------------------
		//	VARIABLES
		//------------------------------------------------------------------------------
		$pDate_Year		= json_decode($oDTO->DateYear, true);
		$pDate_Month	= json_decode($oDTO->DateMonth, true);
		$pFilter		= $oDTO->Filter;	// DATE-BOOKING - DATE-TOUR
		$pExport		= $oDTO->Export;


		//------------------------------------------------------------------------------
		//	FUNCTION
		//------------------------------------------------------------------------------
		$oSubQuery = DB::query();

		$oSubQuery->from("v_booking_sales");
		$oSubQuery->selectRaw("
			Id_Invoice,
			Id_Booking,
			Id_Passenger,
			Booking_Confirm_Year,
			Booking_Confirm_Month,
			MAX(Invoice_Total) AS Amount_Invoice_Total,
			MAX(Invoice_TotalPay) AS Amount_Invoice_Paid,
			MAX(Invoice_TotalPending) AS Amount_Invoice_Pending
		");
		$oSubQuery->where("Booking_Agency", 2);

		if ($pFilter == "DATE-BOOKING")
		{
			$oSubQuery->whereIn("Booking_Confirm_Year", $pDate_Year);
			$oSubQuery->whereIn("Booking_Confirm_Month", $pDate_Month);
		}
		else if($pFilter == "DATE-TOUR")
		{
			$oSubQuery->whereIn("Booking_Start_Year", $pDate_Year);
			$oSubQuery->whereIn("Booking_Start_Month", $pDate_Month);
		}

		$oSubQuery->groupBy("Id_Invoice");

		if ($pFilter == "DATE-BOOKING")
		{
			$oSubQuery->groupBy("Booking_Confirm_Year");
			$oSubQuery->groupBy("Booking_Confirm_Month");
		}
		else if($pFilter == "DATE-TOUR")
		{
			$oSubQuery->groupBy("Booking_Start_Year");
			$oSubQuery->groupBy("Booking_Start_Month");
		}




		$oMonthQuery = DB::query();

		$oMonthQuery->fromSub($oSubQuery, "t");
		$oMonthQuery->selectRaw("
			Booking_Confirm_Year  AS Year,
			Booking_Confirm_Month AS Month,
			IFNULL(SUM(Amount_Invoice_Total), 0) AS Total_Sale,
			COUNT(DISTINCT Id_Booking) AS Total_Booking,
			COUNT(DISTINCT Id_Passenger) AS Total_Passenger
		");
		$oMonthQuery->groupBy("Booking_Confirm_Year");
		$oMonthQuery->groupBy("Booking_Confirm_Month");




		$oQuery = DB::query();

		$oQuery->fromSub($oMonthQuery, "m");
		$oQuery->selectRaw("
			fn_month_name_get(Month, 'SHORT') AS Label,
			fn_month_name_get(Month, 'SHORT') AS Title,
			Year,
			Month,
			IFNULL(Total_Sale, 0) AS Total_Sale,
			IFNULL(Total_Booking, 0) AS Total_Booking,
			IFNULL(Total_Passenger, 0) AS Total_Passenger,
			IFNULL(LAG(Total_Sale) OVER (PARTITION BY Year ORDER BY Month), 0) AS Previous_Sale,
			CASE
				WHEN IFNULL(LAG(Total_Sale) OVER (PARTITION BY Year ORDER BY Month), 0) = 0
				THEN 0
				ELSE
					(Total_Sale - LAG(Total_Sale) OVER (PARTITION BY Year ORDER BY Month) ) / LAG(Total_Sale) OVER (PARTITION BY Year ORDER BY Month )
			END AS MoM_Sale,
			CASE
				WHEN IFNULL(LAG(Total_Booking) OVER (PARTITION BY Year ORDER BY Month), 0) = 0
				THEN 0
				ELSE
					(Total_Booking - LAG(Total_Booking) OVER (PARTITION BY Year ORDER BY Month) ) / LAG(Total_Booking) OVER (PARTITION BY Year ORDER BY Month )
			END AS MoM_Booking,
			CASE
				WHEN IFNULL(LAG(Total_Passenger) OVER (PARTITION BY Year ORDER BY Month), 0) = 0
				THEN 0
				ELSE
					(Total_Passenger - LAG(Total_Passenger) OVER (PARTITION BY Year ORDER BY Month) ) / LAG(Total_Passenger) OVER (PARTITION BY Year ORDER BY Month )
			END AS MoM_Passenger
		");
		$oQuery->orderBy("Year", "DESC");
		$oQuery->orderBy("Month", "ASC");

		$oData = $oQuery->get();


		//------------------------------------------------------------------------------
		//	MAP
		//------------------------------------------------------------------------------
		$oMonths	= collect($pDate_Month);
		$oData 		= $oData->groupBy("Year")
							->map(function ($oItems, $Year) use ($oMonths)
							{
								return [
									"Year" 		=> $Year,
									"Detail"	=> $oMonths->map(function ($Month) use ($oItems)
									{
										$oRow = $oItems->firstWhere("Month", $Month);

										return [
											"Label"				=> $oRow->Label ?? "",
											"Title"				=> $oRow->Title ?? "",
											"Month"      		=> $Month,
											"Total_Sale" 		=> $oRow->Total_Sale ?? 0,
											"Total_Booking"		=> $oRow->Total_Booking ?? 0,
											"Total_Passenger"	=> $oRow->Total_Passenger ?? 0,
											"MoM_Sale"			=> $oRow->MoM_Sale ?? 0,
											"MoM_Booking"		=> $oRow->MoM_Booking ?? 0,
											"MoM_Passenger"		=> $oRow->MoM_Passenger ?? 0
										];
									})->values()
								];
							})
							->values();


		//------------------------------------------------------------------------------
		//	RESPONSE
		//------------------------------------------------------------------------------
		if ( $pExport == false )
		{
			$oResponse["Response_Status"]           = 200;
			$oResponse["Response_Code"]             = 200;
			$oResponse["Response_Domain"]           = $this->oDomain;
			$oResponse["Response_Message"]          = $this->oDomain . " List";
			$oResponse["Response_Data"]             = $oData;
			$oResponse["Response_Error_Message"]    = "";
			$oResponse["Response_Error_Reason"]     = "";

			return ResponseBuilder::Response($oResponse);
		}
		else
		{
			AnalyticAgencyReport::Report_Comparative($oData->toArray());
		}

    }


}