<?php

namespace App\Services;

use App\Models\Bien;
use App\Models\TipoInsumo;
use App\Support\FallbackLabels;

class GraficasService
{
    /**
     * @return array<string, mixed>
     */
    public function buildChartsData(): array
    {
        $typeLabels = $this->resolveTypeLabels();

        $valueRows = Bien::query()
            ->selectRaw('tipo, COALESCE(SUM(COALESCE(costo, 0) * COALESCE(cantidadUnidadUtil, 0)), 0) as total_valor')
            ->groupBy('tipo')
            ->orderBy('tipo')
            ->get();

        $stockRows = Bien::query()
            ->selectRaw('tipo, COALESCE(SUM(cantidadUnidadUtil), 0) as total_stock')
            ->groupBy('tipo')
            ->orderBy('tipo')
            ->get();

        $outputRows = Bien::query()
            ->select(['descripcion', 'cantidadEntregada'])
            ->orderByDesc('cantidadEntregada')
            ->limit(5)
            ->get();

        $locationRows = Bien::query()
            ->selectRaw('COALESCE(NULLIF(TRIM(ubicacionEstante), ""), "Sin Asignar") as estante')
            ->selectRaw('COALESCE(SUM(cantidadUnidadUtil), 0) as total_stock')
            ->groupBy('estante')
            ->orderBy('estante')
            ->get();

        $labelsValor = [];
        $dataValor = [];
        foreach ($valueRows as $row) {
            $tipo = (int) ($row->tipo ?? 0);
            $labelsValor[] = $typeLabels[$tipo] ?? 'Otros';
            $dataValor[] = (float) ($row->total_valor ?? 0);
        }

        $labelsStock = [];
        $dataStock = [];
        foreach ($stockRows as $row) {
            $tipo = (int) ($row->tipo ?? 0);
            $labelsStock[] = $typeLabels[$tipo] ?? 'Otros';
            $dataStock[] = (int) ($row->total_stock ?? 0);
        }

        $labelsOutput = [];
        $dataOutput = [];
        foreach ($outputRows as $row) {
            $labelsOutput[] = (string) ($row->descripcion ?? 'Sin descripcion');
            $dataOutput[] = (int) ($row->cantidadEntregada ?? 0);
        }

        $labelsLocation = [];
        $dataLocation = [];
        foreach ($locationRows as $row) {
            $labelsLocation[] = 'Estante ' . (string) ($row->estante ?? 'Sin Asignar');
            $dataLocation[] = (int) ($row->total_stock ?? 0);
        }

        return [
            'labelsValor' => $labelsValor,
            'dataValor' => $dataValor,
            'labelsStock' => $labelsStock,
            'dataStock' => $dataStock,
            'labelsOutput' => $labelsOutput,
            'dataOutput' => $dataOutput,
            'labelsLocation' => $labelsLocation,
            'dataLocation' => $dataLocation,
            'totalValorInventario' => array_sum($dataValor),
            'totalUnidadesStock' => array_sum($dataStock),
            'totalTopSalidas' => array_sum($dataOutput),
        ];
    }

    /**
     * @return array<int, string>
     */
    private function resolveTypeLabels(): array
    {
        $labels = TipoInsumo::query()
            ->orderBy('id')
            ->pluck('nombre', 'id')
            ->mapWithKeys(fn (string $name, int|string $id): array => [(int) $id => $name])
            ->toArray();

        if ($labels === []) {
            return FallbackLabels::BIEN_TYPE_LABELS;
        }

        return $labels;
    }
}
