<?php

namespace App\Http\Controllers;

use App\Facades\Settings;
use App\Http\Requests\DealBuilderDeliverySettingsRequest;
use App\Http\Resources\DealBuilderDeliverySettingsResource;
use Mtc\MercuryDataModels\DealBuilder\GlobalDeliveryLocation;
use Mtc\MercuryDataModels\DealBuilder\GlobalDeliveryPriceTier;
use Mtc\MercuryDataModels\Services\LocatingService;

class DealBuilderDeliverySettingsController extends Controller
{
    public function show(): DealBuilderDeliverySettingsResource
    {
        return new DealBuilderDeliverySettingsResource([
            'allow_home_delivery' => (bool) Settings::get('deal-builder-delivery-allow-home', false),
            'max_delivery_distance' => Settings::get('deal-builder-delivery-max-distance'),
            'locations' => GlobalDeliveryLocation::all()->toArray(),
            'price_tiers' => GlobalDeliveryPriceTier::all()->toArray(),
        ]);
    }

    public function update(
        DealBuilderDeliverySettingsRequest $request
    ): DealBuilderDeliverySettingsResource {
        $this->ensureSettingsExist();

        Settings::update('deal-builder-delivery-allow-home', $request->input('allow_home_delivery', false));
        Settings::update('deal-builder-delivery-max-distance', $request->input('max_delivery_distance'));

        $this->syncLocations($request->input('locations', []));
        $this->replacePriceTiers($request->input('price_tiers', []));

        return $this->show();
    }

    private function ensureSettingsExist(): void
    {
        if (! Settings::exists('deal-builder-delivery-allow-home')) {
            (new \Database\Seeders\Tenant\DealBuilderDeliverySettingSeeder())->run();
        }
    }

    private function syncLocations(array $locations): void
    {
        $incomingIds = collect($locations)->pluck('id')->filter()->all();

        GlobalDeliveryLocation::whereNotIn('id', $incomingIds)->delete();

        foreach ($locations as $locationData) {
            $this->geocodeLocation($locationData);

            if (! empty($locationData['id'])) {
                $location = GlobalDeliveryLocation::find($locationData['id']);
                $location?->fill($locationData)->save();
            } else {
                unset($locationData['id']);
                GlobalDeliveryLocation::create($locationData);
            }
        }
    }

    private function geocodeLocation(array &$locationData): void
    {
        if (empty($locationData['postcode'])) {
            return;
        }

        try {
            $locator = app(LocatingService::class)->locate($locationData['postcode']);
            $locationData['lat'] = $locator->lat();
            $locationData['lng'] = $locator->lng();
        } catch (\Exception $e) {
            // Geocoding failure is non-fatal; coordinates remain null
        }
    }

    private function replacePriceTiers(array $tiers): void
    {
        GlobalDeliveryPriceTier::query()->delete();

        foreach ($tiers as $tier) {
            GlobalDeliveryPriceTier::create($tier);
        }
    }
}
