<?php

namespace App\Console\Commands;

use App\Models\SerpCheck;
use App\Models\SerpOperationState;
use App\Serp\Operations\ActivationManager;
use App\Serp\Operations\CircuitBreaker;
use App\Serp\Operations\DataForSeoHealthService;
use App\Serp\Operations\Money;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Throwable;

class SerpProductionPreflightCommand extends Command
{
    protected $signature = 'serp:production:preflight {--json}';

    protected $description = 'Production SERP geçiş kapılarını dış HTTP olmadan doğrular';

    public function handle(ActivationManager $activation, DataForSeoHealthService $health, CircuitBreaker $circuit): int
    {
        $gates = [];
        $gate = function (string $name, bool $pass, mixed $value = null, bool $critical = true) use (&$gates) {
            $gates[$name] = ['status' => $pass ? 'pass' : 'fail', 'critical' => $critical, 'value' => $value];
        };
        $configured = (string) config('serp.dataforseo.login') !== '' && (string) config('serp.dataforseo.password') !== '';
        $gate('environment', app()->environment('production'), app()->environment());
        $gate('debug', ! config('app.debug'), config('app.debug') ? 'enabled' : 'disabled');
        $gate('provider', config('serp.provider') === 'dataforseo', config('serp.provider'));
        $state = $activation->state();
        $consistent = (! config('serp.enabled') && in_array($state->value, ['disabled', 'validation_only', 'canary'], true)) || (config('serp.enabled') && in_array($state->value, ['canary', 'enabled', 'emergency_stopped'], true));
        $gate('activation_consistency', $consistent, ['enabled' => (bool) config('serp.enabled'), 'mode' => $state->value]);
        $gate('credentials', $configured, $configured ? 'configured' : 'not_configured');
        try {
            $local = $health->validateConfig();
            $gate('provider_security', true, ['host' => $local['host'], 'tls' => $local['tls']]);
        } catch (Throwable) {
            $gate('provider_security', false, 'invalid');
        }$pending = $this->pendingMigrations();
        $gate('migrations', $pending === 0, ['pending' => $pending]);
        try {
            $lock = Cache::lock('serp:preflight-lock', 5);
            $acquired = $lock->get();
            if ($acquired) {
                $lock->release();
            }$gate('cache_lock', $acquired, config('cache.default'));
        } catch (Throwable) {
            $gate('cache_lock', false, 'unavailable');
        }$gate('queue', in_array(config('queue.default'), ['redis', 'database'], true), ['connection' => config('queue.default'), 'serp_queue' => config('serp.queue')]);
        $console = file_get_contents(base_path('routes/console.php'));
        $gate('scheduler', str_contains($console, 'serp:dispatch-due') && str_contains($console, 'serp:reconcile'), ['defined' => true]);
        $stateRow = SerpOperationState::find(1);
        $gate('kill_switch', ! $stateRow?->emergency_stopped_at, $stateRow?->emergency_stopped_at ? 'active' : 'clear');
        $gate('circuit', ! $circuit->open(), $circuit->open() ? 'open' : 'closed');
        foreach (['daily_budget_usd', 'monthly_budget_usd', 'low_balance_usd', 'critical_balance_usd'] as $key) {
            try {
                $gate($key, Money::micros((string) config('serp.'.$key)) > 0, (string) config('serp.'.$key));
            } catch (Throwable) {
                $gate($key, false, 'invalid');
            }
        }$gate('depth', config('serp.dataforseo.result_depth') === 10, config('serp.dataforseo.result_depth'));
        $gate('provider_modes', config('serp.manual_mode') === 'live' && config('serp.automatic_mode') === 'standard', ['manual' => config('serp.manual_mode'), 'automatic' => config('serp.automatic_mode')]);
        $summary = ['status' => collect($gates)->contains(fn ($g) => $g['critical'] && $g['status'] === 'fail') ? 'failed' : 'passed', 'remote' => 'not_requested', 'gates' => $gates, 'operations' => ['last_health_at' => $stateRow?->last_health_at, 'last_provider_success_at' => $stateRow?->last_provider_success_at, 'stuck' => SerpCheck::whereIn('status', ['pending', 'running'])->where('updated_at', '<', now()->subMinutes((int) config('serp.stuck_after_minutes')))->count(), 'pending' => SerpCheck::where('status', 'pending')->count(), 'running' => SerpCheck::where('status', 'running')->count()]];
        $this->option('json') ? $this->line(json_encode($summary, JSON_THROW_ON_ERROR)) : $this->line('Preflight: '.$summary['status']);

        return $summary['status'] === 'passed' ? self::SUCCESS : self::FAILURE;
    }

    private function pendingMigrations(): int
    {
        if (! Schema::hasTable('migrations')) {
            return count(glob(database_path('migrations/*.php')));
        }$ran = DB::table('migrations')->pluck('migration')->all();

        return count(array_filter(glob(database_path('migrations/*.php')), fn ($f) => ! in_array(pathinfo($f, PATHINFO_FILENAME), $ran, true)));
    }
}
