<?php

namespace App\Http\Controllers;

use App\Exports\DownloadAllProductsExport;
use App\Exports\DownloadProductsExport;
use App\Exports\ProductsByOrderExport;
use App\Imports\ProductsImport;
use App\Models\Log;
use App\Models\Order;
use App\Models\OrderRecord;
use App\Models\Product;
use App\Models\ProductEarlyEnlistment;
use App\Models\Sim;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;
use Throwable;


class ProductController extends Controller
{
    public function index() {
        ini_set('memory_limit', '-1');
        try {
            $products = (new Product())->get();
        } catch (Exception $exception) {
            dd($exception);
        }
        return response()->json($products, 200);
    }

    /**
     * Display the specified resource.
     */
    public function show(Product $product)
    {
        $product_type = $product->productType;
        return response()->json($product, 200);
    }

    public function productsImport(Request $request) {

        ini_set('memory_limit', '-1');

        if ($request->hasFile('products')) {
            try {

                $product_type_id = $request->product_type_id;
                $number_order = $request->number_order;
                $description = $request->description;
    
                Excel::import(new ProductsImport($product_type_id, $number_order, $description), $request->file('products'));
    
            } catch (Exception $exception) {
                return errorReturn($exception->getMessage(), 'products_import', 'No se ha importado el archivo');
            }
        } else {
            return errorReturn('No se ha subido un archivo', 'file_products', 'El archivo es requerido');
        }

        $data = [];

        return successReturn('Se ha subido el archivo correctamente', $request->route()->getActionname(), $data);
    }

    public function searchProduct(Request $request) {

        $serial = $request->serial;
        $data = [];

        try {
            $product = (new Product())
            ->where('serial', $serial)
            ->with(['orderRecord', 'productType', 'productEnlistment', 'productInventory', 'newness.newnessType'])
            ->first();

            if(!empty($product)) {
                if(isset($product->orderRecord)) {
                    $order = (new Order())
                    ->where('id', $product->orderRecord->order_id)
                    ->where('status', 1)
                    ->with(['productType', 'orderStatus', 'client', 'destination'])
                    ->first();

                    $data['order'] = $order;
                    $data['sim'] = $product->orderRecord->sim;
                } else {
                    $data['order'] = null;
                    $data['sim'] = null;
                }

                if(isset($product->productInventory)) {
                    $box = $product->productInventory->box;
                    $stowage = $product->productInventory->box->stowage;
    
                    $data['location'] = [
                        'stowage_number' => $stowage->stowage_number,
                        'box_number' => $box->box_number,
                    ];
                }

                if(isset($product->productEnlistment)) {
                    $box = $product->productEnlistment->box;
                    $stowage = $product->productEnlistment->box->stowage;
    
                    $data['location'] = [
                        'stowage_number' => $stowage->stowage_number,
                        'box_number' => $box->box_number,
                    ];
                    $data['sim'] = $product->productEnlistment->sim;
                }
                
            } else {
                return errorReturn('No existe el producto que intentas buscar', 'products', 'No existe el producto: ' . $serial, 442);
            }
        } catch (\Throwable $th) {
            return errorReturn($th->getMessage(), 'search_product', 'No se pudo consultar el producto', 442);
        }

        $data['product'] = $product;

        return successReturn('Busqueda de productos', $request->route()->getActionname(), $data);

    }


    public function searchProductBySim(Request $request) {

        $sim_serial = $request->sim_serial;
        $data = [];

        try {

            $sim = Sim::where('sim_serial', $sim_serial)
            ->with(['simOrderRecord.simOrder', 'simOrderRecord.simOrder.destination', 'simOrderRecord.simOrder.deliverer', 'simOrderRecord.simOrder.orderStatus'])
            ->first();

            if(!empty($sim)) {
                $data['sim'] = $sim;

                $order_record = (new OrderRecord())
                ->where('sim_serial', $sim_serial)
                ->first();

                if(!empty($order_record)) {
                    $product = (new Product())
                    ->where('id', $order_record->product_id)
                    ->with(['orderRecord', 'productType'])
                    ->first();
        
                    if(!empty($product)) {
                        if(isset($product->orderRecord)) {
                            $order = (new Order())
                            ->where('id', $order_record->order_id)
                            ->where('status', 1)
                            ->with(['productType', 'orderStatus', 'client', 'destination'])
                            ->first();
        
                            $data['order'] = $order;
                            $data['sim'] = $product->orderRecord->sim;
                        } else {
                            $data['order'] = null;
                            $data['sim'] = null;
                        }

                        $data['product'] = $product;

                        if(isset($product->productEnlistment)) {
                            $box = $product->productEnlistment->box;
                            $stowage = $product->productEnlistment->box->stowage;
            
                            $data['location'] = [
                                'stowage_number' => $stowage->stowage_number,
                                'box_number' => $box->box_number,
                            ];
                        }
                        
                    } else {
                        $data['product'] = null;
                    }

                } else {

                    $productEarlyEnlistment = (new ProductEarlyEnlistment())
                    ->where('sim_serial', $sim_serial)
                    ->first();

                    if(!empty($productEarlyEnlistment)) {

                        $product = $productEarlyEnlistment->product;
                        if(isset($product->productEnlistment)) {
                            $box = $product->productEnlistment->box;
                            $stowage = $product->productEnlistment->box->stowage;
                            $product_type = $product->productType;
            
                            $data['location'] = [
                                'stowage_number' => $stowage->stowage_number,
                                'box_number' => $box->box_number,
                            ];
                        }

                        $data['product'] = $product;

                    }
                    
                }

                $data['order_record'] = $order_record;

            } else {
                return errorReturn('No existe una SIM con el serial que intentas buscar.', 'sim', 'No existe la SIM: ' . $sim_serial, 442);
            }
            
        } catch (\Throwable $th) {
            return errorReturn($th->getMessage(), 'search_product', 'No se pudo consultar el producto', 442);
        }

        return successReturn('Busqueda de sim', $request->route()->getActionname(), $data);

    }
    
    public function productsByOrderExport(Request $request)
    {
        try {
            ini_set('memory_limit', '512M');
            set_time_limit(0);
    
            $request->validate([
                'order_id' => ['required', 'integer'],
            ]);
    
            return Excel::download(
                new ProductsByOrderExport($request->order_id),
                'productos-GLP-ZF-' . $request->order_id . '-' . now()->format('Y-m-d-H-i-s') . '.xlsx'
            );
    
        } catch (Throwable $e) {
            report($e);
    
            return response()->json([
                'message' => 'Error generando el archivo.',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    public function downloadProducts(Request $request) {
        
        ini_set('memory_limit', '-1');
        set_time_limit(0);
        
        $product_type_id = $request->product_type_id;
        return Excel::download(new DownloadProductsExport($product_type_id), 'productos-' . $product_type_id . '-' . date('Y-m-d-H-i-s') . '.xlsx');
    }

    public function downloadAllProducts() {
        ini_set('memory_limit', '-1');
        set_time_limit(0);

        // --- DEBUG ---
        register_shutdown_function(function () {
            $error = error_get_last();
            if ($error !== null) {
                \Log::error('DEBUG shutdown: fatal error detectado tras Excel::download', [
                    'type' => $error['type'],
                    'message' => $error['message'],
                    'file' => $error['file'],
                    'line' => $error['line'],
                    'memory_peak_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
                ]);
            }
        });

        \Log::info('DEBUG memoria ANTES de Excel::download', [
            'memory_peak_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
        ]);

        try {
            $response = Excel::download(new DownloadAllProductsExport(), 'productos-' . date('Y-m-d-H-i-s') . '.xlsx');

            \Log::info('DEBUG memoria DESPUES de Excel::download (sin excepcion)', [
                'memory_peak_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
            ]);

            return $response;
        } catch (\Throwable $e) {
            \Log::error('DEBUG excepcion capturada en Excel::download', [
                'class' => get_class($e),
                'message' => $e->getMessage(),
                'location' => $e->getFile() . ':' . $e->getLine(),
                'trace' => collect($e->getTrace())->take(10)->toArray(),
                'memory_peak_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
            ]);
            throw $e;
        }
        // --- FIN DEBUG ---
    }

    public function destroy(Request $request) {

        $serial = $request->serial;

        try {
            
            if (Auth::check()) {
                $product = (new Product())
                ->where('serial', $serial)
                ->first();

                $product->delete();
            } else {
                return errorReturn('Usuario no ha iniciado sesión', 'delete_product', 'No se pudo eliminar el producto', 442);
            }
        
        } catch(\Throwable $th) {
            return errorReturn($th->getMessage(), 'delete_product', 'No se pudo eliminar el producto', 442);
        }

        $data['serial'] = $serial;

        return successReturn('Se ha eliminado correctamente el serial: ' . $serial, $request->route()->getActionname(), $data);

    }

}
