<?php
/*
    Desarrollador: Ing. Jean Jairo Benitez Meza
    Ultima Modificación: 11/04/2023
    Módulo: Gestión de Adquisiciones
*/
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Controllers\ResponseController;
use App\Http\Controllers\EncryptionController;
use App\Http\Controllers\ResourcesController;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Database\Query\JoinClause;

class OrderController extends Controller {

    private $responseController;
    private $encController;
    private $resourcesController;

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

    public function getOrders($line) {
        try {
            $arrOrders = DB::table('S002V01TORCO')
                ->where('ORCO_NULI', '=', $line)
                ->join('S002V01TDESP', 'DESP_NUDE', '=', 'ORCO_NUDE')
                ->join('S002V01TPROV', 'PROV_NUPR', '=', 'ORCO_NUPR')
                ->join('S002V01TLINE', 'LINE_IDLI', '=', 'ORCO_IDLI')
                ->join('S002V01TMEPA', 'MEPA_IDME', '=', 'LINE_IDME')
                ->get([
                    'ORCO_NUOR', // Número de Orden
                    'PROV_NUPR', // Número de Proveedor
                    'PROV_NOCO', // Nombre Comercial del Proveedor
                    'DESP_NUDE', // Número de Despacho
                    'DESP_NOMB', // Nombre del Despacho
                    'LINE_IDLI', // Identificador de línea de solicitud de compra
                    'LINE_DESC', // Descripción de la línea de solicitud de compra
                    'LINE_IDME', // Métodos de Pago
                    'MEPA_NOMB', // Nombre del método de pago
                    'ORCO_COST', // Costo Total
                    'ORCO_MONE', // Moneda
                    'ORCO_PROP', // Proposito
                    'ORCO_ACTI', // Actividad
                    'ORCO_PROY', // Proyecto
                    'ORCO_ESTA', // Estado
                    'ORCO_USRE', // Usuario Registra
                    'ORCO_FERE', // Fecha Registra
                    'ORCO_USMO', // Usuario Modifica
                    'ORCO_FEMO', // Fecha Modifica

                ]);
        } catch ( \Throwable $th ) {
            return $this->responseController->makeResponse(true, "ERR_ORDER_GET000: Ocurrió un error al momento de obtener las órdenes de compra.", $th->getMessage(), 500);
        }

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

    // Se crea una orden de compra
    public function createOrder(Request $request){
        $validator = Validator::make($request->all(), [
            'NUMERO_SOLICITUD' => 'required|string',
            'NUMERO_LINEA' => 'required|string',
            'USUARIO' => 'required|string',
            'ARR_ORDENES' => 'required|array',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_ORDER_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_ORDER_REG001: Ocurrió un error al obtener el usuario.", [], 500);
        }

        foreach ($requestData['ARR_ORDENES'] as $keyOrders => $orders) {
            $validator = Validator::make($orders, [
                'NUMERO_PROVEEDOR' => 'required|string',
                'PROVEEDOR' => 'required|string',
                'PRECIO_TOTAL' => 'required|integer',
                'MONEDA' => 'required|string',
                'DESPACHO' => 'required|string',
                'PROPOSITO' => 'required|string',
                // 'ACTIVIDAD' => '',
                // 'PROYECTO' => '',
            ]);

            if ($validator->fails()) {
                return $this->responseController->makeResponse(
                    true,
                    "ERR_ORDER_REG002: Se encontraron uno o más errores.",
                    $this->responseController->makeErrors($validator->errors()->messages()),
                    401
                );
            }

            $arrInsert = [
                'ORCO_NUPR' => $orders['NUMERO_PROVEEDOR'],
                'ORCO_NUDE' => $orders['DESPACHO'],
                'ORCO_IDLI' => $requestData['NUMERO_SOLICITUD'],
                'ORCO_COST' => $orders['PRECIO_TOTAL'],
                'ORCO_MONE' => $orders['MONEDA'],
                'ORCO_PROP' => $orders['PROPOSITO'],
                'ORCO_ACTI' => $orders['ACTIVIDAD'] === '' ? null : $orders['ACTIVIDAD'],
                'ORCO_PROY' => $orders['PROYECTO'] === '' ? null : $orders['PROYECTO'],
                'ORCO_NULI' => $requestData['NUMERO_LINEA'],
                'ORCO_USRE' => $user,
                'ORCO_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                'ORCO_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
            ];

            try {
                $orderNumber = DB::table('S002V01TORCO')->insertGetId($arrInsert);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ORDER_REG003: Ocurrió un error al momento de insertar los datos en la base de datos.", $th->getMessage(), 500);
            }

            if ( !$orderNumber ) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ORDER_REG004: Ocurrió un error al insertar los datos en la base de datos.", [], 500);
            }

            $arrUpdate = [
                'LINE_ESTA' => 'En OC',
                'LINE_USMO' => $user,
                'LINE_FEMO' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                'LINE_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
            ];

            try {
                $validateInsert = DB::table('S002V01TLINE')
                    ->where('LINE_IDLI', '=', $requestData['NUMERO_SOLICITUD'])
                    ->where('LINE_NULI', '=', $requestData['NUMERO_LINEA'])
                    ->update($arrUpdate);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ORDER_REG005: Ocurrió un error al momento de insertar los datos en la base de datos.", [], 500);
            }

            if ( !$validateInsert ) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ORDER_REG006: Ocurrió un error al insertar los datos en la base de datos.", [], 500);
            }

            $arrInsertState = [
                'HIOR_NUOR' => $orderNumber,
                'HIOR_POEN' => 10,
                'HIOR_NULI' => $requestData['NUMERO_LINEA'],
                'HIOR_USRE' => $user,
                'HIOR_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                'HIOR_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
            ];

            try {
                $validateInsertUpdate = DB::table('S002V01THIOR')->insert($arrInsertState);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ORDER_REG007: Ocurrió un error al momento de insertar los datos en el historial de estados.", [], 500);
            }

            if ( !$validateInsertUpdate ) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_ORDER_REG008: Ocurrió un error al insertar los datos del historial en la base de datos.", [], 500);
            }
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Generación de Órdenes Exitosas");

    }

    public function getOrderByNumber($order, $provider, $line){

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


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


        try {
            $orders = DB::table('S002V01TORCO')
                ->where('ORCO_NULI', '=', $line)
                ->where('ORCO_NUOR', '=', $order)
                ->where('ORCO_NUPR', '=', $provider)
                ->join('S002V01TDESP', 'DESP_NUDE', '=', 'ORCO_NUDE')
                ->join('S002V01TPROV', 'PROV_NUPR', '=', 'ORCO_NUPR')
                ->join('S002V01TLINE', 'LINE_IDLI', '=', 'ORCO_IDLI')
                ->join('S002V01TMEPA', 'MEPA_IDME', '=', 'LINE_IDME')
                ->first([
                    'ORCO_NUOR', // Número de Orden
                    'PROV_NUPR', // Número de Proveedor
                    'PROV_NOCO', // Nombre Comercial del Proveedor
                    'DESP_NUDE', // Número de Despacho
                    'DESP_NOMB', // Nombre del Despacho
                    'DESP_CALL', // Calle
                    'DESP_NUEX', // Número Exterior
                    'DESP_NUIN', // Número Interior
                    'DESP_COPO', // Código Postal
                    'DESP_COLO', // Colonia
                    'DESP_MUNI', // Municipio
                    'DESP_ENTI', // Entidad
                    'DESP_PAIS', // Pais
                    'LINE_IDLI', // Identificador de línea de solicitud de compra
                    'LINE_DESC', // Descripción de la línea de solicitud de compra
                    'LINE_IDME', // Métodos de Pago
                    'MEPA_NOMB', // Nombre del método de pago
                    'ORCO_COST', // Costo Total
                    'ORCO_MONE', // Moneda
                    'ORCO_PROP', // Proposito
                    'ORCO_ACTI', // Actividad
                    'ORCO_PROY', // Proyecto
                    'ORCO_ESTA', // Estado
                    'ORCO_USRE', // Usuario Registra
                    'ORCO_FERE', // Fecha Registra
                    'ORCO_USMO', // Usuario Modifica
                    'ORCO_FEMO', // Fecha Modifica
                ]);
        } catch ( \Throwable $th ) {
            return $this->responseController->makeResponse(true, "ERR_ORDER_GET002: Ocurrió un error al momento de obtener las órdenes de compra.", $th->getMessage(), 500);
        }

        if ( !empty($orders) ) {
            try {
                $arrArtitleSelected = DB::table('S002V01TARSE')
                    ->where('ARSE_IDLI', '=', $orders->LINE_IDLI)
                    ->where('ARSE_NUPR', '=', $provider)
                    ->where('ARSE_NULI', '=', $line)
                    ->where('ARSE_ESTA', '=', 'Activo')
                    ->join('S002V01TARTI', 'ARTI_IDAR', '=', 'ARSE_IDAR')
                    ->join('S002V01TINAR', 'INAR_IDIN', '=', 'ARSE_IDIN')
                    ->join('S002V01TDEAR', 'DEAR_IDDE', '=', 'INAR_IDDE')
                    ->get([
                        'ARSE_IDAS', // Identificador de artículos seleccionados
                        'ARTI_IDAR', // Identificador del artículo
                        'ARTI_IDFA', // Identificador de la familia
                        'ARTI_IDSU', // Identificador de la subfamilia
                        'ARTI_CODI', // Código del artículo
                        'ARTI_NOMB', // Nombre del artículo
                        'ARSE_NUPR', // Número de Identificador del Proveedor
                        'ARSE_IDIN', // Número de Identificador de Información
                        'ARSE_CANT', // Cantidad seleccionada
                        'ARSE_PRTO', // Precio total
                        'ARSE_USRE', // Usuario registra
                        'ARSE_FERE', // Fecha registra
                        'ARSE_USMO', // Usuario modifica
                        'ARSE_FEMO', // Fecha modifica
                        'INAR_CODI', // Código del artículo
                        'INAR_MODE', // Modelo del artículo
                        'INAR_MONE', // Moneda
                        'INAR_PREC', // Precio
                        'INAR_CARA', // Características
                        'DEAR_IDDE', // Identificador de la descripción del artículo
                        'DEAR_DESC', // Descripción del artículo
                        'DEAR_CARA', // Características del proveedor
                        'DEAR_COWE', // Compra Web
                        'DEAR_IMAG', // Imágen del artículo
                        'DEAR_IDUN', // Identificador de la unidad
                        'DEAR_NUPR', // Número del Proveedor
                        'DEAR_IDAR', // Identificador del artícul
                    ]);
            } catch (\Throwable $th) {
                return $this->responseController->makeResponse(true, "ERR_ORDER_GET003: Ocurrió un error al momento de obtener la información de la línea de solicitud de compra", $th->getMessage(), 500);
            }

            $orders->PRODUCTS = $arrArtitleSelected;

            try {
                $arrStateOrder = DB::table('S002V01THIOR')
                    ->where('HIOR_NUOR', '=', $order)
                    ->where('HIOR_ESTA', '=', 'Activo')
                    ->where('HIOR_NULI', '=', $line)
                    ->get([
                        'HIOR_IDHO', // Identificador del historial de órdenes
                        'HIOR_NUOR', // Número de orden de compra
                        'HIOR_ESOR', // Estado de la orden
                        'HIOR_EVI1', // Evidencia 1
                        'HIOR_EVI2', // Evidencia 2
                        'HIOR_DESC', // Descripción
                        'HIOR_POEN', // Porcentaje de entrega
                        'HIOR_USRE', // Usuario entrega
                        'HIOR_FERE', // Fecha entrega
                        'HIOR_USMO', // Usuario modifica
                        'HIOR_FEMO', // Fecha modifica
                    ]);
            } catch (\Throwable $th) {
                return $this->responseController->makeResponse(true, "ERR_ORDER_GET004: Ocurrió un error al momento de obtener la información del historial de orden de compra", $th->getMessage(), 500);
            }

            $orders->STATES = $arrStateOrder;
        }



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

    public function getHistoryStateOrder($order, $line) {
        try {
            $objHistoryState = DB::table('S002V01THIOR')
                ->where('HIOR_NUOR', '=', $order)
                ->where('HIOR_NULI', '=', $line)
                ->where('HIOR_ESTA', '=', 'Activo')
                ->first([
                    'HIOR_IDHO', // Identificador de la historia de la orden
                    'HIOR_ESOR', // Estado de la orden
                    'HIOR_DESC', // Descripción del estado de la orden
                    'HIOR_EVI1', // Evidencia 1
                    'HIOR_EVI2', // Evidencia 2
                    'HIOR_POEN', // Porcentaje de entrega
                ]);
        } catch (\Throwable $th) {
            //throw $th;
        }
    }

    public function updateStateHistory(Request $request) {
        $validator = Validator::make($request->all(), [
            'ESTADO' => 'required|string',
            'DESCRIPCION' => 'required|string',
            'EVIDENCIA1' => 'required|string',
            'NOMBRE_IMAGEN1' => 'string',
            // 'EVIDENCIA2' => 'string',
            // 'NOMBRE_IMAGEN2' => 'string',
            'PORCENTAJE' => 'required|integer',
            'NUMERO_ORDEN' => 'required|string',
            'NUMERO_LINEA' => 'required|string',
            'USUARIO' => 'required|string',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_ORDERSTATE_REG000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

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

        $imageEvidence1 = null;
        $arrResponseImage =  $this->resourcesController->saveImage( $requestData['EVIDENCIA1'], '/app/public/GEAD/FO', $requestData['NOMBRE_IMAGEN1'], $requestData['NUMERO_LINEA'] );
        if ( $arrResponseImage['error'] ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, $arrResponseImage['msg'], $arrResponseImage['response'], 500);
        }
        $imageEvidence1 = $arrResponseImage['response'];


        $imageEvidence2 = null;
        if ( $requestData['EVIDENCIA2'] != '' && $requestData['EVIDENCIA2'] != null ) {
            $arrResponseImage =  $this->resourcesController->saveImage( $requestData['EVIDENCIA2'], '/app/public/GEAD/FO', $requestData['NOMBRE_IMAGEN2'], $requestData['NUMERO_LINEA'] );

            if ( $arrResponseImage['error'] ) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, $arrResponseImage['msg'], $arrResponseImage['response'], 500);
            }
            $imageEvidence2 = $arrResponseImage['response'];
        }

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

        $arrInsert = [
            'HIOR_NUOR' => $requestData['NUMERO_ORDEN'],
            'HIOR_ESOR' => $requestData['ESTADO'],
            'HIOR_DESC' => $requestData['DESCRIPCION'],
            'HIOR_EVI1' => $imageEvidence1,
            'HIOR_EVI2' => $imageEvidence2,
            'HIOR_POEN' => $requestData['PORCENTAJE'],
            'HIOR_NULI' => $requestData['NUMERO_LINEA'],
            'HIOR_USRE' => $user,
            'HIOR_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
            'HIOR_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
        ];

        try {
            $validateInsert = DB::table('S002V01THIOR')->insert($arrInsert);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ORDERSTATE_REG002: Ocurrió un error al momento de insertar los datos.", [], 500);
        }

        if ( !$validateInsert ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ORDERSTATE_REG003: No se pudo insertar los datos a la tabla.", [], 500);
        }

        $arrUpdate = [
            'ORCO_ESTA' => $requestData['ESTADO'],
            'ORCO_USMO' => $user,
            'ORCO_FEMO' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
        ];

        try {
            $validateUpdate = DB::table('S002V01TORCO')
                ->where('ORCO_NUOR', '=', $requestData['NUMERO_ORDEN'])
                ->where('ORCO_NULI', '=', $requestData['NUMERO_LINEA'])
                ->update($arrUpdate);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ORDERSTATE_REG004: Ocurrió un error al momento de modificar los datos.", [], 500);
        }

        if ( !$validateUpdate ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_ORDERSTATE_REG005: No se pudo modificar los datos a la tabla.", [], 500);
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Modificación de Estado Exitoso");
    }

    public function reorderArtitles(Request $request) {
        $validator = Validator::make($request->all(), [
            'ORDEN' => 'required|string',
            'DESCRIPCION' => 'required|string',
            'USUARIO' => 'required|string',
            'NUMERO_LINEA' => 'required|string',
        ]);

        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_REORDER_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_REORDER_REG001: Ocurrió un error al obtener el usuario.", [], 500);
        }
        try {
            $order = $this->encController->decrypt($requestData['ORDEN']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_REORDER_REG002: Ocurrió un error al obtener el número de orden.", [], 500);
        }

        try {
            $idRegisterLine = DB::table('S002V01TLINE')->insertGetId([
                'LINE_DESC' => $request['DESCRIPCION'],
                'LINE_NULI' => $request['NUMERO_LINEA'],
                'LINE_USRE' => $user,
                'LINE_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                'LINE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
            ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_REORDER_REG003: Ocurrió un error al hacer la inserción en la base.", $th->getMessage(), 500);
        }

        if ( !$idRegisterLine ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_REORDER_REG004: Ocurrió un error al hacer la inserción en la base.", [], 500);
        }

        try {
            $arrArtitles = DB::table('S002V01TORCO')
                ->where('ORCO_NUOR', '=', $order)
                ->join('S002V01TARSE', function (JoinClause $join) {
                    $join->on('ARSE_IDLI', '=', 'ORCO_IDLI')
                    ->on('ARSE_NUPR', '=', 'ORCO_NUPR');
                })
                ->get([
                    'ARSE_IDAR', // Identificador del artículo
                    'ARSE_NUPR', // Número del proveedor
                    'ARSE_IDIN', // Identificador de la información del artículo
                    'ARSE_CANT', // Cantidad
                    'ARSE_PRTO', // Precio total
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_REORDER_REG005: No se pudo obtener la información de la orden.", $th->getMessage(), 500);
        }

        if ( $arrArtitles->isEmpty() ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_REORDER_REG006: La orden no tiene artículos.", [], 500);
        }

        foreach ($arrArtitles as $keyArtitle => $artitle) {
            try {
                $validateInsert = DB::table('S002V01TARSE')->insert([
                    'ARSE_IDLI' => $idRegisterLine,
                    'ARSE_IDAR' => $artitle->ARSE_IDAR,
                    'ARSE_NUPR' => $artitle->ARSE_NUPR,
                    'ARSE_IDIN' => $artitle->ARSE_IDIN,
                    'ARSE_CANT' => $artitle->ARSE_CANT,
                    'ARSE_PRTO' => $artitle->ARSE_PRTO,
                    'ARSE_NULI' => $request['NUMERO_LINEA'],
                    'ARSE_USRE' => $user,
                    'ARSE_FERE' => Carbon::now()->timezone('America/Mazatlan')->toDateTimeString(),
                    'ARSE_FEAR' => DB::raw('CURRENT_TIMESTAMP')
                ]);
            } catch (\Throwable $th) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_REORDER_REG007: Ocurrió un error al hacer la inserción en la base.", $th->getMessage(), 500);
            }
            if ( !$validateInsert ) {
                DB::rollBack();
                return $this->responseController->makeResponse(true, "ERR_REORDER_REG008: Ocurrió un error al hacer la inserción en la base.", [], 500);
            }
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Artículos Reordenados Exitosamente");
    }
}
