<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use stdClass;
use Throwable;

class InterventionController extends Controller{
    private $responseController;
    private $encryptionController;
    private $documentManagementController;
    private $functionsController;

    public function __construct(){
        $this->responseController = new ResponseController();
        $this->encryptionController = new EncryptionController();
        $this->documentManagementController = new DocumentManagementController();
        $this->functionsController = new FunctionsController();
    }

    public function storeContract(Request $request) {
        DB::enableQueryLog();

        $request['CONTRACT_COST'] = $this->encryptionController->decrypt($request->CONTRACT_COST) ? $this->encryptionController->decrypt($request->CONTRACT_COST) : 'ENC_ERR';
        $request['CONTRACT_COST'] = floatval($request->CONTRACT_COST);

        $validator = Validator::make($request->all(), [
            'id_user' => 'required|string',
            'linea' => 'required|integer',
            'CONTRACT_NAME' => 'required|string|max:100',
            'WORK_ORDER' => 'required|string',
            'CONTRACT_TYPE' => 'required|string|in:Subcontratista,Interno',
            'DENOMINATION' => 'required|string',
            'START_DATE' => 'required|date',
            'END_DATE' => 'required|date',
            'CONTRACT_COST' => 'required|numeric',
            'DOCUMENT' => 'required|json',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                TRUE,
                'ERR_CONTRATO_REG001: Uno o más errores encontrados',
                $this->responseController->makeErrors($validator->errors()->messages()),
                400
            );
        }

        $form = $request->all();
        foreach($form as $k=>$v){
            if($k == 'CONTRACT_COST' && $v == '0'){
                unset($form[$k]);
            }else if($v == '-'){
                unset($form[$k]);
            }
        }

        $idUser = $this->encryptionController->decrypt($form['id_user']);
        if(!$idUser){
            return $this->responseController->makeResponse(true, 'El ID de usuario no fue encriptado correctamente.', [], 400);
        }

        $usr = DB::table('S002V01TUSUA')->where([
            ['USUA_NULI', '=', $form['linea']],
            ['USUA_IDUS', '=', $idUser]
        ])->first();
        
        if(is_null($usr)){
            return $this->responseController->makeResponse(true, 'El usuario que realizó la petición no existe.', [], 404);
        }

        $idOrderArr = explode('-', $form['WORK_ORDER']);
        $idOrder = $this->encryptionController->decrypt($idOrderArr[0]);
        if(!$idOrder){
            return $this->responseController->makeResponse(true, 'El ID de la orden seleccionada no está encriptado correctamente.', [], 400);
        }

        $order = null;
        if($idOrderArr[1] == 'prev'){
            $order = DB::table('S002V01TOTPR')->where([
                ['OTPR_NULI', '=', $form['linea']],
                ['OTPR_IDOT', '=', $idOrder],
            ])->first();
        }else{
            //PENDIENTE MANTENIMIENTO CORRECTIVO
        }

        if(is_null($order)){
            return $this->responseController->makeResponse(true, 'La orden seleccionada no existe.', [], 404);
        }

        $workersStr = "[]";
        if($idOrderArr[1] == 'prev'){
            $workersStr = $order->OTPR_OPPR;
        }else{
            //PENDIENTE MANTENIMIENTO PREVENTIVO
        }

        $workersArr = json_decode($workersStr, true);
        $staff = [];
        foreach($workersArr as $worker){
            $type = $worker['TYPE'];
            switch($type){
                case "EM":
                    if(!in_array(intval($worker['ID']), $staff)){
                        $staff[] = intval($worker['ID']);
                    }
                break;
                case "EQ": 
                    $employees = DB::table('S002V01TPERS')->where([
                        ['PERS_NULI', '=', $form['linea']],
                        ['PERS_EQTR', '=', $worker['ID']],
                    ])->get()->all();

                    foreach($employees as $employee){
                        if(!in_array(intval($employee->PERS_IDPE), $staff)){
                            $staff[] = intval($employee->PERS_IDPE);
                        }
                    }
                break;
                case "SU":
                    $employees = DB::table('S002V01TPERS')->where([
                        ['PERS_NULI', '=', $form['linea']],
                        ['PERS_IDPS', '=', $worker['ID']],
                    ])->get()->all();

                    foreach($employees as $employee){
                        if(!in_array(intval($employee->PERS_IDPE), $staff)){
                            $staff[] = intval($employee->PERS_IDPE);
                        }
                    }
                break;
            }
        }

        $idEmployee = $this->encryptionController->decrypt($form['DENOMINATION']);
        if(!$idEmployee){
            return $this->responseController->makeResponse(true, 'El ID del empleado seleccionado no está encriptado correctamente.', [], 400);
        }else if(!in_array(intval($idEmployee), $staff)){
            return $this->responseController->makeResponse(true, 'El empleado seleccionado no está ligado a la orden de trabajo seleccionada.', [], 400);
        }

        $employee = DB::table('S002V01TPERS')->where([
            ['PERS_NULI', '=', $form['linea']],
            ['PERS_IDPE', '=', $idEmployee]
        ])->first();
        
        if(is_null($employee)){
            return $this->responseController->makeResponse(true, 'El empleado seleccionado no existe.', [], 404);
        }

        $orderType = $idOrderArr[1] == 'prev' ? 'Preventivo' : 'Correctivo';
        $contract = DB::table('S002V01TCONT')->where([
            ['CONT_NULI', '=', $form['linea']],
            ['CONT_IDEM', '=', $idEmployee],
            ['CONT_IDOT', '=', $idOrder],
            ['CONT_TOTR', '=', $orderType],
        ])->first();

        if(!is_null($contract)){
            return $this->responseController->makeResponse(true, "El empleado #$idEmployee ya tiene un contrato relacionado a la orden de trabajo $orderType #$idOrder", [], 404);
        }

        
        $docsArr = json_decode($form['DOCUMENT'], true);
        $finalDocsArr = [];
        foreach($docsArr as $doc){
            $idFileDec = $this->encryptionController->decrypt($doc['id']);
            $tempFile = DB::table('S002V01TARTE')->where([
                ['ARTE_NULI', '=', $form['linea']],
                ['ARTE_IDAR', '=', $idFileDec],
            ])->first();
    
            if(is_null($tempFile)){
                return $this->responseController->makeResponse(true, "El archivo $doc[name] no está registrado.", [], 404);
            }

            $cldo = "CO";
            $finalFile = $this->documentManagementController->moveFinalFile($form['linea'], "GPRS", $cldo, $tempFile, $idUser);
    
            if(!$finalFile[0]){
                return $this->responseController->makeResponse(true, $finalFile[1], [], 400);
            }else{
                $finalDocsArr[] = $finalFile[1];
            }
        }

        if(!isset($form['CONTRACT_COST'])){
            return $this->responseController->makeResponse(true, 'El costo del contrato no fue encriptado correctamente.', [], 400);
        }
        
        $lido = json_encode($finalDocsArr);
        $now = $this->functionsController->now();
        $nowStr = $now->toDateTimeString();
        $idContract = DB::table('S002V01TCONT')->insertGetId([
            'CONT_NULI' => $form['linea'],
            'CONT_NOCO' => $form['CONTRACT_NAME'],
            'CONT_IDEM' => $idEmployee,
            'CONT_IDOT' => $idOrder,
            'CONT_TOTR' => $orderType,
            'CONT_TIPO' => $form['CONTRACT_TYPE'],
            'CONT_FEIN' => $form['START_DATE'],
            'CONT_FEFI' => $form['END_DATE'],
            'CONT_COST' => $form['CONTRACT_COST'],
            'CONT_LIDO' => $lido,
            'CONT_USRE' => $idUser,
            'CONT_FERE' => $nowStr,
        ]);

        $actions = DB::getQueryLog();
        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
        
        $idac = $this->functionsController->registerActivity(
            $form['linea'],
            'S002V01M11GPRS',
            'S002V01F02ADCN',
            'S002V01P02RECO',
            'Registro',
            "El usuario $name (" . $usr->USUA_IDUS . ") registró el contrato #$idContract.",
            $idUser,
            $nowStr,
            'S002V01S03GEIN'
        );

        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $form['linea']);
        return $this->responseController->makeResponse(false, 'EXITO');
    }

    public function getConsultOfContracts($idUser, $line) {
        DB::enableQueryLog();

        $idUser = $this->encryptionController->decrypt($idUser);
        if(!$idUser){
            return $this->responseController->makeResponse(true, 'El ID del usuario que realizó la solicitud no está encriptado correctamente', [], 400);
        }

        $usr = DB::table('S002V01TUSUA')->where([
            ['USUA_NULI', '=', $line],
            ['USUA_IDUS', '=', $idUser],
        ])->first();

        if(is_null($usr)){
            return $this->responseController->makeResponse(true, 'El usuario que realizó la consulta no está registrado', [], 404);
        }

        $contracts = DB::table('S002V01TCONT')->select([
            'CONT_IDCO AS CONTRACT_ID',
            'CONT_NOCO AS CONTRACT_NAME',
            'CONT_IDEM AS DENOMINATION',
            'CONT_IDOT AS WORK_ORDER_ID',
            'CONT_TOTR AS WORK_ORDER_TYPE',
            'CONT_TIPO AS CONTRACT_TYPE',
            'CONT_FEIN AS START_DATE',
            'CONT_FEFI AS END_DATE',
            'CONT_COST AS CONTRACT_COST',
            'CONT_LIDO AS DOCUMENT',
            'CONT_USRE AS REGISTERED_BY',
            'CONT_FERE AS REGISTER_DATE',
            'CONT_USMO AS MODIFIED_BY',
            'CONT_FEMO AS MODIFICATION_DATE',
        ])->where('CONT_NULI', '=', $line)->get()->all();

        $now = $this->functionsController->now();
        $nowStr = $now->toDateTimeString();
        foreach($contracts as $key=>$contract){
            $contract->CONTRACT_ID = $this->encryptionController->encrypt($contract->CONTRACT_ID);
            $contract->CONTRACT_COST = $this->encryptionController->encrypt($contract->CONTRACT_COST);
            $docsArr = json_decode($contract->DOCUMENT);

            $docsFN = [];
            foreach($docsArr as $keyDoc=>$doc){
                $docIDArr = explode('=', $doc);
                $codeArr = explode('-', $docIDArr[0]);

                $file = DB::table('S002V01TAFAL')->where([
                    ['AFAL_NULI', '=', $line],
                    ['AFAL_COMO', '=', $codeArr[1]],
                    ['AFAL_CLDO', '=', $codeArr[2]],
                    ['AFAL_FECR', '=', $codeArr[3]],
                    ['AFAL_NUSE', '=', $codeArr[4]],
                    ['AFAL_NUVE', '=', $docIDArr[1]],
                ])->first();

                $docsFN[] = [
                    'id' => $this->encryptionController->encrypt($doc),
                    'name' => $doc,
                    'size' => $file->AFAL_TAMA
                ];
            }

            $contract->DOCUMENT = json_encode($docsFN);
            $usrReg = DB::table('S002V01TUSUA')->where([
                ['USUA_NULI', '=', $line],
                ['USUA_IDUS', '=', $contract->REGISTERED_BY],
            ])->first();

            $contract->REGISTERED_BY = $this->functionsController->joinName(
                $usrReg->USUA_NOMB, $usrReg->USUA_APPA, $usrReg->USUA_APMA
            ) . " (" . $contract->REGISTERED_BY . ")";

            if(!is_null($contract->MODIFIED_BY)){
                $usrMod = DB::table('S002V01TUSUA')->where([
                    ['USUA_NULI', '=', $line],
                    ['USUA_IDUS', '=', $contract->MODIFIED_BY],
                ])->first();
    
                $contract->MODIFIED_BY = $this->functionsController->joinName(
                    $usrMod->USUA_NOMB, $usrMod->USUA_APPA, $usrMod->USUA_APMA
                ) . " (" . $contract->MODIFIED_BY . ")";
            }

            $employee = DB::table('S002V01TPERS')->join('S002V01TUSUA', 'USUA_IDUS', '=', 'PERS_IDUS')->where([
                ['PERS_NULI', '=', $line],
                ['PERS_IDPE', '=', $contract->DENOMINATION],
            ])->first();

            $contract->DENOMINATION = $this->functionsController->joinName(
                $employee->USUA_NOMB, $employee->USUA_APPA, $employee->USUA_APMA
            ) . ' (' . $employee->PERS_IDPE . ') (' . $employee->PERS_IDUS . ')';

            $contract->DURATION = $this->functionsController->getDatesDifference($contract->START_DATE, $contract->END_DATE);
            $contracts[$key] = $contract;

            $endDate = new Carbon($contract->END_DATE);
            $status = $now->gt($endDate) ? 'Expirado' : 'Activo';
            $contract->STATUS = $status;
        }

        $actions = DB::getQueryLog();
        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
        
        $idac = $this->functionsController->registerActivity(
            $line,
            'S002V01M11GPRS',
            'S002V01F02ADCN',
            'S002V01P01COCO',
            'Consulta',
            "El usuario $name (" . $usr->USUA_IDUS . ") consultó los contratos registrados.",
            $idUser,
            $nowStr,
            'S002V01S03GEIN'
        );

        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $line);
        return $this->responseController->makeResponse(false, 'EXITO', $contracts);
    }

    public function getConsultOfInterventions($idUser, $line) {
        DB::enableQueryLog();

        $idUser = $this->encryptionController->decrypt($idUser);
        if(!$idUser){
            return $this->responseController->makeResponse(true, 'El ID del usuario que realizó la solicitud no está encriptado correctamente', [], 400);
        }

        $usr = DB::table('S002V01TUSUA')->where([
            ['USUA_NULI', '=', $line],
            ['USUA_IDUS', '=', $idUser],
        ])->first();

        if(is_null($usr)){
            return $this->responseController->makeResponse(true, 'El usuario que realizó la consulta no está registrado', [], 404);
        }

        //PENDIENTE LIGAR CON EQUIPAMIENTOS
        $preventiveInterventions = DB::table('S002V01TBEOT')->select([
            DB::raw('CONCAT(BEOT_IDRE, "|", BEOT_FEPR) AS IDREG'),
            'OTPR_IDOT AS IDORDER',
            'OTPR_EQIN AS EQUIPMENT',
            'BEOT_TIOR AS ORDER_TYPE',
            'BEOT_TIAC AS ACTION_TYPE',
            'BEOT_FEEJ AS START_DATE',
            'BEOT_FEFI AS END_DATE',
        ])->join('S002V01TOTPR', 'OTPR_IDOT', '=', 'BEOT_IDOT')->where([
            ['BEOT_NULI', '=', $line],
            ['BEOT_TIOR', '=', 'Preventivo'],
        ])->get()->all();

        foreach($preventiveInterventions as $key=>$val){
            $val->IDREG = $this->encryptionController->encrypt($val->IDREG);
            $preventiveInterventions[$key] = $val;
        }

        //PENDIENTE MANTENIMIENTO CORRECTIVO

        $now = $this->functionsController->now();
        $nowStr = $now->toDateTimeString();
        $actions = DB::getQueryLog();
        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
        
        $idac = $this->functionsController->registerActivity(
            $line,
            'S002V01M11GPRS',
            'S002V01F01ADIN',
            '-',
            'Consulta',
            "El usuario $name (" . $usr->USUA_IDUS . ") consultó las intervenciones registradas.",
            $idUser,
            $nowStr,
            'S002V01S03GEIN'
        );

        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $line);
        return $this->responseController->makeResponse(false, 'EXITO', $preventiveInterventions);
    }
}