<?php

namespace App\Http\Controllers\Owner;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Http\Helpers\ResponseBuilder;
use App\Http\Helpers\ParamsValidator;
use App\Http\History\HistoryData;
use App\Http\History\HistoryTables;
use App\Modules\Group\Application\Create\CreateGroupQuery;
use App\Modules\Shared\Domain\Bus\Query\QueryBus;
use DateTime;
use Illuminate\Support\Facades\DB;

class c_Flight extends Controller
{
    private $oDomain;
    /** @var HistoryData */
    private $history;
    /** @var HistoryData */
    private $historyGroup;

    public function __construct(
        private QueryBus $queryBus
    ) {
        $this->oDomain = "Flight";
        $this->history = new HistoryData(HistoryTables::FLIGHT);
        $this->historyGroup = new HistoryData(HistoryTables::GROUP);
    }

    public static function findBooking($Id_Flight)
    {
        $found = DB::select('CALL `sp_flight_index`(?)', [$Id_Flight]);
        return count($found) ? $found[0]->Id_Booking : null;
    }

    public function Insert(Request $Request)
    {
        $oResponse  = array();
        $oValParams = array(
            'Flight_DateDeparture' => 'required|string',
            'Flight_DateArrival' => 'required|string',
            'Flight_Origin' => 'string|max:100',
            'Flight_Destination' => 'string|max:100',
            'Flight_Number' => 'string|max:20',
            'Flight_Carrier' => 'string|max:100',
            'Flight_Observation' => 'string',
            'Flight_Type' => 'required|int',
            'Id_Booking' => 'required|int',
            'Group_Origin' => 'required|string|max:250',
            'Group_Destination' => 'required|string|max:250'
        );

        // VALIDANDO DATOS
        $oResponse = ParamsValidator::Validate_Request($Request, $oValParams, $this->oDomain);

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $departure = new DateTime($Request->input("Flight_DateDeparture") . ':00');
            $arrival = new DateTime($Request->input("Flight_DateArrival") . ':00');
            $oParam = array(
                $departure->format('Y-m-d H:i:s'),
                $arrival->format('Y-m-d H:i:s'),
                Str::upper($Request->input("Flight_Origin")),
                Str::upper($Request->input("Flight_Destination")),
                Str::upper($Request->input("Flight_Number")),
                Str::upper($Request->input("Flight_Carrier")),
                $Request->input("Flight_Observation"),
                $Request->input("Flight_Type"),
                $Request->input("Id_Booking")
            );
            $oData = DB::select('call sp_flight_insert(?,?,?,?,?,?,?,?,?)', $oParam);

            //  RESPONSE
            if ($oData[0]->Response_Success == 1) {
                $this->history->insert(
                    $Request->all(),
                    $Request,
                    $Request->input('Id_Booking')
                );

                //region SETEA FECHAS
                $Departure_Date     = $departure->format('Y-m-d');
                $Departure_Hour     = $departure->format('H:i:s');
                $Arrival_Date       = $arrival->format('Y-m-d');
                $Arrival_Hour       = $arrival->format('H:i:s');
                //endregion

                //region SETEANDO VALORES PARA GRUPO
                $Group_DateStart    = $Request->input("Flight_Type") == 1 ? $Arrival_Date : $Departure_Date;
                $Group_Hour         = $Request->input("Flight_Type") == 1 ? $Arrival_Hour : $Departure_Hour;
                $Group_Type         = 1;
                $Group_Remark       = $Request->input("Flight_Observation");
                $Group_ServiceType  = $Request->input("Flight_Type") == 1 ? 3 : 4;
                $Id_Service         = $oData[0]->Response_Id;
                //endregion

                //region AGREGA GRUPO
                $oParam = [
                    'Group_DateStart' => $Group_DateStart,
                    'Group_Hour' => $Group_Hour,
                    'Group_Origin' => Str::upper($Request->input("Group_Origin")),
                    'Group_Destination' => Str::upper($Request->input("Group_Destination")),
                    'Group_Type' => $Group_Type,
                    'Group_Remark' => $Group_Remark,
                    'Group_ServiceType' => $Group_ServiceType,
                    'Id_Service' => $Id_Service
                ];

                $this->queryBus->ask(new CreateGroupQuery(...array_values($oParam)));
                $this->historyGroup->insert($oParam, $Request);
                //endregion
            }

            $oResponse["Response_Status"]           = $oData[0]->Response_Status;
            $oResponse["Response_Code"]             = $oData[0]->Response_Code;
            $oResponse["Response_Domain"]           = $this->oDomain;
            $oResponse["Response_Message"]          = $oData[0]->Response_Message;
            $oResponse["Response_Data"]             = null;
            $oResponse["Response_Error_Message"]    = $oData[0]->Response_Message;
            $oResponse["Response_Error_Reason"]     = $oData[0]->Response_Reason;
        }

        return ResponseBuilder::Response($oResponse);
    }

    public function Update(Request $Request)
    {
        $oResponse  = array();
        $oValParams = array(
            'Id_Flight'                 => 'required|int',
            'Flight_DateDeparture'      => 'required|string',
            'Flight_DateArrival'        => 'required|string',
            'Flight_Origin'             => 'string|max:100',
            'Flight_Destination'        => 'string|max:100',
            'Flight_Number'             => 'string|max:20',
            'Flight_Carrier'            => 'string|max:100',
            'Flight_Observation'        => 'string',
            'Flight_Type'               => 'required|int',
            'Id_Booking'                => 'required|int',
            'Group_Origin'              => 'required|string|max:250',
            'Group_Destination'         => 'required|string|max:250'
        );

        // VALIDANDO DATOS
        $oResponse = ParamsValidator::Validate_Request($Request, $oValParams, $this->oDomain);

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $this->history->obtainOld($Request->input("Id_Flight"));

            $oParam = array(
                $Request->input("Id_Flight"),
                $Request->input("Flight_DateDeparture") . ':00',
                $Request->input("Flight_DateArrival") . ':00',
                Str::upper($Request->input("Flight_Origin")),
                Str::upper($Request->input("Flight_Destination")),
                Str::upper($Request->input("Flight_Number")),
                Str::upper($Request->input("Flight_Carrier")),
                $Request->input("Flight_Observation"),
                $Request->input("Flight_Type"),
                $Request->input("Id_Booking")
            );
            $oData = DB::select('call sp_flight_update(?,?,?,?,?,?,?,?,?,?)', $oParam);

            //  RESPONSE
            if ($oData[0]->Response_Success == 1) {
                $this->history->update(
                    $Request->input("Id_Booking"),
                    $this->history->oldValue,
                    [$Request->all()],
                    $Request
                );

                $oParam     = array($Request->input("Id_Flight"));
                $oData      = DB::select('call sp_flight_group_index(?)', $oParam);

                if (count($oData) > 0) {

                    $Id_Group   = $oData[0]->Id_Group;
                    $this->historyGroup->obtainOld($Id_Group);

                    //region SETEA FECHAS
                    $Departure_Date     = date("Y-m-d", strtotime($Request->input("Flight_DateDeparture") . ':00'));
                    $Departure_Hour     = date("H:i:s", strtotime($Request->input("Flight_DateDeparture") . ':00'));
                    $Arrival_Date       = date("Y-m-d", strtotime($Request->input("Flight_DateArrival") . ':00'));
                    $Arrival_Hour       = date("H:i:s", strtotime($Request->input("Flight_DateArrival") . ':00'));
                    //endregion

                    //region SETEANDO VALORES PARA GRUPO
                    $Group_DateStart    = $Request->input("Flight_Type") == 1 ? $Arrival_Date : $Departure_Date;
                    $Group_Hour         = $Request->input("Flight_Type") == 1 ? $Arrival_Hour : $Departure_Hour;
                    $Group_Type         = 1;
                    $Group_Remark       = $Request->input("Flight_Observation");
                    $Group_ServiceType  = $Request->input("Flight_Type") == 1 ? 3 : 4;
                    $Id_Service         = $Request->input("Id_Flight");
                    //endregion

                    //region AGREGA GRUPO
                    $oParam = array(
                        $Id_Group,
                        $Group_DateStart,
                        $Group_Hour,
                        Str::upper($Request->input("Group_Origin")),
                        Str::upper($Request->input("Group_Destination")),
                        $Group_Type,
                        $Group_Remark,
                        $Group_ServiceType,
                        $Id_Service
                    );

                    $oData = DB::select('call sp_group_update_flight(?,?,?,?,?,?,?,?,?)', $oParam);

                    $this->historyGroup->update(
                        $Id_Group,
                        $this->historyGroup->oldValue,
                        [
                            'Id_Group' => $Id_Group,
                            'Group_DateStart' => $Group_DateStart,
                            'Group_Hour' => $Group_Hour,
                            'Request' => $Request->input("Group_Origin"),
                            'Request' => $Request->input("Group_Destination"),
                            'Group_Type' => $Group_Type,
                            'Id_Service' => $Id_Service
                        ],
                        $Request
                    );
                    //endregion
                }
            } else {
            }

            $oResponse["Response_Status"]           = $oData[0]->Response_Status;
            $oResponse["Response_Code"]             = $oData[0]->Response_Code;
            $oResponse["Response_Domain"]           = $this->oDomain;
            $oResponse["Response_Message"]          = $oData[0]->Response_Message;
            $oResponse["Response_Data"]             = null;
            $oResponse["Response_Error_Message"]    = $oData[0]->Response_Message;
            $oResponse["Response_Error_Reason"]     = $oData[0]->Response_Reason;
        }

        return ResponseBuilder::Response($oResponse);
    }

    public function Delete(Request $Request, $Id)
    {
        $oResponse  = array();

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

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $this->history->obtainOld($Id);

            $oParam = array($Id);
            $IdBooking = $this->findBooking($Id);
            $oData  = DB::select('call sp_flight_delete(?)', $oParam);

            //  RESPONSE
            if ($oData[0]->Response_Success == 1) {
                $this->history->delete(
                    $IdBooking,
                    $this->history->oldValue,
                    $Request
                );

                $oParam     = array($Id);
                $oData      = DB::select('call sp_flight_group_index(?)', $oParam);

                if (count($oData) > 0) {
                    $Id_Group   = $oData[0]->Id_Group;
                    $this->historyGroup->obtainOld($Id_Group);

                    $oParam     = array($Id_Group);
                    $oData      = DB::select('call sp_group_delete(?)', $oParam);

                    $this->historyGroup->delete(
                        $Id_Group,
                        $this->historyGroup->oldValue,
                        $Request
                    );
                }
            } else {
            }

            $oResponse["Response_Status"]           = $oData[0]->Response_Status;
            $oResponse["Response_Code"]             = $oData[0]->Response_Code;
            $oResponse["Response_Domain"]           = $this->oDomain;
            $oResponse["Response_Message"]          = $oData[0]->Response_Message;
            $oResponse["Response_Data"]             = null;
            $oResponse["Response_Error_Message"]    = $oData[0]->Response_Message;
            $oResponse["Response_Error_Reason"]     = $oData[0]->Response_Reason;
        }

        return ResponseBuilder::Response($oResponse);
    }

    public function Index(Request $Request, $Id)
    {
        $oResponse  = array();

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

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $oParam = array($Id);
            $oData  = DB::select('call sp_flight_index(?)', $oParam);

            $oResponse["Response_Status"]           = 200;
            $oResponse["Response_Code"]             = 200;
            $oResponse["Response_Domain"]           = $this->oDomain;
            $oResponse["Response_Message"]          = $this->oDomain . " Index";
            $oResponse["Response_Data"]             = $oData;
            $oResponse["Response_Error_Message"]    = "";
            $oResponse["Response_Error_Reason"]     = "";
        }

        return ResponseBuilder::Response($oResponse);
    }

    public function List(Request $Request, $Id_Booking)
    {
        $oResponse  = array();

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

        if ($oResponse["Response_Code"] == 200) {
            $oParam = [$Id_Booking];
            $oData  = DB::select('call sp_flight_list(?)', $oParam);

            $oResponse["Response_Status"]           = 200;
            $oResponse["Response_Code"]             = 200;
            $oResponse["Response_Domain"]           = $this->oDomain;
            $oResponse["Response_Message"]          = $this->oDomain . ' list ' . $Id_Booking;
            $oResponse["Response_Data"]             = $oData;
            $oResponse["Response_Error_Message"]    = "";
            $oResponse["Response_Error_Reason"]     = "";
        }

        return ResponseBuilder::Response($oResponse);
    }
}
