<?php

namespace App\Http\Controllers\Owner;

use App\Http\Controllers\Controller;

use Illuminate\Http\Request;

use App\Http\Helpers\ResponseBuilder;
use App\Http\Helpers\ParamsValidator;
use Illuminate\Support\Facades\DB;

class CashMovementDetail extends Controller
{
    private $oDomain;
    private static $staticDomain = "Cash Movement Detail";

    public function __construct()
    {
        $this->oDomain = "Cash Movement Detail";
    }

    public function listUpgrade(Request $Request, $Id_Invoice)
    {
        $oResponse  = array();
        // VALIDANDO DATOS
        $oResponse = ParamsValidator::Validate_Id($Id_Invoice, $this->oDomain);

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $oParam = [
                $Id_Invoice,
                config('var.PATH_PUBLIC')
            ];
            $oData  = DB::select('call sp_cash_movement_detail_invoice_upgrade_list(?,?)', $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($idCashMovement)
    {
        $oResponse  = array();

        // VALIDANDO DATOS
        $oResponse = ParamsValidator::Validate_Id($idCashMovement, $this->oDomain);
        $action = 'active';

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $oParam = [
                $idCashMovement,
                $action
            ];
            $oData  = DB::select('call sp_cash_movement_detail_list(?,?)', $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 invoiceList(Request $Request, $Id_Invoice)
    {
        $oResponse  = array();

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

        //  INGRESANDO DATOS
        if ($oResponse["Response_Code"] == 200) {
            $oParam = [
                $Id_Invoice,
                config('var.PATH_PUBLIC')
            ];
            $oData  = DB::select('call sp_cash_movement_detail_invoice_list(?,?)', $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 static function listAll(Request $Request)
    {
        $oSucces    = true;
        $oResponse  = array();
        $oValParams = array('Invoices' => 'required|string');

        // VALIDANDO DATOS
        $oResponse = ParamsValidator::Validate_Request($Request, $oValParams, self::$staticDomain);

        //  INGRESANDO DATOS

        if ($oResponse["Response_Code"] == 200) {
            $oData = self::getAll($Request->input('Invoices'));

            $oResponse["Response_Status"]           = 200;
            $oResponse["Response_Code"]             = 200;
            $oResponse["Response_Domain"]           = self::$staticDomain;
            $oResponse["Response_Message"]          = self::$staticDomain . " list All ";
            $oResponse["Response_Data"]             = $oData;
            $oResponse["Response_Error_Message"]    = "";
            $oResponse["Response_Error_Reason"]     = "";
        }

        return ResponseBuilder::Response($oResponse);
    }

    public static function getAll(string $invoiceListJSON)
    {
        $oInvoices = json_decode($invoiceListJSON);
        $oData = [];
        $value = -1;

        $invoiceDetails = [];
        for ($k = 0; $k < count($oInvoices); $k++) {
            $oParam = [
                $oInvoices[$k]->Id,
                config('var.PATH_PUBLIC')
            ];
            $oData_Temp = DB::select('call sp_cash_movement_detail_invoice_list(?,?)', $oParam);
            $invoiceDetails = array_merge($invoiceDetails, $oData_Temp);
        }

        $grouped = self::groupByIdCashMovement($invoiceDetails);
        foreach ($grouped as $group) {
            $group->CashMovementDetail_Amount = self::sumCashMovementDetailAmount(
                self::filterByIdCashMovement($invoiceDetails, $group->Id_CashMovement)
            );
            $group->CashMovement_Date_Seconds = strtotime($group->CashMovement_Date);
        }
        usort($grouped, fn ($a, $b) => $a->CashMovement_Date_Seconds - $b->CashMovement_Date_Seconds);
        return $grouped;
    }

    public static function getAllHistory(string $invoiceListJSON)
    {
        $oInvoices = json_decode($invoiceListJSON);
        $oData = [];
        $value = -1;

        $invoiceDetails = [];
        for ($k = 0; $k < count($oInvoices); $k++) {
            $oParam = [
                $oInvoices[$k]->Id
            ];
            $oData_Temp = DB::select('call sp_cash_movement_detail_invoice_list_history(?)', $oParam);
            $invoiceDetails = array_merge($invoiceDetails, $oData_Temp);
        }

        $grouped = self::groupByIdCashMovement($invoiceDetails);
        foreach ($grouped as $group) {
            $group->CashMovementDetail_Amount = self::sumCashMovementDetailAmount(
                self::filterByIdCashMovement($invoiceDetails, $group->Id_CashMovement)
            );
        }
        return $grouped;
    }

    public static function groupByIdCashMovement($list)
    {
        $turn = [];
        foreach ($list as $li) {
            if (!array_key_exists($li->Id_CashMovement, $turn)) {
                $turn[$li->Id_CashMovement] = $li;
            }
        }
        return array_values($turn);
    }

    public static function filterByIdCashMovement($list, $id)
    {
        return array_values(array_filter($list, fn ($li) => $li->Id_CashMovement == $id));
    }

    public static function sumCashMovementDetailAmount($list)
    {
        return array_reduce($list, fn ($carry, $li) => $carry + $li->CashMovementDetail_Amount, 0);
    }
}
