<?php

namespace App\Console\Commands;

use App\Services\MeilisearchService;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Mtc\MercuryDataModels\Vehicle;

class SyncVehiclesToMeilisearch extends Command
{
    private const SCHEDULED_LOOKBACK_HOURS = 3;

    protected $signature = 'meilisearch:sync-vehicles
                            {--fresh : Delete all documents and re-index from scratch}
                            {--configure : Only configure index settings without syncing data}
                            {--scheduled= : Indicate the command is run from the scheduler (only recently updated)}
                            {--batch-size=500 : Number of vehicles to process per batch}';

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

    public function handle(MeilisearchService $meilisearch): int
    {
        if ($this->option('scheduled') && tenant('type') !== 'listing') {
            $this->info('Scheduled indexing supported only for listing sites');
            return self::SUCCESS;
        }

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

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

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

        return self::SUCCESS;
    }

    private function configureIndex(MeilisearchService $meilisearch): void
    {
        $this->info("Configuring Meilisearch index: {$meilisearch->getIndexName()}");
        $meilisearch->configureIndex();
        $this->info('Index configured successfully.');
    }

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

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

    private function syncVehicles(MeilisearchService $meilisearch): void
    {
        $batchSize = (int) $this->option('batch-size');
        $index = $meilisearch->getVehicleIndex();

        if ($this->option('scheduled')) {
            $meilisearch->removeRecentlyDeletedVehicles(self::SCHEDULED_LOOKBACK_HOURS);
            $meilisearch->removeRecentlyUnpublishedVehicles(self::SCHEDULED_LOOKBACK_HOURS);
        }

        $query = Vehicle::query()
            ->active()
            ->when(
                $this->option('scheduled'),
                fn($query) => $query->where('updated_at', '>=', Carbon::now()->subHours(self::SCHEDULED_LOOKBACK_HOURS))
            );

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

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

        $query->clone()
            ->with(MeilisearchService::VEHICLE_RELATIONS)
            ->chunk($batchSize, function ($vehicles) use ($meilisearch, $index, $progressBar) {
                $documents = $vehicles->map(fn($vehicle) => $meilisearch->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.');
    }
}
