<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Filter\FilterIndex;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\Franchise;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\GlobalContent;
use Mtc\MercuryDataModels\Menu;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\Property;
use Mtc\MercuryDataModels\PropertyCategory;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleOffer;

class FormViewResource extends JsonResource
{
    private array $assignedValues = [];

    public function setValues(array $values)
    {
        $this->assignedValues = $values;
        return $this;
    }

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    #[\Override]
    public function toArray($request)
    {
        if (!$this->resource) {
            return [];
        }

        return [
            'id' => $this->resource->id,
            'title' => $this->resource->name,
            'success_message' => $this->resource->success_message,
            'button_text' => $this->resource->button_text,
            'partial_submissions' => $this->resource->data['partial_submissions'] ?? false,
            'sections' => $this->resource->sections->map(fn($section) => [
                'id' => $section->id,
                'name' => $section->name,
                'settings' => $section->settings ?? [],
                'segments' => collect($section->segments ?? [])
                    ->map(fn($segment) => [
                        'name' => $segment,
                        'questions' => $section->questions
                            ->where('segment', $segment)
                            ->map(fn($question) => [
                                'id' => $question->id,
                                'type' => $this->questionType($question->type),
                                'name' => $question->name,
                                'value' => $this->assignedValues[$question->type] ?? null,
                                'choices' => $this->questionChoices($question),
                                'placeholder' => $question->placeholder,
                                'description' => $question->description,
                                'cssId' => $question->data['cssId'] ?? null,
                                'cssClass' => $question->data['cssClass'] ?? null,
                                'multiple' => $question->data['allow_multiple'] ?? false,
                                'required' => in_array('required', (array)$question->validation),
                                'includeDraft' => $question->data['include_in_draft'] ?? false
                            ])->values(),
                    ]),
            ]),
        ];
    }

    private function questionType(string $fieldType): string
    {
        return match ($fieldType) {
            'offer_id',
            'property_id',
            'page_id',
            'vehicle_id',
            'valuation_id',
            'car_configuration_id',
            'car_configuration_model_id',
            'new_car_id',
            'dealership_id' => 'hidden',
            default => $fieldType,
        };
    }

    private function questionChoices(object $question): array|null
    {
        if (!empty($question->data['meta']['options']['items'])) {
            return $question->data['meta']['options']['items'];
        }

        $options = $question->data['meta']['options'] ?? [];

        // Allow franchise_id from setValues() to filter dealerships
        if (isset($this->assignedValues['franchise_id']) && empty($options['franchiseId'])) {
            $options['franchiseId'] = $this->assignedValues['franchise_id'];
        }

        return $this->getChoicesFromDataSource($options['source'] ?? null, $options)
            ->map(fn($entry) => [
                 'id' => $entry->id,
                 'name' => $entry->name,
                 'value' => $entry->id,
            ])
            ->toArray()
            ?? null;
    }

    private function getChoicesFromDataSource(?string $type, array $options = []): ?Collection
    {
        if (empty($type)) {
            return collect();
        }

        return match ($type) {
            'dealerships' => Dealership::query()
                ->select(['id', 'name', 'order'])
                ->where('active', 1)
                ->when(
                    Settings::get('dealerships-sort-order', 'name') === 'order',
                    fn($query) => $query->orderBy('order'),
                    fn($query) => $query->orderBy('name')
                )
                ->when(
                    !empty($options['franchiseId']),
                    fn($query) => $query->when(
                        Settings::get('dealerships-multiple-franchises'),
                        fn($franchiseQuery) => $franchiseQuery->whereHas(
                            'franchises', fn($subQuery) => $subQuery->where('franchise_id', $options['franchiseId'])
                        ),
                        fn($franchiseQuery) => $franchiseQuery->where('franchise_id', $options['franchiseId']),
                    )
                )
                ->orderBy('name')
                ->get()
                ->each(fn(Dealership $entry) => $entry->setHidden(['open_times', 'primaryDepartment', 'order'])),
            'franchises' => Franchise::query()
                ->select(['id', 'name'])
                ->orderBy('name')
                ->get(),
            'makes' => VehicleMake::query()
                ->with('filterIndex')
                ->orderBy('name')
                ->get()
                ->map(fn ($entry) => [
                    'id' => $entry->id,
                    'name' => $entry->name,
                    'slug' => $entry->slug,
                ]),
            'fuel-types' => FuelType::query()
                ->with('filterIndex')
                ->orderBy('name')
                ->get()
                ->map(fn ($entry) => [
                    'id' => $entry->id,
                    'name' => $entry->name,
                    'slug' => $entry->slug,
                ]),
            'body-styles' => BodyStyleType::query()
                ->with('filterIndex')
                ->orderBy('name')
                ->get()
                ->map(fn ($entry) => [
                    'id' => $entry->id,
                    'name' => $entry->name,
                    'slug' => $entry->slug,
                ]),
            'pages' => Page::query()
                ->select(['id', 'title as name'])
                ->active()
                ->orderBy('name')
                ->get(),
            'menus' => Menu::query()
                ->select(['id', 'title as name'])
                ->active()
                ->orderBy('name')
                ->get(),
            'global-content' => GlobalContent::query()
                ->select(['id', 'name'])
                ->orderBy('name')
                ->get(),
            'forms' => Form::query()
                ->select(['id', 'name'])
                ->where('is_active', 1)
                ->orderBy('name')
                ->get(),
            'blog-pages' => Page::query()
                ->select(['id', 'title as name'])
                ->where('category', 'blog')
                ->orderBy('name')
                ->get(),
            'news-pages' => Page::query()
                ->select(['id', 'title as name'])
                ->where('category', 'news')
                ->orderBy('name')
                ->get(),
            'offers' => VehicleOffer::query()
                ->select(['id', 'name'])
                ->active()
                ->orderBy('name')
                ->get(),
            'vehicles' => Vehicle::query()
                ->select(['id', 'title', 'slug', 'registration_number'])
                ->active()
                ->orderBy('title')
                ->get()
                ->map(fn (Vehicle $vehicle) => [
                    'id' => $vehicle->id,
                    'name' => collect([
                        $vehicle->title,
                        $vehicle->registration_number,
                        $vehicle->slug,
                    ])->implode(' - '),
                ]),
            'taxonomies' => PropertyCategory::query()
                ->active()
                ->select(['id', 'name', 'slug as value'])
                ->get(),
            default => Property::query()
                ->whereHas('category', fn ($query) => $query->where('slug', $type))
                ->active()
                ->select(['name', 'slug as value'])
                ->get(),
        };
    }

    private function getIndexType(string $type): string
    {
        return match ($type) {
            'makes' => 'make',
            'fuel-types' => 'fuel_type',
            'body-styles' => 'body_type',
        };
    }
}
