<?php

declare(strict_types=1);

namespace App\Framework\Queue\Commands;

use App\Framework\Console\Attributes\ConsoleCommand;
use App\Framework\Queue\Contracts\JobDependencyManagerInterface;
use App\Framework\Queue\ValueObjects\JobDependency;
use App\Framework\Queue\ValueObjects\DependencyType;
use App\Framework\Queue\Services\DependencyResolutionEngine;

final readonly class JobDependencyCommands
{
    public function __construct(
        private JobDependencyManagerInterface $dependencyManager,
        private DependencyResolutionEngine $resolutionEngine
    ) {}

    #[ConsoleCommand(name: 'queue:dependency:add', description: 'Add a dependency between two jobs')]
    public function addDependency(
        string $dependentJobId,
        string $dependsOnJobId,
        string $type = 'completion',
        ?string $condition = null
    ): void {
        $dependencyType = DependencyType::from($type);

        $dependency = new JobDependency(
            dependentJobId: $dependentJobId,
            dependsOnJobId: $dependsOnJobId,
            type: $dependencyType,
            condition: $condition
        );

        $this->dependencyManager->addDependency($dependency);

        echo "✅ Dependency added: {$dependentJobId} depends on {$dependsOnJobId} ({$type})\n";
    }

    #[ConsoleCommand(name: 'queue:dependency:remove', description: 'Remove a dependency between two jobs')]
    public function removeDependency(string $dependentJobId, string $dependsOnJobId): void
    {
        $this->dependencyManager->removeDependency($dependentJobId, $dependsOnJobId);

        echo "✅ Dependency removed: {$dependentJobId} no longer depends on {$dependsOnJobId}\n";
    }

    #[ConsoleCommand(name: 'queue:dependency:list', description: 'List dependencies for a job')]
    public function listDependencies(string $jobId): void
    {
        $dependencies = $this->dependencyManager->getDependencies($jobId);
        $dependents = $this->dependencyManager->getDependents($jobId);

        echo "📋 Dependencies for job: {$jobId}\n\n";

        echo "🔗 This job depends on:\n";
        if (empty($dependencies)) {
            echo "   No dependencies\n";
        } else {
            foreach ($dependencies as $dep) {
                $status = $dep->isSatisfied ? '✅' : '⏳';
                echo "   {$status} {$dep->dependsOnJobId} ({$dep->dependencyType})\n";
            }
        }

        echo "\n🔗 Jobs that depend on this one:\n";
        if (empty($dependents)) {
            echo "   No dependents\n";
        } else {
            foreach ($dependents as $dep) {
                $status = $dep->isSatisfied ? '✅' : '⏳';
                echo "   {$status} {$dep->dependentJobId} ({$dep->dependencyType})\n";
            }
        }

        $canExecute = $this->dependencyManager->canJobBeExecuted($jobId);
        $statusIcon = $canExecute ? '✅' : '⏳';
        echo "\n{$statusIcon} Can execute: " . ($canExecute ? 'Yes' : 'No') . "\n";
    }

    #[ConsoleCommand(name: 'queue:dependency:analyze', description: 'Analyze dependencies for a job')]
    public function analyzeDependencies(string $jobId): void
    {
        $analysis = $this->resolutionEngine->analyzeDependencies($jobId);

        echo "🔍 Dependency Analysis for job: {$jobId}\n\n";

        echo "📊 Statistics:\n";
        echo "   Total dependencies: {$analysis['statistics']['total_dependencies']}\n";
        echo "   Satisfied: {$analysis['statistics']['satisfied_dependencies']}\n";
        echo "   Unsatisfied: {$analysis['statistics']['unsatisfied_dependencies']}\n";
        echo "   Total dependents: {$analysis['statistics']['total_dependents']}\n";
        echo "   Chain depth: {$analysis['statistics']['chain_depth']}\n";

        $canExecute = $analysis['can_execute'] ? '✅ Yes' : '❌ No';
        echo "   Can execute: {$canExecute}\n\n";

        if (!empty($analysis['unsatisfied_dependencies'])) {
            echo "⏳ Unsatisfied Dependencies:\n";
            foreach ($analysis['unsatisfied_dependencies'] as $dep) {
                echo "   - {$dep['depends_on_job_id']} ({$dep['dependency_type']})\n";
            }
            echo "\n";
        }

        if (!empty($analysis['full_dependency_chain'])) {
            echo "🔗 Full Dependency Chain:\n";
            foreach ($analysis['full_dependency_chain'] as $depJobId) {
                echo "   → {$depJobId}\n";
            }
        }
    }

    #[ConsoleCommand(name: 'queue:dependency:ready', description: 'List all jobs ready for execution')]
    public function listReadyJobs(): void
    {
        $readyJobs = $this->dependencyManager->getReadyJobs();

        echo "🚀 Jobs ready for execution:\n\n";

        if (empty($readyJobs)) {
            echo "   No jobs are currently ready\n";
        } else {
            foreach ($readyJobs as $jobId) {
                echo "   ✅ {$jobId}\n";
            }
        }

        echo "\nTotal: " . count($readyJobs) . " jobs ready\n";
    }

    #[ConsoleCommand(name: 'queue:dependency:validate', description: 'Validate dependency graph for circular dependencies')]
    public function validateDependencies(string $jobIds): void
    {
        $jobIdArray = explode(',', $jobIds);
        $jobIdArray = array_map('trim', $jobIdArray);

        $results = $this->resolutionEngine->validateDependencyGraph($jobIdArray);

        echo "🔍 Dependency Graph Validation\n\n";

        $hasErrors = false;

        foreach ($results as $result) {
            $status = $result['valid'] ? '✅' : '❌';
            echo "{$status} {$result['job_id']}";

            if (!$result['valid']) {
                $hasErrors = true;
                echo " - {$result['error']}\n";
                if (isset($result['dependency_chain'])) {
                    echo "   Chain: " . implode(' → ', $result['dependency_chain']) . "\n";
                }
            } else {
                echo " - Valid\n";
            }
        }

        if ($hasErrors) {
            echo "\n❌ Validation failed: Circular dependencies detected\n";
        } else {
            echo "\n✅ Validation passed: No circular dependencies\n";
        }
    }

    #[ConsoleCommand(name: 'queue:dependency:cleanup', description: 'Clean up old satisfied dependencies')]
    public function cleanupOldDependencies(int $olderThanDays = 30): void
    {
        $deletedCount = $this->dependencyManager->cleanupOldDependencies($olderThanDays);

        echo "🧹 Cleaned up old dependencies\n";
        echo "   Deleted: {$deletedCount} satisfied dependencies older than {$olderThanDays} days\n";
    }

    #[ConsoleCommand(name: 'queue:dependency:health', description: 'Perform dependency system health check')]
    public function healthCheck(): void
    {
        $health = $this->resolutionEngine->performHealthCheck();

        $statusIcon = $health['status'] === 'healthy' ? '✅' : '⚠️';
        echo "{$statusIcon} Dependency System Health: {$health['status']}\n\n";

        echo "📊 Statistics:\n";
        echo "   Active chains: {$health['statistics']['active_chains']}\n";
        echo "   Pending chains: {$health['statistics']['pending_chains']}\n";
        echo "   Ready jobs: {$health['statistics']['ready_jobs']}\n";
        echo "   Detected issues: {$health['statistics']['detected_issues']}\n\n";

        if (!empty($health['issues'])) {
            echo "⚠️ Issues Detected:\n";
            foreach ($health['issues'] as $issue) {
                echo "   - {$issue['type']}: ";

                match($issue['type']) {
                    'stalled_chain' => echo "Chain {$issue['chain_id']} running for {$issue['hours_running']} hours\n",
                    'many_unsatisfied_dependencies' => echo "Job {$issue['job_id']} has {$issue['unsatisfied_count']} unsatisfied dependencies\n",
                    default => echo "Unknown issue\n"
                };
            }
        }
    }
}