<?php

namespace App\Http\Controllers;

use App\Http\Controllers\ResponseController;
use App\Http\Controllers\EncryptionController;
use App\Http\Controllers\ResourcesController;
use App\Http\Controllers\FunctionsController;
use App\Http\Controllers\DocumentManagementController;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class IssueTrackingController extends Controller
{
    private $responseController;
    private $encController;
    private $resourcesController;
    private $documentManagementController;
    private $functionsController;

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

    public function reportProblem(Request $request) {
        $validator = Validator::make($request->all(),[
            'ORDER' => 'required|string',
            'TIPO' => 'required|string',
            'DESCRIPCION' => 'required|string',
            'EVIDENCIA' => 'required|array',
            'USUARIO' => 'required|string',
            'NUMERO_LINEA' => 'required|integer',
        ]);
        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_ISSUE_TRACKING_REG000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        DB::beginTransaction();
        $requestData = $request->all();

        try {
            $user = $this->encController->decrypt($requestData['USUARIO']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_REG001: Ocurrió un error al obtener el usuario.", $th->getMessage(), 500);
        }

        try {
            $orderNumber = $this->encController->decrypt($requestData['ORDER']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_REG002: Ocurrió un error al obtener el usuario.", $th->getMessage(), 500);
        }

        try {
            $validateExists = DB::table('S002V01TORCO')->where('ORCO_NUOR', '=', $orderNumber)->exists();
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_REG003: Ocurrió un error al validar el número de orden de compra.", $th->getMessage(), 500);
        }

        if (!$validateExists) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_REG004: No se encontró el número de orden de compra.", [], 500);
        }

        $arrCodeEvidence = array();
        foreach ($requestData['EVIDENCIA'] as $keyEvidence => $evidence) {
            $idFile = $this->encController->decrypt($evidence);
            $tempFile = DB::table('S002V01TARTE')->where([
                ['ARTE_NULI', '=', $requestData['NUMERO_LINEA']],
                ['ARTE_IDAR', '=', $idFile],
            ])->first();

            if(is_null($tempFile)){
                return $this->responseController->makeResponse(true, 'ERR_ISSUE_TRACKING_REG005: El archivo consultado no está registrado', [], 404);
            }else if($tempFile->ARTE_ESTA == 'Eliminado'){
                return $this->responseController->makeResponse(true, 'ERR_ISSUE_TRACKING_REG006: El archivo consultado está eliminado', [], 404);
            }
            $fileResponse = $this->documentManagementController->moveFinalFile(
                intval($requestData['NUMERO_LINEA']),
                'GEAD',
                'FO',
                $tempFile,
                $user,
            );
            if(!$fileResponse[0]){
                return $this->responseController->makeResponse(true, 'ERR_ISSUE_TRACKING_REG007: '.$fileResponse[1], [], 400);
            }
            $arrCodeEvidence[] = $this->encController->encrypt($fileResponse[1]);
        }
        $jsonEvidence = json_encode($arrCodeEvidence);

        $now = $this->functionsController->now();
        $currentDate = $now->toDateTimeString();

        try {
            $validateInsert = DB::table('S002V01TSEPR')->insert([
                'SEPR_NUOR' => $orderNumber,
                'SEPR_TIPO' => $requestData['TIPO'],
                'SEPR_DESC' => $requestData['DESCRIPCION'],
                'SEPR_EVID' => $jsonEvidence,
                'SEPR_NULI' => $requestData['NUMERO_LINEA'],
                'SEPR_USRE' => $user,
                'SEPR_FERE' => $currentDate,
                'SEPR_FEAR' => DB::raw('CURRENT_TIMESTAMP')
            ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_REG008: Ocurrió un error al hacer la inserción en la base.", $th->getMessage(), 500);
        }
        
        if (!$validateInsert) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_REG009: No se pudo ingresar el reporte en la base.", [], 500);
        }
        
        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Registro de Reporte Exitoso");
    }

    public function getIssueTracking($user, $line) {
        DB::beginTransaction();
        try {
            $arrIssueTracking = DB::table('S002V01TSEPR')
                ->where('SEPR_NULI', '=', $line)
                ->where('ORCO_NULI', '=', $line)
                ->where('DESP_NULI', '=', $line)
                ->join('S002V01TORCO', 'SEPR_NUOR', '=', 'ORCO_NUOR')
                ->join('S002V01TDESP', 'DESP_IDDE', '=', 'ORCO_IDDE')
                ->get([
                    'SEPR_IDPR',
                    'SEPR_NUOR',
                    'DESP_NOMB',
                    'SEPR_TIPO',
                    'SEPR_DESC',
                    'SEPR_RESO',
                    'SEPR_EVID',
                    'SEPR_ESTA',
                    'SEPR_USRE',
                    'SEPR_FERE',
                    'SEPR_USMO',
                    'SEPR_FEMO',
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_GET000: Ocurrió un error al obtener los datos.", $th->getMessage(), 500);
        }

        $arrIssueTracking = json_decode(json_encode($arrIssueTracking), true);
        foreach ($arrIssueTracking as $keyIssueTracking => $issueTracking) {
            $issueTracking['SEPR_EVID'] = json_decode($issueTracking['SEPR_EVID']);
            $arrUrlImage = array();
            foreach ($issueTracking['SEPR_EVID'] as $keyEvidence => $evidence) {
                $responseDocument = $this->documentManagementController->getPublicDocumentURL($evidence, $user, $line);
                $arrResponseDocument = json_decode($responseDocument->original, true);
                if ($arrResponseDocument['error']) {
                    return $this->responseController->makeResponse(true, "ERR_ARTITLE_GET003: Ocurrió un error al obtener la URL de la imágen.", [], 500);
                }
                $arrUrlImage[] = $arrResponseDocument['response']['public_uri'];
            }
            $issueTracking['SEPR_EVID'] = $arrUrlImage;
            $arrIssueTracking[$keyIssueTracking] = $issueTracking;
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Consulta Exitosa", $arrIssueTracking);
    }

    public function resolutionIssueTracking(Request $request) {
        $validator = Validator::make($request->all(),[
            'NUMERO_SEGUIMIENTO' => 'required|string',
            'DESCRIPCION' => 'required|string',
            'NUMERO_LINEA' => 'required|string',
            'USUARIO' => 'required|string',
        ]);
        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_ISSUE_TRACKING_RES000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        DB::beginTransaction();
        $requestData = $request->all();
        
        // Se obtiene el usuario encriptado
        try {
            $user = $this->encController->decrypt($requestData['USUARIO']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_RES001: Ocurrió un error al obtener el usuario.", $th->getMessage(), 500);
        }

        // Se obtiene el número de orden enctriptado
        try {
            $trackingNumber = $this->encController->decrypt($requestData['NUMERO_SEGUIMIENTO']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_RES002: Ocurrió un error al obtener el usuario.", $th->getMessage(), 500);
        }

        // Se valida el número de seguimiento
        try {
            $validateExists = DB::table('S002V01TSEPR')
                ->where('SEPR_IDPR', '=', $trackingNumber)
                ->where('SEPR_NULI', '=', $requestData['NUMERO_LINEA'])
                ->exists();
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_RES003: Ocurrió un error al validar el número de seguimiento.", $th->getMessage(), 500);
        }
        if (!$validateExists) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_RES004: No se encontró el número de seguimiento seleccionado.", [], 500);
        }

        $now = $this->functionsController->now();
        $currentDate = $now->toDateTimeString();

        try {
            $validateUpdate = DB::table('S002V01TSEPR')->where('SEPR_IDPR', '=', $trackingNumber)->where('SEPR_NULI', '=', $requestData['NUMERO_LINEA'])->update([
                'SEPR_ESTA' => 'Resuelto',
                'SEPR_RESO' => $requestData['DESCRIPCION'],
                'SEPR_USRE' => $user,
                'SEPR_FEMO' => $currentDate,
                'SEPR_FEAR' => DB::raw('CURRENT_TIMESTAMP')
            ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_RES005: Ocurrió un error al modificar los registros de seguimiento.", $th->getMessage(), 500);
        }

        if (!$validateUpdate) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ISSUE_TRACKING_RES006: No se pudo modificar los registros de seguimiento.", [], 500);
        }
        
        // Se guardan todos los cambios
        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Modificación de Reporte Exitoso");
    }
}