<?php

namespace App\Console\Commands;

use App\Model\Master\Client;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class RetryFailedLeadsCron extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'leads:retry-failed';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Retry failed or stale PROCESSING leads by re-inserting them into lead_temp';

    /**
     * Maximum number of retry attempts per lead.
     */
    const MAX_ATTEMPTS = 3;

    /**
     * Minutes after which a PROCESSING lead is considered stale (job probably died).
     */
    const STALE_MINUTES = 3;

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function handle()
    {
        $clients = Client::where('outbond_ai', 1)->pluck('id')->toArray();

        foreach ($clients as $clientId) {
            try {
                $this->retryForClient($clientId);
            } catch (\Exception $e) {
                Log::error('RetryFailedLeadsCron error', [
                    'client_id' => $clientId,
                    'error'     => $e->getMessage(),
                    'line'      => $e->getLine(),
                    'file'      => $e->getFile(),
                ]);
            }
        }
    }

    /**
     * Find and retry stale/failed leads for a single client.
     */
    private function retryForClient(int $clientId): void
    {
        $db = 'mysql_' . $clientId;

        // Find leads stuck in PROCESSING for too long (job likely died or timed out)
        $staleLeads = DB::connection($db)->select(
            "SELECT campaign_id, list_id, lead_id
             FROM lead_report
             WHERE status = 'PROCESSING'
               AND picked_at < NOW() - INTERVAL ? MINUTE
               AND attempt_count < ?",
            [self::STALE_MINUTES, self::MAX_ATTEMPTS]
        );

        // Find explicitly FAILED leads eligible for retry
        $failedLeads = DB::connection($db)->select(
            "SELECT campaign_id, list_id, lead_id
             FROM lead_report
             WHERE status = 'FAILED'
               AND attempt_count < ?",
            [self::MAX_ATTEMPTS]
        );

        $retryLeads = array_merge($staleLeads, $failedLeads);

        if (empty($retryLeads)) {
            return;
        }

        Log::info('RetryFailedLeadsCron: retrying leads', [
            'client_id' => $clientId,
            'count'     => count($retryLeads),
        ]);

        foreach ($retryLeads as $lead) {
            try {
                // Re-insert into lead_temp so the normal cron picks it up.
                // INSERT IGNORE avoids errors if the lead is already in the hopper.
                DB::connection($db)->insert(
                    "INSERT IGNORE INTO lead_temp (campaign_id, list_id, lead_id)
                     VALUES (:campaign_id, :list_id, :lead_id)",
                    [
                        'campaign_id' => $lead->campaign_id,
                        'list_id'     => $lead->list_id,
                        'lead_id'     => $lead->lead_id,
                    ]
                );

                // Reset to PROCESSING with incremented attempt count.
                // The next cron run will pick it from lead_temp and the
                // ON DUPLICATE KEY UPDATE in OutboundUpdateCron will bump
                // the attempt_count again.
                DB::connection($db)->update(
                    "UPDATE lead_report
                     SET status = 'PROCESSING', picked_at = NOW(), attempt_count = attempt_count + 1
                     WHERE campaign_id = :campaign_id AND lead_id = :lead_id",
                    [
                        'campaign_id' => $lead->campaign_id,
                        'lead_id'     => $lead->lead_id,
                    ]
                );
            } catch (\Exception $e) {
                Log::error('RetryFailedLeadsCron: failed to retry lead', [
                    'client_id'   => $clientId,
                    'campaign_id' => $lead->campaign_id,
                    'lead_id'     => $lead->lead_id,
                    'error'       => $e->getMessage(),
                ]);
            }
        }
    }
}
