<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Facades\Site;
use App\Traits\HasPlaceholderImage;
use Illuminate\Http\Resources\Json\JsonResource;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Page;

class DealershipList extends JsonResource
{
    use HasPlaceholderImage;
    use FranchiseData;

    public static $wrap = '';

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'dealerships' => $this->resource->map(fn(Dealership $dealership) => $this->mapDealership($dealership)),
            'franchises' => $this->franchiseNames(),
            'cities' => $this->cities(),
            'page' => new PageResource(
                Page::query()->where('slug', $request->input('page_slug', 'locations'))->first()
            ),
        ];
    }

    public function mapDealership(Dealership $dealership)
    {
        $coords = explode(',', $dealership->coordinates);
        $data = [
            'name' => $dealership->name,
            'address' => collect([
                $dealership->address1,
                $dealership->address2,
                $dealership->city,
                $dealership->county,
                $dealership->postcode,
            ])->filter()->implode(', '),
            'city' => $dealership->city,
            'county' => $dealership->county,
            'open' => $dealership->is_open,
            'openStart' => $dealership->opens_at,
            'openEnd' => $dealership->closes_at,
            'openDays' => [],
            'open_times' => $dealership->open_times,
            'notes' => $dealership->notes,
            'images' => $this->getGallery($dealership)?->toArray() ?: null,
            'coords' => [
                'lat' => $coords[0] ?? null,
                'lng' => $coords[1] ?? null,
            ],
            'url' => Site::dealershipUrl($dealership),
            'contact_no' => $dealership->contact_no,
            'email' => $dealership->email,
            'external_showroom_url' => $dealership->external_showroom_url,
            'external_service_url' => $dealership->attributeValues
                ->firstWhere('slug', 'external-service-url')
                ?->getValue(),
            'slug' => $dealership->slug,
            'departments' => $dealership->departments->keyBy('name'),
        ];

        if (Settings::get('dealerships-multiple-franchises')) {
            $this->resource->load([
                'franchises.primaryMediaUse.media'
            ]);
            $data['franchises'] = $dealership->franchises->map(fn($franchise) => $this->franchiseData($franchise));
        } else {
            $data['franchise'] = $this->franchiseData($dealership->franchise);
        }

        $secondary_department = $dealership->departments()
            ->where('name', '=', Settings::get('dealership-secondary-open-close-time-name'))
            ->first();

        if ($secondary_department) {
            $data['alt_open_time_name'] = $secondary_department->name;
            $data['alt_open_times'] = $this->getOpenTime($secondary_department->open_times);
        } else {
            $data['alt_open_time_name'] = Settings::get('dealership-secondary-open-close-time-name');
            $data['alt_open_times'] = Settings::get('dealership-second-open-times')
                ? $this->getOpenTime($dealership->alt_open_times)
                : [];
        }

        $tertiary_department = $dealership->departments()
            ->where('name', '=', Settings::get('dealership-tertiary-open-close-time-name'))
            ->first();

        if ($tertiary_department) {
            $data['second_alt_open_time_name'] = $tertiary_department->name;
            $data['second_alt_open_times'] = $this->getOpenTime($tertiary_department->open_times);
        } else {
            $data['second_alt_open_time_name'] = Settings::get('dealership-tertiary-open-close-time-name');
            $data['second_alt_open_times'] = Settings::get('dealership-third-open-times')
                ? $this->getOpenTime($dealership->second_alt_open_times)
                : [];
        }

        return $data;
    }

    private function getOpenTime($openTimes)
    {
        if (!empty($openTimes)) {
            foreach ($openTimes as $openTime) {
                if (!empty($openTime['open']) && !empty($openTime['close'])) {
                    return $openTimes;
                }
            }
        }

        return [];
    }

    protected function largeImageDimensions(): string
    {
        return 'full-width-banner';
    }

    protected function mediumImageDimensions(): string
    {
        return 'square';
    }

    protected function thumbnailImageDimensions(): string
    {
        return 'square';
    }

    private function cities(): array
    {
        return $this->resource->pluck('city')->unique()->filter()->toArray();
    }

    private function franchiseNames(): array
    {
        return $this->resource->pluck('franchise.name')->filter()->unique()->toArray();
    }

    private function franchiseData($franchise): array
    {
        if (empty($franchise)) {
            return [];
        }

        $data = $franchise->only([
            'logo',
            'name',
            'slug',
        ]);
        if (!empty($franchise->primaryMediaUse)) {
            $data['logo'] = $this->sizesForFranchise($franchise, $franchise->primaryMediaUse);
        }
        return $data;
    }
}
