<?php

namespace App;

use App\Facades\Settings;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Mtc\MercuryDataModels\CarConfiguratorModel;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\NewCar;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleTrim;

class SiteRepository
{
    public function vehicleUrl(Vehicle $vehicle, bool $withAccess = false, bool $absolute = true): ?string
    {
        try {
            $urlPath = $vehicle->urlPath();
            if ($withAccess) {
                $urlPath .= $this->accessParam($vehicle);
            }

            return $absolute ? $this->baseUrl(Settings::get('url-path-include-www')) . $urlPath : $urlPath;
        } catch (ModelNotFoundException $exception) {
            return null;
        }
    }

    public function pageUrl(Page $page, bool $withAccess = false, bool $absolute = true): ?string
    {
        return $this->buildUrl(
            $page->urlPath() === '/home' ? '/' : $page->urlPath(),
            $page,
            $withAccess,
            $absolute,
            Settings::get('url-path-include-www')
        );
    }

    public function offerUrl(VehicleOffer $offer, bool $withAccess = false, bool $absolute = true): ?string
    {
        return $this->buildUrl(
            $offer->urlPath(),
            $offer,
            $withAccess,
            $absolute,
            Settings::get('url-path-include-www')
        );
    }

    public function configuratorUrl(CarConfiguratorModel $car, bool $withAccess = false, bool $absolute = true): ?string
    {
        return $this->buildUrl($car->urlPath(), $car, $withAccess, $absolute, Settings::get('url-path-include-www'));
    }

    public function newCarUrl(NewCar $newCar, bool $withAccess = false, bool $absolute = true): ?string
    {
        return $this->buildUrl(
            $newCar->urlPath(),
            $newCar,
            $withAccess,
            $absolute,
            Settings::get('url-path-include-www')
        );
    }

    public function trimUrl(VehicleTrim $trim, bool $withAccess = false, bool $absolute = true): ?string
    {
        return $this->buildUrl(
            $trim->urlPath(),
            $trim,
            $withAccess,
            $absolute,
            Settings::get('url-path-include-www')
        );
    }

    public function url(string $endpoint = '', bool $absolute = true): ?string
    {
        return $this->buildUrl('/' . ltrim($endpoint, '/'), null, false, $absolute);
    }

    public function baseUrl(?bool $includeWww = false): string
    {
        $domain = tenant()->domains()
            ->orderByDesc('primary')
            ->firstOrFail();

        $protocol = config('app.env') === 'local' ? 'http://' : 'https://';

        if ($includeWww && !str_starts_with($domain->domain, 'www')) {
            return $protocol . 'www.' . $domain->domain;
        }

        return $protocol . $domain->domain;
    }

    private function accessParam(Model $model): string
    {
        return  '?' . http_build_query([
            'a' => base64_encode($model->id . '-' . $model->slug),
        ]);
    }

    private function buildUrl(
        string $path,
        ?Model $model = null,
        bool $withAccess = false,
        bool $absolute = true,
        ?bool $includeWww = false,
    ): ?string {
        try {
            if ($withAccess && $model) {
                $path .= $this->accessParam($model);
            }

            return $absolute ? $this->baseUrl($includeWww) . $path : $path;
        } catch (ModelNotFoundException $exception) {
            return null;
        }
    }
}
