<?php

namespace App\Console\Commands;

use App\Facades\Feature;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Str;
use Meilisearch\Client;
use Mtc\MercuryDataModels\Vehicle;

class SyncVehiclesToMeilisearch extends Command
{
    protected $signature = 'meilisearch:sync-vehicles
                            {--fresh : Delete all documents and re-index from scratch}
                            {--configure : Only configure index settings without syncing data}
                            {--batch-size=500 : Number of vehicles to process per batch}';

    protected $description = 'Sync vehicles to Meilisearch index for fast filtering';

    private ?Client $client = null;

    public function handle(): int
    {
        $indexName = $this->getIndexName();

        if ($this->option('fresh')) {
            $this->deleteAllDocuments($indexName);
        }

        if ($this->option('configure')) {
            $this->configureIndex($indexName);
            return self::SUCCESS;
        }

        $this->configureIndex($indexName);
        $this->syncVehicles($indexName);

        return self::SUCCESS;
    }

    private function getClient(): Client
    {
        if ($this->client === null) {
            $this->client = new Client(
                Config::get('meilisearch.host'),
                Config::get('meilisearch.key')
            );
        }

        return $this->client;
    }

    private function getIndexName(): string
    {
        return tenant('id') . '_vehicles';
    }

    private function configureIndex(string $indexName): void
    {
        $this->info("Configuring Meilisearch index: {$indexName}");

        $client = $this->getClient();

        try {
            $client->createIndex($indexName, ['primaryKey' => 'id']);
        } catch (\Exception $e) {
            // Index may already exist
        }

        $index = $client->index($indexName);

        $index->updateFilterableAttributes($this->getFilterableAttributes());
        $index->updateSortableAttributes($this->getSortableAttributes());
        $index->updateSearchableAttributes($this->getSearchableAttributes());

        // Set pagination limit to support large inventories (default is 1000)
        $index->updatePagination([
            'maxTotalHits' => 200000,
        ]);

        $this->info('Index configured successfully.');
    }

    private function deleteAllDocuments(string $indexName): void
    {
        $this->info("Deleting all documents from index: {$indexName}");

        try {
            $index = $this->getClient()->index($indexName);
            $index->deleteAllDocuments();
            $this->info('All documents deleted.');
        } catch (\Exception $e) {
            $this->warn("Could not delete documents: {$e->getMessage()}");
        }
    }

    private function syncVehicles(string $indexName): void
    {
        $batchSize = (int) $this->option('batch-size');
        $index = $this->getClient()->index($indexName);

        $totalCount = Vehicle::query()->count();
        $this->info("Syncing {$totalCount} vehicles to Meilisearch...");

        $progressBar = $this->output->createProgressBar($totalCount);
        $progressBar->start();

        Vehicle::query()
            ->with([
                'make',
                'model',
                'bodyStyle',
                'transmission',
                'fuelType',
                'dealership.franchise',
                'labels',
                'features',
                'attributeValues',
            ])
            ->chunk($batchSize, function ($vehicles) use ($index, $progressBar) {
                $documents = $vehicles->map(fn($vehicle) => $this->transformVehicle($vehicle))->toArray();

                try {
                    $index->addDocuments($documents);
                } catch (\Exception $e) {
                    $this->error("Error syncing batch: {$e->getMessage()}");
                }

                $progressBar->advance(count($vehicles));
            });

        $progressBar->finish();
        $this->newLine();
        $this->info('Vehicle sync completed.');
    }

    private function transformVehicle(Vehicle $vehicle): array
    {
        $stockStatus = $vehicle->attributeValues
            ->where('slug', 'stock_status')
            ->first()?->value;

        return [
            'id' => $vehicle->id,
            'tenant_id' => tenant('id'),
            'title' => $vehicle->title,
            'derivative' => $vehicle->derivative,
            'registration_number' => $vehicle->registration_number,
            'slug' => $vehicle->slug,

            // Make
            'make_id' => $vehicle->make_id,
            'make_name' => $vehicle->make?->name,
            'make_slug' => $vehicle->make?->slug,

            // Model
            'model_id' => $vehicle->model_id,
            'model_name' => $vehicle->model?->name,
            'model_slug' => $vehicle->model?->slug,

            // Body style
            'body_style_id' => $vehicle->body_style_id,
            'body_style_slug' => $vehicle->bodyStyle?->slug,

            // Transmission
            'transmission_id' => $vehicle->transmission_id,
            'transmission_slug' => $vehicle->transmission?->slug,

            // Fuel type
            'fuel_type_id' => $vehicle->fuel_type_id,
            'fuel_type_slug' => $vehicle->fuelType?->slug,

            // Drivetrain
            'drivetrain_id' => $vehicle->drivetrain_id,

            // Dealership
            'dealership_id' => $vehicle->dealership_id,
            'dealership_slug' => $vehicle->dealership?->slug,

            // Franchise
            'franchise_id' => $vehicle->dealership?->franchise_id,

            // Colour
            'colour' => $vehicle->colour,
            'colour_slug' => $vehicle->colour ? Str::slug($vehicle->colour) : null,

            // Status flags
            'is_new' => $vehicle->is_new,
            'is_published' => $vehicle->is_published,
            'is_sold' => $vehicle->is_sold,
            'is_reserved' => $vehicle->is_reserved,
            'is_demo' => $vehicle->is_demo,
            'is_vat_applicable' => $vehicle->is_vat_applicable,

            // Type
            'type' => $vehicle->type,
            'vehicle_category' => $vehicle->vehicle_category ?? null,

            // Pricing
            'price' => (float) $vehicle->price,
            'monthly_price' => (float) $vehicle->monthly_price,
            'original_price' => $vehicle->original_price ? (float) $vehicle->original_price : null,

            // Technical specs
            'manufacture_year' => (int) $vehicle->manufacture_year,
            'odometer_km' => (int) $vehicle->odometer_km,
            'odometer_mi' => (int) $vehicle->odometer_mi,
            'engine_size_cc' => (int) $vehicle->engine_size_cc,
            'door_count' => (int) $vehicle->door_count,
            'seat_count' => (int) $vehicle->seats,
            'co2' => (int) $vehicle->co2,

            // Labels and features
            'label_ids' => $vehicle->labels->pluck('id')->toArray(),
            'feature_ids' => $vehicle->features->pluck('id')->toArray(),

            // Stock status
            'stock_status' => $stockStatus,

            // Trim
            'trim' => $vehicle->trim,
            'trim_slug' => $vehicle->trim ? Str::slug($vehicle->trim) : null,

            // Description
            'description' => $vehicle->description,

            // Timestamps
            'created_at' => $vehicle->created_at?->timestamp,
            'published_at' => $vehicle->published_at?->timestamp,

            // Geolocation for distance filtering
            '_geo' => $vehicle->lat && $vehicle->lng ? [
                'lat' => (float) $vehicle->lat,
                'lng' => (float) $vehicle->lng,
            ] : null,
        ];
    }

    private function getFilterableAttributes(): array
    {
        return [
            'tenant_id',
            'make_id',
            'make_slug',
            'model_id',
            'model_slug',
            'body_style_id',
            'body_style_slug',
            'transmission_id',
            'transmission_slug',
            'fuel_type_id',
            'fuel_type_slug',
            'drivetrain_id',
            'dealership_id',
            'dealership_slug',
            'franchise_id',
            'colour',
            'colour_slug',
            'is_new',
            'is_published',
            'is_sold',
            'is_reserved',
            'is_demo',
            'is_vat_applicable',
            'type',
            'vehicle_category',
            'price',
            'monthly_price',
            'manufacture_year',
            'odometer_km',
            'odometer_mi',
            'engine_size_cc',
            'door_count',
            'seat_count',
            'co2',
            'label_ids',
            'feature_ids',
            'stock_status',
            'trim_slug',
            '_geo',
        ];
    }

    private function getSortableAttributes(): array
    {
        return [
            'created_at',
            'price',
            'monthly_price',
            'manufacture_year',
            'odometer_km',
            'odometer_mi',
        ];
    }

    private function getSearchableAttributes(): array
    {
        return [
            'title',
            'derivative',
            'registration_number',
            'make_name',
            'model_name',
            'colour',
            'trim',
            'description',
        ];
    }
}
