<?php

namespace App\Services;

use App\Models\Bien;
use App\Models\SolicitudBien;
use Illuminate\Support\Facades\Schema;

class AsignacionSupportService
{
    private const BIEN_TYPE_LABELS = [
        1 => 'Equipo',
        2 => 'Herramienta',
        3 => 'Dotacion',
        4 => 'Consumible',
        5 => 'Repuesto',
        6 => 'Material oficina',
        7 => 'Material medico',
    ];

    public function formatFechaCorta(mixed $fecha): string
    {
        if (! filled($fecha)) {
            return '';
        }

        try {
            return date('d/m/Y', strtotime((string) $fecha));
        } catch (\Throwable) {
            return '';
        }
    }

    public function formatBienTipo(mixed $tipo): string
    {
        return self::BIEN_TYPE_LABELS[(int) ($tipo ?? 0)] ?? 'Sin tipo';
    }

    public function formatBienTipoMarca(mixed $tipo, mixed $marca): string
    {
        $tipoLabel = $this->formatBienTipo($tipo);
        $marcaLabel = trim((string) ($marca ?? ''));

        return $marcaLabel === '' ? $tipoLabel : $tipoLabel . ' / ' . $marcaLabel;
    }

    /**
     * @param array<string, mixed> $referenciasPersonal
     */
    public function formatReferenciaPersonal(string $cedula, array $referenciasPersonal): string
    {
        $cedula = trim($cedula);

        if ($cedula === '') {
            return '';
        }

        $persona = $referenciasPersonal[$cedula] ?? null;
        $nombre = trim((string) data_get($persona, 'nombre', ''));

        if ($nombre === '') {
            return $cedula;
        }

        return $cedula . ' - ' . $nombre;
    }

    /**
     * @return array{stock_antes:int, stock_despues:int}
     */
    public function aplicarDevolucionBien(Bien $bien, int $cantidadDevolver, string $cedulaEditor, mixed $fechaOperacion): array
    {
        $cantidadUnidadAntes = (int) ($bien->cantidadUnidad ?? 0);
        $stockAntes = (int) ($bien->cantidadUnidadUtil ?? 0);
        $cantidadEntregadaAntes = (int) ($bien->cantidadEntregada ?? 0);
        $relacionUnidades = max(1, (int) ($bien->relacionUnidades ?? 1));

        $stockDespues = $stockAntes + $cantidadDevolver;
        $cantidadUnidadDespues = (int) floor($stockDespues / $relacionUnidades);
        $cantidadEntregadaDespues = max(0, $cantidadEntregadaAntes - $cantidadDevolver);
        $diferenciaUnidades = $cantidadUnidadDespues - $cantidadUnidadAntes;
        $cantidadRotacion = Schema::hasColumn('bienes', 'cantidadRotacion')
            ? (int) ($bien->getAttribute('cantidadRotacion') ?? 0) + $diferenciaUnidades
            : null;

        $updateBien = [
            'cantidadUnidad' => $cantidadUnidadDespues,
            'cantidadUnidadUtil' => $stockDespues,
            'cantidadEntregada' => $cantidadEntregadaDespues,
            'fechaActualizacion' => $fechaOperacion,
            'cedulaEditor' => $cedulaEditor,
        ];

        if ($cantidadRotacion !== null) {
            $updateBien['cantidadRotacion'] = $cantidadRotacion;
        }

        $bien->update($updateBien);

        return [
            'stock_antes' => $stockAntes,
            'stock_despues' => $stockDespues,
        ];
    }

    public function loadBienesEnStock()
    {
        return Bien::query()
            ->select([
                'codigo',
                'descripcion',
                'marca',
                'tipo',
                'cantidadUnidad',
                'unidad',
                'cantidadUnidadUtil',
                'unidadUtil',
                'cantidadEntregada',
            ])
            ->where('cantidadUnidadUtil', '>', 0)
            ->orderBy('descripcion')
            ->get();
    }

    public function mapBienesData(mixed $bienes)
    {
        return $bienes->map(function (Bien $bien): array {
            return [
                'codigo' => $bien->codigo,
                'descripcion' => $bien->descripcion,
                'marca' => $bien->marca,
                'tipo' => self::BIEN_TYPE_LABELS[(int) ($bien->tipo ?? 0)] ?? 'Sin tipo',
                'almacenado' => trim(((string) ($bien->cantidadUnidad ?? 0)) . ' ' . ((string) ($bien->unidad ?? ''))),
                'en_stock' => trim(((string) ($bien->cantidadUnidadUtil ?? 0)) . ' UNIDADES'),
                'stock_disponible' => (int) ($bien->cantidadUnidadUtil ?? 0),
                'entregado' => trim(((string) ($bien->cantidadEntregada ?? 0)) . ' UNIDADES'),
            ];
        })->values();
    }

    /**
     * @return array{solicitud:?SolicitudBien,items:array<int,array<string,mixed>>,summary:array<string,int>}
     */
    public function preloadSolicitudForAlimentos(string $cedulaSolicitante, mixed $bienesData): array
    {
        $cedulaSolicitante = trim($cedulaSolicitante);

        if ($cedulaSolicitante === '') {
            return [
                'solicitud' => null,
                'items' => [],
                'summary' => [
                    'requested_items' => 0,
                    'loaded_items' => 0,
                    'omitted_items' => 0,
                ],
            ];
        }

        $solicitud = SolicitudBien::query()
            ->where('solicitante_cedula', $cedulaSolicitante)
            ->whereIn('estado', ['pendiente', 'generada'])
            ->orderByDesc('fecha_solicitud')
            ->orderByDesc('id')
            ->first();

        if (! $solicitud) {
            return [
                'solicitud' => null,
                'items' => [],
                'summary' => [
                    'requested_items' => 0,
                    'loaded_items' => 0,
                    'omitted_items' => 0,
                ],
            ];
        }

        $catalogo = collect($bienesData)
            ->filter(fn (mixed $bien): bool => is_array($bien) && trim((string) ($bien['codigo'] ?? '')) !== '')
            ->mapWithKeys(fn (array $bien): array => [(string) $bien['codigo'] => $bien])
            ->all();

        $detalle = collect(is_array($solicitud->detalle_json) ? $solicitud->detalle_json : [])
            ->filter(fn (mixed $item): bool => is_array($item))
            ->values();

        $items = [];

        foreach ($detalle as $detalleItem) {
            $codigo = trim((string) ($detalleItem['codigo'] ?? ''));

            if ($codigo === '' || ! array_key_exists($codigo, $catalogo)) {
                continue;
            }

            $bien = $catalogo[$codigo];
            $stockDisponible = (int) ($bien['stock_disponible'] ?? 0);

            if ($stockDisponible < 1) {
                continue;
            }

            $cantidadSolicitada = max(1, (int) ($detalleItem['cantidad'] ?? 1));

            $items[] = [
                'codigo' => $codigo,
                'almacenado' => (string) ($bien['almacenado'] ?? ''),
                'entregado' => (string) ($bien['entregado'] ?? ''),
                'descripcion' => (string) ($bien['descripcion'] ?? ($detalleItem['descripcion'] ?? '')),
                'marca' => (string) ($bien['marca'] ?? ''),
                'tipo' => (string) ($bien['tipo'] ?? ($detalleItem['tipo'] ?? '')),
                'stock' => (string) ($bien['stock'] ?? ($bien['en_stock'] ?? '')),
                'stock_disponible' => $stockDisponible,
                'cantidad' => min($cantidadSolicitada, $stockDisponible),
                'observacion' => '',
            ];
        }

        return [
            'solicitud' => $solicitud,
            'items' => $items,
            'summary' => [
                'requested_items' => $detalle->count(),
                'loaded_items' => count($items),
                'omitted_items' => max(0, $detalle->count() - count($items)),
            ],
        ];
    }
}
