<?php

namespace App;

use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Mtc\MercuryDataModels\BodyStyleType;
use Mtc\MercuryDataModels\CatalogOffer;
use Mtc\MercuryDataModels\ContentElement;
use Mtc\MercuryDataModels\Country;
use Mtc\MercuryDataModels\Currency;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\Franchise;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\GlobalContent;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\Menu;
use Mtc\MercuryDataModels\NewCar;
use Mtc\MercuryDataModels\OfferType;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\Property;
use Mtc\MercuryDataModels\PropertyCategory;
use Mtc\MercuryDataModels\Template;
use Mtc\MercuryDataModels\Setting;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\DealershipDepartment;
use Mtc\MercuryDataModels\VehicleAttribute;
use Mtc\MercuryDataModels\VehicleTrim;
use App\Facades\Settings;
use App\Models\ImportMap;

class OptionListRepository
{
    public function getForType(string $type, Request $request): Collection
    {
        return match ($type) {
            'primitives' => collect(config('pages.field_types', []))
                ->map(fn ($type) => App::make($type))
                ->values(),
            'dealerships' => Dealership::query()
                ->select(['id', 'name', 'slug', 'email'])
                ->when(
                    $request->input('franchise_id'),
                    fn ($query) => $query->where('franchise_id', $request->input('franchise_id'))
                )
                ->when(
                    $request->input('email_field') &&
                        str_starts_with($request->input('email_field'), 'attribute:'),
                    fn ($query) => $query->with([
                        'attributeValues' => fn ($subQuery) => $subQuery
                            ->where('slug', str_replace('attribute:', '', $request->input('email_field')))
                    ])
                )
                ->when(
                    $request->input('email_field') &&
                        str_starts_with($request->input('email_field'), 'department:'),
                    fn ($query) => $query->with([
                        'departments' => fn ($subQuery) => $subQuery
                            ->where('name', str_replace('department:', '', $request->input('email_field')))
                            ->whereNotNull('email')
                            ->where('email', '!=', '')
                    ])
                )
                ->orderBy('name')
                ->get()
                ->map(function (Dealership $dealership) use ($request) {
                    $emailField = $request->input('email_field');
                    $email = $dealership->email;

                    if ($emailField && str_starts_with($emailField, 'attribute:')) {
                        $attributeSlug = str_replace('attribute:', '', $emailField);
                        $attributeValue = $dealership->attributeValues->firstWhere('slug', $attributeSlug);
                        if ($attributeValue) {
                            $email = $attributeValue->value_text ?? $attributeValue->value;
                        }
                    } elseif ($emailField && str_starts_with($emailField, 'department:')) {
                        $email = $dealership->departments->first()?->email ?? $dealership->email;
                    }

                    return [
                        'id' => $dealership->id,
                        'name' => $dealership->name,
                        'slug' => $dealership->slug,
                        'email' => $email,
                    ];
                }),
            'franchises' => Franchise::query()
                ->select(['id', 'name', 'make_id'])
                ->orderBy('name')
                ->get(),
            'makes' => VehicleMake::query()
                ->with('filterIndex')
                ->orderBy('name')
                ->get()
                ->map(fn ($entry) => [
                    'id' => $entry->id,
                    'name' => $entry->name,
                    'slug' => $entry->slug,
                ]),
            'models' => VehicleModel::query()
                ->with('filterIndex')
                ->orderBy('name')
                ->when($request->input('filter'), fn ($query) => $query->where('make_id', $request->input('filter')))
                ->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'])
                ->orderBy('name')
                ->get(),
            'menus' => Menu::query()
                ->select(['id', 'title as name'])
                ->orderBy('name')
                ->get(),
            'templates' => Template::query()
                ->select(['id', 'name', 'id as value'])
                ->orderBy('name')
                ->active()
                ->get(),
            'page-categories' => collect(config('pages.page_types', []))
                ->filter(fn ($type) => Settings::get($type['config_key']))
                ->map(fn ($type) => [
                    'id' => $type['value'],
                    'name' => __('pages.types.' . $type['value']),
                ])
                ->values(),
            'currencies' => Currency::all()
                ->map(fn ($currency) => [
                    'name' => $currency->code,
                    'value' => $currency->code,
                    'id' => $currency->code,
                ]),
            'countries' => Country::all()
                ->map(fn ($country) => [
                    'name' => "[$country->code] $country->name",
                    'value' => $country->code,
                    'id' => $country->code,
                ]),
            'elements' => ContentElement::query()
                ->select(['id', 'title as name', 'id as value'])
                ->when($request->filled('filter'), fn ($query) => $query->where('category', $request->input('filter')))
                ->orderBy('name')
                ->active()
                ->get(),
            'global-content' => GlobalContent::query()
                ->select(['id', 'name'])
                ->orderBy('name')
                ->get(),
            'forms' => Form::query()
                ->select(['id', 'name', 'id as value'])
                ->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'])
                ->orderBy('name')
                ->get(),
            'new-cars' => NewCar::query()
                ->select(['id', 'name'])
                ->when($request->input('make_id'), fn ($query) => $query->where('make_id', $request->input('make_id')))
                ->when(
                    $request->input('model_id'),
                    fn ($query) => $query->where('model_id', $request->input('model_id'))
                )
                ->orderBy('name')
                ->get(),
            'trims' => VehicleTrim::query()
                ->select(['id', 'name'])
                ->when($request->input('make_id'), fn ($query) => $query->where('make_id', $request->input('make_id')))
                ->when(
                    $request->input('model_id'),
                    fn ($query) => $query->where('model_id', $request->input('model_id'))
                )
                ->orderBy('name')
                ->get(),
            'vehicles' => Vehicle::query()
                ->select(['id', 'title', 'slug', 'registration_number'])
                ->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(),
            'labels' => Label::query()
                ->select(['name', 'id'])
                ->when($request->input('filter') === 'active', fn ($query) => $query->where('active', 1))
                ->get(),
            'catalog-offers' => CatalogOffer::query()
                ->select(['name', 'id'])
                ->get(),
            'vehicle-attributes' => VehicleAttribute::query()
                ->where('model', 'vehicle')
                ->select(['id', 'name', 'slug as value'])
                ->orderBy('name')
                ->get(),
            'stock-providers' => $this->getStockProviders(),
            'offer-types' => OfferType::query()
                ->select(['id', 'name', 'slug as value'])
                ->orderBy('name')
                ->get(),
            'sort-options' => Setting::query()
                ->where('config_key', 'like', 'automotive-vehicle-sorting-%')
                ->select(['name', 'config_key'])
                ->orderBy('order')
                ->get()
                ->map(fn ($setting) => [
                    'id' => str_replace('automotive-vehicle-sorting-', '', $setting->config_key),
                    'name' => $setting->name,
                    'value' => str_replace('automotive-vehicle-sorting-', '', $setting->config_key),
                ]),

            default => Property::query()
                ->whereHas('category', fn ($query) => $query->where('slug', $type))
                ->active()
                ->select(['name', 'slug as value'])
                ->get(),
        };
    }

    /**
     * Get email field options for dealerships (main email + email type attributes)
     */
    public function getDealershipEmailFields(): Collection
    {
        $emailFields = collect([
            [
                'value' => 'email',
                'name' => 'Main Email Address',
            ],
        ]);

        $emailAttributes = VehicleAttribute::query()
            ->where('model', 'dealership')
            ->where('type', 'email')
            ->select(['slug', 'name'])
            ->orderBy('name')
            ->get()
            ->map(fn (VehicleAttribute $attribute) => [
                'value' => 'attribute:' . $attribute->slug,
                'name' => $attribute->name,
            ]);

        $departmentNames = DealershipDepartment::query()
            ->select('name')
            ->distinct()
            ->whereNotNull('email')
            ->where('email', '!=', '')
            ->orderBy('name')
            ->pluck('name')
            ->map(fn (string $name) => [
                'value' => 'department:' . $name,
                'name' => $name . ' Department Email',
            ]);

        return $emailFields->merge($emailAttributes)->merge($departmentNames);
    }

    private function getStockProviders(): Collection
    {
        if (tenant('type') === 'listing') {
            return collect();
        }

        $providers = Vehicle::query()
            ->select('stock_provider')
            ->distinct()
            ->whereNotNull('stock_provider')
            ->where('stock_provider', '!=', '')
            ->orderBy('stock_provider')
            ->get();

        $importMapIds = $providers
            ->filter(fn ($item) => str_starts_with($item->stock_provider, 'import-map-'))
            ->map(fn ($item) => (int) str_replace('import-map-', '', $item->stock_provider))
            ->values();

        $importMapNames = $importMapIds->isNotEmpty()
            ? ImportMap::whereIn('id', $importMapIds)->pluck('name', 'id')
            : collect();

        $integrations = App::make(IntegrationRepository::class)->getAllForType('stock');

        return $providers
            ->map(function ($item) use ($importMapNames, $integrations) {
                return [
                    'id' => $item->stock_provider,
                    'name' => $this->resolveStockProviderName(
                        $item->stock_provider,
                        $importMapNames,
                        $integrations,
                    ),
                    'value' => $item->stock_provider,
                ];
            })
            ->prepend([
                'id' => 'default',
                'name' => 'Default (no stock provider)',
                'value' => 'default',
            ]);
    }

    private function resolveStockProviderName(
        string $stockProvider,
        Collection $importMapNames,
        Collection $integrations,
    ): string {
        if (str_starts_with($stockProvider, 'import-map-')) {
            $id = (int) str_replace('import-map-', '', $stockProvider);

            return $importMapNames->get($id, $stockProvider);
        }

        if ($integrations->has($stockProvider) && isset($integrations[$stockProvider]['class'])) {
            return App::make($integrations[$stockProvider]['class'])->name();
        }

        return $stockProvider;
    }
}
