<?php

namespace App\Modules\CatalogOffers\Http\Controllers;

use App\Facades\Settings;
use App\Http\Controllers\Controller;
use App\Modules\CatalogOffers\Http\Requests\StoreCatalogOfferRequest;
use App\Modules\CatalogOffers\Http\Requests\UpdateCatalogOfferRequest;
use App\Modules\CatalogOffers\Http\Resources\CatalogOfferList;
use App\Modules\CatalogOffers\Http\Resources\CatalogOfferView;
use Mtc\ContentManager\Facades\Media;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Mtc\MercuryDataModels\CatalogOffer;

class CatalogOfferController extends Controller
{
    public function index(Request $request): CatalogOfferList
    {
        $query = CatalogOffer::query();

        if ($request->filled('type')) {
            $query->ofType($request->input('type'));
        }

        return new CatalogOfferList($query->paginate());
    }

    public function show(CatalogOffer $catalogOffer): CatalogOfferView
    {
        return new CatalogOfferView($catalogOffer);
    }

    public function store(StoreCatalogOfferRequest $request): CatalogOfferView
    {
        $catalogOffer = DB::transaction(function () use ($request) {
            $this->enforceWeightCap($request->integer('weight', 0));
            return CatalogOffer::query()->create($request->input());
        });

        return new CatalogOfferView($catalogOffer);
    }

    public function update(UpdateCatalogOfferRequest $request, CatalogOffer $catalogOffer): CatalogOfferView
    {
        DB::transaction(function () use ($request, $catalogOffer) {
            $this->enforceWeightCap($request->integer('weight', 0), $catalogOffer->id);
            $catalogOffer->update($request->input());
            Media::setUsesForModel(
                $request->input('media', []),
                $catalogOffer,
                [
                    'primary' =>  true,
                    'allowed_sizes' => config('automotive.catalog_offers_sizes', [])
                ],
            );

            $rules = collect($request->input('rules', []));

            // Remove rules not in list
            $catalogOffer->rules()
                ->whereNotIn('id', $rules->pluck('id'))
                ->delete();

            // Add/Update rules - serialize array values to JSON
            $rules->each(function ($rule) use ($catalogOffer) {
                if (isset($rule['value']) && is_array($rule['value'])) {
                    $rule['value'] = json_encode($rule['value']);
                }
                $catalogOffer->rules()->updateOrCreate(['id' => $rule['id']], $rule);
            });
        });

        return new CatalogOfferView($catalogOffer);
    }

    public function destroy(Request $request, CatalogOffer $catalogOffer): CatalogOfferList
    {
        $catalogOffer->delete();
        return $this->index($request);
    }

    private function enforceWeightCap(int $weight, ?int $excludeId = null): void
    {
        if ($weight <= 0) {
            return;
        }

        $maxWeighted = (int) Settings::get('catalog-offer-max-weighted', 0);

        if ($maxWeighted <= 0) {
            return;
        }

        $currentWeighted = CatalogOffer::query()
            ->where('weight', '>', 0)
            ->when($excludeId, fn ($q) => $q->where('id', '!=', $excludeId))
            ->orderBy('weight')
            ->get();

        $overflow = $currentWeighted->count() - ($maxWeighted - 1);

        if ($overflow > 0) {
            $currentWeighted->take($overflow)->each->update(['weight' => 0]);
        }
    }
}
