<?php

namespace App\Services;

use App\Models\Producto;
use App\Models\ProductVariant;

class EAN13Service
{
    /**
     * Genera un código de barras EAN-13 único.
     *
     * @param string $countryCode Código de país (2 dígitos)
     * @param int $categoryId ID de la categoría (2 dígitos)
     * @param int $productId ID del producto (5 dígitos)
     * @param int|null $variantId ID de la variante (2 dígitos, opcional)
     * @return string Código de barras EAN-13
     * @throws \Exception Si hay un error en la generación del código
     */
    public function generateUniqueBarcode($countryCode, $categoryId, $productId, $variantId = null)
    {
        // Formatear los valores con ceros a la izquierda
        $categoryCode = str_pad($categoryId, 2, '0', STR_PAD_LEFT);
        $productCode = str_pad($productId, 5, '0', STR_PAD_LEFT);
        $variantCode = str_pad($variantId ?? 0, 3, '0', STR_PAD_LEFT);
    
        // Generar los primeros 12 dígitos del código EAN-13
        $barcodeBase = $countryCode . $categoryCode . $productCode . $variantCode;
    
        // Validar que la longitud sea exactamente 12 caracteres
        if (strlen($barcodeBase) !== 12) {
            throw new \Exception("Error: El código base del EAN-13 no tiene 12 caracteres: $barcodeBase");
        }
    
        // Intentar generar un código único hasta 5 veces
        $maxAttempts = 5;
        $uniqueBarcode = null;
    
        foreach (range(1, $maxAttempts) as $attempt) {
            // Calcular el dígito de control
            $checkDigit = $this->calculateCheckDigit($barcodeBase);
            $barcode = $barcodeBase . $checkDigit;
    
            // Verificar si el código de barras ya existe en la base de datos
            $existsInProductVariant = ProductVariant::where('barcode', $barcode)->exists();
            $existsInProducto = Producto::where('codigo_barras', $barcode)->exists();
    
            if (!$existsInProductVariant && !$existsInProducto) {
                // Si no existe, asignar el código único y salir del ciclo
                $uniqueBarcode = $barcode;
                break;
            }
    
            // Si existe, modificar el código base agregando un sufijo incremental
            $suffix = str_pad($attempt, 3, '0', STR_PAD_LEFT); // Agregar un sufijo de 3 dígitos
            $barcodeBase = substr($barcodeBase, 0, -3) . $suffix; // Reemplazar los últimos 3 dígitos con el sufijo
        }
    
        // Retornar el código único si se encontró, o null si no se pudo generar
        return $uniqueBarcode;
    }

    /**
     * Calcula el dígito de control de un código EAN-13.
     *
     * @param string $barcodeBase Los primeros 12 dígitos del código EAN-13
     * @return int Dígito de control calculado
     * @throws \Exception Si el código base no tiene 12 caracteres
     */
    private function calculateCheckDigit($barcodeBase)
    {
        if (strlen($barcodeBase) !== 12) {
            throw new \Exception("Error: El código base para el dígito de control no tiene 12 caracteres: $barcodeBase");
        }

        $sum = 0;
        for ($i = 0; $i < 12; $i++) {
            $digit = (int) $barcodeBase[$i];
            $sum += ($i % 2 === 0) ? $digit : $digit * 3;
        }

        $remainder = $sum % 10;
        return ($remainder === 0) ? 0 : 10 - $remainder;
    }
}
