<?php

namespace App\Imports;

use App\Models\Producto;
use App\Models\ProductVariant;
use App\Models\Bodega;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Illuminate\Support\Collection;

class CompraDetallesImport implements ToCollection, WithHeadingRow, WithValidation
{
    protected $previewData = [];
    protected $errors = [];

    /**
     * Procesa la colección y genera vista preliminar
     */
    public function collection(Collection $rows)
    {
        $this->previewData = [];
        $rowNumber = 2; // Comenzar en 2 porque fila 1 son los encabezados

        foreach ($rows as $row) {
            $detalle = $this->processRow($row->toArray(), $rowNumber);
            $this->previewData[] = $detalle;
            $rowNumber++;
        }
    }

    /**
     * Procesa una fila individual
     */
    private function processRow(array $row, int $rowNumber): array
    {
        $result = [
            'row_number' => $rowNumber,
            'valid' => true,
            'errors' => [],
            'data' => [],
            'producto_creado' => false,
        ];

        // Normalizar nombres de columnas
        $row = $this->normalizeKeys($row);

        // Buscar o crear producto
        $producto = null;
        $variante = null;
        $productoCreado = false;

        // 1. Primero intentar buscar por código de barras
        if (!empty($row['codigo_barras'])) {
            // Buscar variante primero
            $variante = ProductVariant::where('barcode', $row['codigo_barras'])->first();
            if ($variante) {
                $producto = $variante->producto;
            } else {
                // Buscar producto por código
                $producto = Producto::where('codigo_barras', $row['codigo_barras'])->first();
            }
        }
        
        // 2. Si no se encontró por código, buscar por nombre
        if (!$producto && !empty($row['producto'])) {
            $producto = Producto::where('nombre', 'like', '%' . trim($row['producto']) . '%')->first();
        }

        // 3. Si no existe, crear el producto
        if (!$producto) {
            // Validar que tenga al menos nombre o código
            if (empty($row['producto']) && empty($row['codigo_barras'])) {
                $result['valid'] = false;
                $result['errors'][] = 'Debe proporcionar código de barras o nombre del producto';
            } else {
                $nombreProducto = !empty($row['producto']) ? trim($row['producto']) : 'Producto ' . $row['codigo_barras'];
                $precioUnitario = isset($row['precio_unitario']) ? (float) $row['precio_unitario'] : 0;
                
                if ($precioUnitario <= 0) {
                    $result['valid'] = false;
                    $result['errors'][] = 'Precio debe ser mayor a 0 para crear producto';
                } else {
                    // Buscar o crear categoría "Importados"
                    $categoria = \App\Models\Categoria::firstOrCreate(
                        ['nombre' => 'Importados'],
                        ['descripcion' => 'Productos creados automáticamente durante importación de compras']
                    );

                    // Generar código de barras único si no se proporcionó
                    $codigoBarras = !empty($row['codigo_barras']) ? $row['codigo_barras'] : null;
                    
                    if (!$codigoBarras) {
                        // Generar código único: IMP + timestamp + random
                        do {
                            $codigoBarras = 'IMP' . time() . rand(100, 999);
                        } while (Producto::where('codigo_barras', $codigoBarras)->exists());
                    }

                    $producto = Producto::create([
                        'nombre' => $nombreProducto,
                        'descripcion' => 'Creado automáticamente desde importación',
                        'codigo_barras' => $codigoBarras,
                        'categoria_id' => $categoria->id,
                        'precio_compra' => $precioUnitario,
                        'precio_venta' => round($precioUnitario * 1.3, 2), // 30% de margen por defecto
                        'unidad_medida' => 'unidad',
                        'estado' => true,
                        'imagen' => '',
                    ]);

                    $productoCreado = true;
                    $result['producto_creado'] = true;
                }
            }
        }

        // Buscar bodega
        $bodega = null;
        if (!empty($row['bodega'])) {
            $bodega = Bodega::where('nombre', 'like', '%' . $row['bodega'] . '%')->first();
        } else {
            $bodega = Bodega::where('nombre', 'Principal')->first();
        }

        if (!$bodega) {
            $result['valid'] = false;
            $result['errors'][] = 'Bodega no encontrada';
        }

        // Validar cantidad
        $cantidad = isset($row['cantidad']) ? (int) $row['cantidad'] : 1;
        if ($cantidad <= 0) {
            $result['valid'] = false;
            $result['errors'][] = 'Cantidad debe ser mayor a 0';
        }

        // Validar precio
        $precio = isset($row['precio_unitario']) ? (float) $row['precio_unitario'] : 0;
        if ($precio <= 0) {
            $result['valid'] = false;
            $result['errors'][] = 'Precio debe ser mayor a 0';
        }

        // Calcular subtotal
        $subtotal = $cantidad * $precio;

        // Preparar datos
        $result['data'] = [
            'codigo_barras' => $row['codigo_barras'] ?? '',
            'producto_nombre_excel' => $row['producto'] ?? '',
            'bodega_id' => $bodega?->id,
            'bodega_nombre' => $bodega?->nombre ?? 'No encontrada',
            'producto_id' => $producto?->id,
            'producto_nombre' => $producto?->nombre ?? 'No encontrado',
            'variante_id' => $variante?->id,
            'variante_info' => $variante ? $this->getVariantInfo($variante) : null,
            'cantidad' => $cantidad,
            'precio_unitario' => $precio,
            'subtotal' => $subtotal,
            'DetalleCompra' => $row['observaciones'] ?? $row['detalle'] ?? '',
        ];

        return $result;
    }

    /**
     * Obtiene información formateada de la variante
     */
    private function getVariantInfo($variante): string
    {
        $colorName = $variante->color?->name ?? 'Sin color';
        $sizeName = $variante->size?->name ?? 'Sin talla';
        return "$colorName / $sizeName";
    }

    /**
     * Normaliza las claves del array
     */
    private function normalizeKeys(array $row): array
    {
        $normalized = [];
        $mappings = [
            'codigo_de_barras' => 'codigo_barras',
            'codigo' => 'codigo_barras',
            'barcode' => 'codigo_barras',
            'precio' => 'precio_unitario',
            'precio_unit' => 'precio_unitario',
            'observacion' => 'observaciones',
            'detalle' => 'observaciones',
            'cantidad' => 'cantidad',
            'cant' => 'cantidad',
            'qty' => 'cantidad',
            'producto' => 'producto',
            'nombre' => 'producto',
            'nombre_producto' => 'producto',
            'articulo' => 'producto',
            'bodega' => 'bodega',
        ];

        foreach ($row as $key => $value) {
            $normalizedKey = strtolower(trim($key));
            $normalizedKey = str_replace(' ', '_', $normalizedKey);
            $normalizedKey = $this->removeAccents($normalizedKey);
            
            if (isset($mappings[$normalizedKey])) {
                $normalized[$mappings[$normalizedKey]] = $value;
            } else {
                $normalized[$normalizedKey] = $value;
            }
        }

        return $normalized;
    }

    /**
     * Elimina tildes
     */
    private function removeAccents($string)
    {
        $unwanted = [
            'á' => 'a', 'é' => 'e', 'í' => 'i', 'ó' => 'o', 'ú' => 'u',
            'Á' => 'A', 'É' => 'E', 'Í' => 'I', 'Ó' => 'O', 'Ú' => 'U',
            'ñ' => 'n', 'Ñ' => 'N',
        ];
        return strtr($string, $unwanted);
    }

    /**
     * Reglas de validación
     */
    public function rules(): array
    {
        return [
            'codigo_barras' => 'nullable|string',
            'producto' => 'nullable|string',
            'bodega' => 'nullable|string',
            'cantidad' => 'nullable|integer|min:1',
            'precio_unitario' => 'nullable|numeric|min:0',
            'observaciones' => 'nullable|string',
        ];
    }

    /**
     * Obtiene los datos de vista preliminar
     */
    public function getPreviewData(): array
    {
        return $this->previewData;
    }

    /**
     * Obtiene estadísticas de la importación
     */
    public function getStats(): array
    {
        $valid = collect($this->previewData)->filter(fn($item) => $item['valid'])->count();
        $invalid = collect($this->previewData)->filter(fn($item) => !$item['valid'])->count();
        $productosCreados = collect($this->previewData)->filter(fn($item) => isset($item['producto_creado']) && $item['producto_creado'])->count();
        $total = count($this->previewData);
        $totalAmount = collect($this->previewData)
            ->where('valid', true)
            ->sum(fn($item) => $item['data']['subtotal']);

        return [
            'total' => $total,
            'valid' => $valid,
            'invalid' => $invalid,
            'productos_creados' => $productosCreados,
            'total_amount' => $totalAmount,
        ];
    }

    /**
     * Convierte los datos preliminares a formato para guardar
     */
    public function getDetallesForSave(): array
    {
        return collect($this->previewData)
            ->filter(fn($item) => $item['valid'])
            ->map(fn($item) => [
                'bodega_id' => $item['data']['bodega_id'],
                'producto_id' => $item['data']['producto_id'],
                'variante_id' => $item['data']['variante_id'],
                'cantidad' => $item['data']['cantidad'],
                'precio_unitario' => $item['data']['precio_unitario'],
                'subtotal' => $item['data']['subtotal'],
                'DetalleCompra' => $item['data']['DetalleCompra'],
                'producto_nombre_snapshot' => $item['data']['producto_nombre'],
                'variante_info_snapshot' => $item['data']['variante_info'],
            ])
            ->toArray();
    }
}
