<?php

namespace App\Services\Administracion\Crud;

use App\Models\Bien;
use App\Models\PreciosPorBien;
use App\Models\TipoInsumo;
use App\Rules\BienRules;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;

class BienesCrudService extends CrudEntityService
{
    protected string $entity = 'bienes';

    protected string $modelClass = Bien::class;

    protected array $entityLabels = [
        'singular' => 'Bien',
        'plural' => 'Bienes',
        'create' => 'Nuevo Bien',
    ];

    protected array $tableColumns = ['sap', 'codigo', 'descripcion', 'tipo', 'unidadUtil', 'precioUnitario', 'peso', 'relacionUnidades', 'pesoTotal'];

    protected array $tableLabels = [
        'sap' => 'SAP',
        'codigo' => 'Código',
        'descripcion' => 'Descripción',
        'tipo' => 'Tipo de Bien',
        'unidadUtil' => 'Unidad',
        'precioUnitario' => 'Precio unitario',
        'peso' => 'Peso / Und.',
        'relacionUnidades' => 'Rel. Unidad',
        'pesoTotal' => 'Peso total',
    ];

    protected array $formLabels = [
        'sap' => 'SAP',
        'codigo' => 'Código',
        'descripcion' => 'Descripción',
        'unidad' => 'Unid. Almac.',
        'unidadUtil' => 'Unidad',
        'relacionUnidades' => 'Cant. Und.',
        'tipo' => 'Tipo de Bien',
        'marca' => 'Marca',
        'modelo' => 'Modelo',
        'serial' => 'Serial',
        'peso' => 'Peso/unidad',
        'ubicacionEstante' => 'Ubicación de Estante',
        'ubicacionFila' => 'Ubicación de Fila',
        'tiempoRetorno' => 'Tiempo de Retorno (días)',
        'mesesEntrega' => 'Meses para la Siguiente Entrega',
    ];

    protected array $searchColumns = ['sap', 'codigo', 'descripcion'];

    protected ?string $searchPlaceholder = 'Buscar por SAP, codigo o descripcion';

    protected array $editableColumns = [
        'sap',
        'codigo',
        'descripcion',
        'unidad',
        'unidadUtil',
        'relacionUnidades',
        'tipo',
        'marca',
        'modelo',
        'serial',
        'peso',
        'ubicacionEstante',
        'ubicacionFila',
        'tiempoRetorno',
        'mesesEntrega',
    ];

    protected array $importLookupColumns = ['codigo', 'sap'];

    protected ?array $defaultSort = ['descripcion', 'asc'];

    protected function validationRules(bool $isUpdate = false, ?int $id = null): array
    {
        return BienRules::rules($isUpdate, $id);
    }

    protected function fieldOptions(): array
    {
        return [
            'tipo' => TipoInsumo::query()->orderBy('nombre')->pluck('nombre', 'id')->toArray(),
        ];
    }

    protected function configureIndexQuery(Builder $query, Model $model): void
    {
        $query->with(['tipoInsumo', 'ultimoPrecioPorBien']);

        $latestUnitPriceSubquery = PreciosPorBien::query()
            ->selectRaw('precio + (precio * porcentaje_utilidad / 100)')
            ->whereColumn('bien_id', 'bienes.id')
            ->orderByDesc('fecha_registro')
            ->orderByDesc('id')
            ->limit(1);

        $query->reorder()
            ->orderBy('descripcion')
            ->orderByRaw('CASE WHEN (' . $latestUnitPriceSubquery->toSql() . ') IS NULL THEN 1 ELSE 0 END ASC', $latestUnitPriceSubquery->getBindings())
            ->orderBy($latestUnitPriceSubquery)
            ->orderBy('codigo');
    }

    protected function applyEntityDefaultValues(array &$defaults): void
    {
        if (array_key_exists('tipo', $defaults)) {
            $defaults['tipo'] = 1;
        }

        if (array_key_exists('relacionUnidades', $defaults)) {
            $defaults['relacionUnidades'] = 1;
        }
    }

    protected function afterSave(Request $request, Model $record, bool $isUpdate): void
    {
        $this->storeBienesPhoto($request, $record);
    }

    protected function additionalImportHeaderAliases(): array
    {
        return [
            'codigo_sap' => 'sap',
            'codigo_barras' => 'codigo',
            'unidad_almacen' => 'unidad',
            'unidad_entrega' => 'unidadUtil',
            'relacion' => 'relacionUnidades',
            'tipo_bien' => 'tipo',
            'tiempo_retorno' => 'tiempoRetorno',
            'meses_entrega' => 'mesesEntrega',
            'ubicacion_estante' => 'ubicacionEstante',
            'ubicacion_fila' => 'ubicacionFila',
        ];
    }

    protected function normalizeImportPayload(array $payload): array
    {
        foreach (['tipo', 'relacionUnidades', 'tiempoRetorno', 'mesesEntrega'] as $integerColumn) {
            if (array_key_exists($integerColumn, $payload)) {
                $payload[$integerColumn] = $this->normalizeImportedInteger($payload[$integerColumn]);
            }
        }

        if (array_key_exists('costo', $payload)) {
            $payload['costo'] = $this->normalizeImportedDecimal($payload['costo']);
        }

        if (array_key_exists('peso', $payload)) {
            $payload['peso'] = $this->normalizeImportedWeight($payload['peso']);
        }

        return $payload;
    }
}