<?php

namespace Modules\Lpj\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Services\InspeksiCleanupService;

class CleanupInspeksiDataCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'lpj:cleanup-inspeksi 
                            {--permohonan-id= : ID permohonan yang akan di-cleanup (opsional)}
                            {--sync : Jalankan secara synchronous}
                            {--dry-run : Tampilkan preview tanpa menjalankan cleanup}
                            {--force : Jalankan tanpa konfirmasi}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Cleanup data inspeksi lama yang tidak memiliki dokument_id';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        Log::info('CleanupInspeksiDataCommand: Memulai proses cleanup data inspeksi', [
            'options' => $this->options()
        ]);

        try {
            $permohonanId = $this->option('permohonan-id');
            $sync = $this->option('sync');
            $dryRun = $this->option('dry-run');
            $force = $this->option('force');

            // Validasi opsi
            if ($dryRun && $sync) {
                $this->error('Opsi --dry-run dan --sync tidak dapat digunakan bersamaan.');
                return Command::FAILURE;
            }

            // Tampilkan header
            $this->info('=== Cleanup Data Inspeksi ===');
            $this->newLine();

            // Ambil data yang akan di-cleanup
            $cleanupData = $this->getCleanupData($permohonanId);

            if ($cleanupData->isEmpty()) {
                $this->info('Tidak ada data yang perlu di-cleanup.');
                return Command::SUCCESS;
            }

            // Tampilkan preview data
            $this->displayPreview($cleanupData);

            if ($dryRun) {
                $this->info('Mode dry-run: Tidak ada perubahan yang dilakukan.');
                return Command::SUCCESS;
            }

            // Konfirmasi jika tidak force
            if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
                $this->info('Cleanup dibatalkan.');
                return Command::SUCCESS;
            }

            // Jalankan cleanup
            $this->runCleanup($cleanupData, $sync);

            $this->info('Proses cleanup selesai.');
            return Command::SUCCESS;

        } catch (\Exception $e) {
            Log::error('CleanupInspeksiDataCommand: Terjadi error saat proses cleanup', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->error('Terjadi kesalahan: ' . $e->getMessage());
            return Command::FAILURE;
        }
    }

    /**
     * Ambil data yang akan di-cleanup
     */
    private function getCleanupData(?int $permohonanId = null)
    {
        $this->info('Mencari data yang akan di-cleanup...');

        $query = DB::table('inspeksi as i')
            ->select(
                'i.permohonan_id',
                'i.created_by',
                DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
                DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count')
            )
            ->whereNull('i.deleted_at')
            ->groupBy('i.permohonan_id', 'i.created_by');

        if ($permohonanId) {
            $query->where('i.permohonan_id', $permohonanId);
        }

        $results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
            ->get();

        return $results;
    }

    /**
     * Tampilkan preview data
     */
    private function displayPreview($cleanupData): void
    {
        $this->info('Data yang akan di-cleanup:');
        $this->table(
            ['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama'],
            $cleanupData->map(function ($item) {
                return [
                    $item->permohonan_id,
                    $item->created_by,
                    $item->new_data_count,
                    $item->old_data_count
                ];
            })->toArray()
        );

        $totalPermohonan = $cleanupData->count();
        $totalOldData = $cleanupData->sum('old_data_count');

        $this->info("Total permohonan: {$totalPermohonan}");
        $this->info("Total data lama yang akan dihapus: {$totalOldData}");
        $this->newLine();
    }

    /**
     * Jalankan cleanup
     */
    private function runCleanup($cleanupData, bool $sync): void
    {
        $this->info('Memulai proses cleanup...');
        $this->newLine();

        $progressBar = $this->output->createProgressBar($cleanupData->count());
        $progressBar->setFormat('Processing: %current%/%max% [%bar%] %percent:3s%% %message%');
        $progressBar->start();

        $totalDeleted = 0;
        $totalErrors = 0;

        foreach ($cleanupData as $data) {
            try {
                $progressBar->setMessage("Permohonan ID: {$data->permohonan_id}");

                // Ambil data baru untuk mendapatkan dokument_id
                $newInspeksi = Inspeksi::where('permohonan_id', $data->permohonan_id)
                    ->where('created_by', $data->created_by)
                    ->whereNotNull('dokument_id')
                    ->whereNull('deleted_at')
                    ->first();

                if (!$newInspeksi) {
                    $this->warn("Tidak ditemukan data baru untuk permohonan {$data->permohonan_id}");
                    $progressBar->advance();
                    continue;
                }

                // Jalankan cleanup
                if ($sync) {
                    // Jalankan sync
                    $job = new CleanupInspeksiDataJob(
                        $data->permohonan_id,
                        $data->created_by,
                        $newInspeksi->dokument_id
                    );
                    $job->handle();
                } else {
                    // Dispatch ke queue
                    CleanupInspeksiDataJob::dispatch(
                        $data->permohonan_id,
                        $data->created_by,
                        $newInspeksi->dokument_id
                    );
                }

                $totalDeleted += $data->old_data_count;

            } catch (\Exception $e) {
                Log::error('CleanupInspeksiDataCommand: Error pada permohonan', [
                    'permohonan_id' => $data->permohonan_id,
                    'created_by' => $data->created_by,
                    'error' => $e->getMessage()
                ]);

                $this->error("Error pada permohonan {$data->permohonan_id}: {$e->getMessage()}");
                $totalErrors++;
            }

            $progressBar->advance();
        }

        $progressBar->finish();
        $this->newLine();
        $this->newLine();

        // Tampilkan hasil
        $this->info('=== Hasil Cleanup ===');
        $this->info("Data lama yang dihapus: {$totalDeleted}");
        $this->info("Error: {$totalErrors}");

        if (!$sync) {
            $this->info('Job telah di-dispatch ke queue. Monitor progress di log.');
        }
    }
}