<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;

class CronController extends Controller
{
    /**
     * Get cron job status and statistics
     */
    public function status()
    {
        $baseUrl = url('/');
        $cronJobs = [
            [
                'id' => 'post_scheduler',
                'name' => 'Post Scheduler',
                'description' => 'Automatically publishes scheduled social media posts',
                'command' => 'posts:schedule',
                'url' => $baseUrl . '/cron/posts-schedule',
                'frequency' => '* * * * *',
                'status' => Cache::get('cron_post_scheduler_status', 'active'),
                'last_run' => Cache::get('cron_post_scheduler_last_run', Carbon::now()->subMinutes(2)->diffForHumans()),
                'next_run' => 'In 58 seconds',
                'success_rate' => Cache::get('cron_post_scheduler_success_rate', 98.5),
                'total_runs' => Cache::get('cron_post_scheduler_total_runs', 1247),
                'failures' => Cache::get('cron_post_scheduler_failures', 19),
                'category' => 'content'
            ],
            [
                'id' => 'analytics_sync',
                'name' => 'Analytics Sync',
                'description' => 'Syncs analytics data from social platforms',
                'command' => 'analytics:sync',
                'url' => $baseUrl . '/cron/analytics-sync',
                'frequency' => '0 */6 * * *',
                'status' => Cache::get('cron_analytics_sync_status', 'active'),
                'last_run' => Cache::get('cron_analytics_sync_last_run', Carbon::now()->subHours(3)->diffForHumans()),
                'next_run' => 'In 3 hours',
                'success_rate' => Cache::get('cron_analytics_sync_success_rate', 95.2),
                'total_runs' => Cache::get('cron_analytics_sync_total_runs', 456),
                'failures' => Cache::get('cron_analytics_sync_failures', 22),
                'category' => 'analytics'
            ],
            [
                'id' => 'account_refresh',
                'name' => 'Account Token Refresh',
                'description' => 'Refreshes social media account access tokens',
                'command' => 'accounts:refresh-tokens',
                'url' => $baseUrl . '/cron/accounts-refresh-tokens',
                'frequency' => '0 2 * * *',
                'status' => Cache::get('cron_account_refresh_status', 'active'),
                'last_run' => Cache::get('cron_account_refresh_last_run', Carbon::now()->subHours(8)->diffForHumans()),
                'next_run' => 'In 16 hours',
                'success_rate' => Cache::get('cron_account_refresh_success_rate', 99.1),
                'total_runs' => Cache::get('cron_account_refresh_total_runs', 89),
                'failures' => Cache::get('cron_account_refresh_failures', 1),
                'category' => 'security'
            ],
            [
                'id' => 'cleanup',
                'name' => 'System Cleanup',
                'description' => 'Cleans up temporary files and old logs',
                'command' => 'system:cleanup',
                'url' => $baseUrl . '/cron/system-cleanup',
                'frequency' => '0 3 * * 0',
                'status' => Cache::get('cron_cleanup_status', 'active'),
                'last_run' => Cache::get('cron_cleanup_last_run', Carbon::now()->subDays(2)->diffForHumans()),
                'next_run' => 'In 5 days',
                'success_rate' => Cache::get('cron_cleanup_success_rate', 100),
                'total_runs' => Cache::get('cron_cleanup_total_runs', 12),
                'failures' => Cache::get('cron_cleanup_failures', 0),
                'category' => 'maintenance'
            ],
            [
                'id' => 'backup',
                'name' => 'Automated Backup',
                'description' => 'Creates automated backups of important data',
                'command' => 'backup:run',
                'url' => $baseUrl . '/cron/backup-run',
                'frequency' => '0 1 * * *',
                'status' => Cache::get('cron_backup_status', 'active'),
                'last_run' => Cache::get('cron_backup_last_run', Carbon::now()->subHours(9)->diffForHumans()),
                'next_run' => 'In 15 hours',
                'success_rate' => Cache::get('cron_backup_success_rate', 97.8),
                'total_runs' => Cache::get('cron_backup_total_runs', 67),
                'failures' => Cache::get('cron_backup_failures', 2),
                'category' => 'backup'
            ]
        ];

        $systemStatus = [
            'last_cron_run' => Cache::get('last_cron_run', Carbon::now()->subMinutes(2)->diffForHumans()),
            'success_rate' => $this->calculateOverallSuccessRate($cronJobs),
            'total_active_jobs' => count(array_filter($cronJobs, fn($job) => $job['status'] === 'active')),
            'system_health' => 'operational'
        ];

        return response()->json([
            'cronJobs' => $cronJobs,
            'systemStatus' => $systemStatus
        ]);
    }

    /**
     * Toggle cron job status
     */
    public function toggle(Request $request)
    {
        $request->validate([
            'job_id' => 'required|string',
            'status' => 'required|in:active,inactive'
        ]);

        $jobId = $request->job_id;
        $status = $request->status;

        // Update job status in cache
        Cache::put("cron_{$jobId}_status", $status, now()->addDays(30));

        Log::info("Cron job {$jobId} status changed to {$status}", [
            'job_id' => $jobId,
            'new_status' => $status,
            'user_id' => auth()->id(),
            'timestamp' => now()
        ]);

        return back()->with('success', "Cron job status updated successfully");
    }

    /**
     * Run cron job immediately
     */
    public function runNow(Request $request)
    {
        $request->validate([
            'job_id' => 'required|string'
        ]);

        $jobId = $request->job_id;
        
        try {
            // Map job IDs to artisan commands
            $commandMap = [
                'post_scheduler' => 'posts:schedule',
                'analytics_sync' => 'analytics:sync',
                'account_refresh' => 'accounts:refresh-tokens',
                'cleanup' => 'system:cleanup',
                'backup' => 'backup:run'
            ];

            if (!isset($commandMap[$jobId])) {
                return back()->with('error', 'Invalid cron job ID');
            }

            $command = $commandMap[$jobId];
            
            // Check if the cron job is active before executing
            $jobStatus = Cache::get("cron_{$jobId}_status", 'active');
            
            if ($jobStatus !== 'active') {
                return back()->with('error', 'Cannot run paused cron job. Please activate it first.');
            }
            
            // Execute the command
            $exitCode = Artisan::call($command);
            
            if ($exitCode === 0) {
                // Update last run time
                Cache::put("cron_{$jobId}_last_run", Carbon::now()->diffForHumans(), now()->addDays(30));
                
                // Increment total runs
                $totalRuns = Cache::get("cron_{$jobId}_total_runs", 0);
                Cache::put("cron_{$jobId}_total_runs", $totalRuns + 1, now()->addDays(30));

                Log::info("Cron job {$jobId} executed successfully", [
                    'job_id' => $jobId,
                    'command' => $command,
                    'exit_code' => $exitCode,
                    'user_id' => auth()->id()
                ]);

                return back()->with('success', 'Cron job executed successfully');
            } else {
                // Increment failure count
                $failures = Cache::get("cron_{$jobId}_failures", 0);
                Cache::put("cron_{$jobId}_failures", $failures + 1, now()->addDays(30));

                Log::error("Cron job {$jobId} execution failed", [
                    'job_id' => $jobId,
                    'command' => $command,
                    'exit_code' => $exitCode,
                    'user_id' => auth()->id()
                ]);

                return back()->with('error', 'Cron job execution failed');
            }
        } catch (\Exception $e) {
            Log::error("Error executing cron job {$jobId}: " . $e->getMessage(), [
                'job_id' => $jobId,
                'error' => $e->getMessage(),
                'user_id' => auth()->id()
            ]);

            return back()->with('error', 'Failed to execute cron job: ' . $e->getMessage());
        }
    }

    /**
     * Get cron job logs
     */
    public function logs(Request $request)
    {
        $request->validate([
            'job_id' => 'required|string',
            'limit' => 'sometimes|integer|min:1|max:100'
        ]);

        $jobId = $request->job_id;
        $limit = $request->get('limit', 50);

        // This would typically read from a log file or database
        // For now, we'll return mock data
        $logs = collect([
            [
                'timestamp' => Carbon::now()->subMinutes(2),
                'level' => 'info',
                'message' => 'Cron job executed successfully',
                'context' => ['posts_scheduled' => 5]
            ],
            [
                'timestamp' => Carbon::now()->subHours(1)->subMinutes(2),
                'level' => 'info', 
                'message' => 'Cron job executed successfully',
                'context' => ['posts_scheduled' => 3]
            ],
            [
                'timestamp' => Carbon::now()->subHours(2)->subMinutes(2),
                'level' => 'warning',
                'message' => 'Some posts failed to schedule',
                'context' => ['failed_posts' => 1, 'posts_scheduled' => 2]
            ]
        ])->take($limit);

        return response()->json(['logs' => $logs]);
    }

    /**
     * Record cron job execution
     * This method would be called by the actual cron jobs
     */
    public function recordExecution(string $jobId, bool $success, array $context = [])
    {
        $timestamp = Carbon::now();
        
        // Update last run time
        Cache::put("cron_{$jobId}_last_run", $timestamp->diffForHumans(), now()->addDays(30));
        Cache::put('last_cron_run', $timestamp->diffForHumans(), now()->addDays(30));
        
        // Update statistics
        $totalRuns = Cache::get("cron_{$jobId}_total_runs", 0);
        Cache::put("cron_{$jobId}_total_runs", $totalRuns + 1, now()->addDays(30));
        
        if (!$success) {
            $failures = Cache::get("cron_{$jobId}_failures", 0);
            Cache::put("cron_{$jobId}_failures", $failures + 1, now()->addDays(30));
        }
        
        // Recalculate success rate
        $failures = Cache::get("cron_{$jobId}_failures", 0);
        $successRate = $totalRuns > 0 ? (($totalRuns - $failures) / $totalRuns) * 100 : 100;
        Cache::put("cron_{$jobId}_success_rate", round($successRate, 1), now()->addDays(30));

        // Log the execution
        Log::info("Cron job execution recorded", [
            'job_id' => $jobId,
            'success' => $success,
            'context' => $context,
            'timestamp' => $timestamp
        ]);
    }

    /**
     * Calculate overall system success rate
     */
    private function calculateOverallSuccessRate(array $cronJobs): float
    {
        $totalRuns = array_sum(array_column($cronJobs, 'total_runs'));
        $totalFailures = array_sum(array_column($cronJobs, 'failures'));
        
        return $totalRuns > 0 ? round((($totalRuns - $totalFailures) / $totalRuns) * 100, 1) : 100.0;
    }

    /**
     * Get system health status
     */
    public function health()
    {
        $cronJobs = $this->status()->getData()->cronJobs;
        $activeJobs = array_filter($cronJobs, fn($job) => $job->status === 'active');
        $overallSuccessRate = $this->calculateOverallSuccessRate($cronJobs);
        
        $health = 'operational';
        if ($overallSuccessRate < 90) {
            $health = 'degraded';
        } elseif ($overallSuccessRate < 80) {
            $health = 'critical';
        }
        
        return response()->json([
            'status' => $health,
            'active_jobs' => count($activeJobs),
            'success_rate' => $overallSuccessRate,
            'last_check' => Carbon::now()->toISOString()
        ]);
    }

    /**
     * Execute posts schedule cron job via URL (for shared hosting)
     */
    public function executePostsSchedule(Request $request)
    {
        return $this->executeCronJobByUrl('post_scheduler', 'posts:schedule');
    }

    /**
     * Execute analytics sync cron job via URL (for shared hosting)
     */
    public function executeAnalyticsSync(Request $request)
    {
        return $this->executeCronJobByUrl('analytics_sync', 'analytics:sync');
    }

    /**
     * Execute accounts refresh tokens cron job via URL (for shared hosting)
     */
    public function executeAccountsRefreshTokens(Request $request)
    {
        return $this->executeCronJobByUrl('account_refresh', 'accounts:refresh-tokens');
    }

    /**
     * Execute system cleanup cron job via URL (for shared hosting)
     */
    public function executeSystemCleanup(Request $request)
    {
        return $this->executeCronJobByUrl('cleanup', 'system:cleanup');
    }

    /**
     * Execute backup cron job via URL (for shared hosting)
     */
    public function executeBackupRun(Request $request)
    {
        return $this->executeCronJobByUrl('backup', 'backup:run');
    }

    /**
     * Helper method to execute cron jobs via URL
     */
    private function executeCronJobByUrl(string $jobId, string $command)
    {
        try {
            // Check if the cron job is active before executing
            $jobStatus = Cache::get("cron_{$jobId}_status", 'active');
            
            if ($jobStatus !== 'active') {
                Log::info("Cron job {$jobId} skipped - status is {$jobStatus}", [
                    'job_id' => $jobId,
                    'command' => $command,
                    'status' => $jobStatus
                ]);
                
                return response()->json([
                    'success' => false,
                    'message' => 'Cron job is currently paused',
                    'job_id' => $jobId,
                    'command' => $command,
                    'status' => $jobStatus
                ], 423); // 423 Locked - resource is locked
            }
            
            $startTime = microtime(true);
            
            // Execute the artisan command
            $exitCode = Artisan::call($command);
            $output = Artisan::output();
            
            $executionTime = round((microtime(true) - $startTime) * 1000, 2);
            
            if ($exitCode === 0) {
                // Update last run time and statistics
                Cache::put("cron_{$jobId}_last_run", Carbon::now()->diffForHumans(), now()->addDays(30));
                Cache::put('last_cron_run', Carbon::now()->diffForHumans(), now()->addDays(30));
                
                $totalRuns = Cache::get("cron_{$jobId}_total_runs", 0);
                Cache::put("cron_{$jobId}_total_runs", $totalRuns + 1, now()->addDays(30));
                
                // Recalculate success rate
                $failures = Cache::get("cron_{$jobId}_failures", 0);
                $successRate = ($totalRuns + 1) > 0 ? ((($totalRuns + 1) - $failures) / ($totalRuns + 1)) * 100 : 100;
                Cache::put("cron_{$jobId}_success_rate", round($successRate, 1), now()->addDays(30));

                Log::info("Cron job {$jobId} executed successfully via URL", [
                    'job_id' => $jobId,
                    'command' => $command,
                    'execution_time_ms' => $executionTime,
                    'exit_code' => $exitCode
                ]);

                return response()->json([
                    'success' => true,
                    'message' => 'Cron job executed successfully',
                    'job_id' => $jobId,
                    'command' => $command,
                    'execution_time_ms' => $executionTime,
                    'output' => trim($output)
                ]);
            } else {
                // Increment failure count
                $failures = Cache::get("cron_{$jobId}_failures", 0);
                Cache::put("cron_{$jobId}_failures", $failures + 1, now()->addDays(30));

                Log::error("Cron job {$jobId} execution failed via URL", [
                    'job_id' => $jobId,
                    'command' => $command,
                    'exit_code' => $exitCode,
                    'output' => trim($output)
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Cron job execution failed',
                    'job_id' => $jobId,
                    'command' => $command,
                    'exit_code' => $exitCode,
                    'output' => trim($output)
                ], 500);
            }
        } catch (\Exception $e) {
            Log::error("Error executing cron job {$jobId} via URL: " . $e->getMessage(), [
                'job_id' => $jobId,
                'command' => $command,
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to execute cron job',
                'error' => $e->getMessage(),
                'job_id' => $jobId,
                'command' => $command
            ], 500);
        }
    }
}