<?php

namespace App\Console\Commands;

use App\RegistrationOtp;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class CleanupExpiredOtps extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'otp:cleanup {--dry-run : Show what would be deleted without actually deleting} {--older-than=24 : Delete OTPs older than specified hours}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Clean up expired and old OTP records from the database';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $dryRun = $this->option('dry-run');
        $olderThanHours = (int) $this->option('older-than');
        $cutoffTime = now()->subHours($olderThanHours);

        $this->info("Starting OTP cleanup process...");
        $this->info("Cutoff time: {$cutoffTime->format('Y-m-d H:i:s')}");
        $this->info("Dry run: " . ($dryRun ? 'Yes' : 'No'));

        // Get statistics before cleanup
        $totalRecords = RegistrationOtp::count();
        $expiredRecords = RegistrationOtp::expiredByTime()->count();
        $oldRecords = RegistrationOtp::where('created_at', '<', $cutoffTime)->count();
        $verifiedRecords = RegistrationOtp::verified()->count();
        $failedRecords = RegistrationOtp::failed()->count();

        $this->info("\nCurrent OTP Statistics:");
        $this->table(
            ['Metric', 'Count'],
            [
                ['Total Records', $totalRecords],
                ['Expired Records', $expiredRecords],
                ['Records older than ' . $olderThanHours . ' hours', $oldRecords],
                ['Verified Records', $verifiedRecords],
                ['Failed Records', $failedRecords],
            ]
        );

        if ($dryRun) {
            $this->warn("\nDRY RUN MODE - No records will be deleted");

            $recordsToDelete = RegistrationOtp::where(function ($query) use ($cutoffTime) {
                $query->where('expires_at', '<', now())
                    ->orWhere('created_at', '<', $cutoffTime);
            })->get();

            if ($recordsToDelete->isEmpty()) {
                $this->info("No records would be deleted.");
                return 0;
            }

            $this->info("\nRecords that would be deleted:");
            $this->table(
                ['ID', 'Phone', 'Status', 'Created', 'Expires', 'IP Address'],
                $recordsToDelete->map(function ($otp) {
                    return [
                        $otp->id,
                        $otp->phone_number,
                        $otp->status,
                        $otp->created_at->format('Y-m-d H:i:s'),
                        $otp->expires_at->format('Y-m-d H:i:s'),
                        $otp->ip_address ?? 'N/A'
                    ];
                })->toArray()
            );

            return 0;
        }

        // Perform actual cleanup
        $this->info("\nPerforming cleanup...");

        try {
            DB::beginTransaction();

            // Delete expired OTPs
            $expiredDeleted = RegistrationOtp::expiredByTime()->delete();

            // Delete old OTPs (regardless of status)
            $oldDeleted = RegistrationOtp::where('created_at', '<', $cutoffTime)->delete();

            DB::commit();

            $totalDeleted = $expiredDeleted + $oldDeleted;

            $this->info("Cleanup completed successfully!");
            $this->info("Records deleted: {$totalDeleted}");
            $this->info("- Expired records: {$expiredDeleted}");
            $this->info("- Old records: {$oldDeleted}");

            // Show remaining statistics
            $remainingRecords = RegistrationOtp::count();
            $this->info("Remaining records: {$remainingRecords}");

            return 0;

        } catch (\Exception $e) {
            DB::rollback();
            $this->error("Cleanup failed: " . $e->getMessage());
            return 1;
        }
    }
}
