<?php
/**
 * ===========================================
 * FLOWBOT DCI - DASHBOARD API CONTROLLER v3.0
 * ===========================================
 * API endpoints for dashboard functionality
 *
 * Endpoints:
 * - GET  /api/v1/dashboard/stats - Dashboard statistics
 * - GET  /api/v1/dashboard/active - Active processes
 * - GET  /api/v1/dashboard/history - Process history
 * - GET  /api/v1/dashboard/activity - Recent activity
 * - GET  /api/v1/dashboard/charts - Chart data
 * - GET  /api/v1/process/{id}/live - Live process state
 * - POST /api/v1/process/{id}/pause - Pause process
 * - POST /api/v1/process/{id}/resume - Resume process
 * - POST /api/v1/process/{id}/cancel - Cancel process
 * - POST /api/v1/validate-urls - Validate URLs
 * - POST /api/v1/analyze-urls - Analyze URLs
 */

declare(strict_types=1);

namespace FlowbotDCI\Api\v1;

use FlowbotDCI\Services\DashboardService;
use FlowbotDCI\Services\ProcessManager;
use FlowbotDCI\Utils\UrlPreProcessor;

class DashboardController
{
    private DashboardService $dashboard;
    private ProcessManager $processManager;
    private ?UrlPreProcessor $urlProcessor = null;

    const VERSION = '3.0';

    public function __construct(DashboardService $dashboard, ProcessManager $processManager)
    {
        $this->dashboard = $dashboard;
        $this->processManager = $processManager;
    }

    /**
     * Set URL processor for validation
     */
    public function setUrlProcessor(UrlPreProcessor $processor): self
    {
        $this->urlProcessor = $processor;
        return $this;
    }

    /**
     * Handle API request
     */
    public function handle(string $action, array $params = []): array
    {
        try {
            switch ($action) {
                // Dashboard endpoints
                case 'dashboard/stats':
                    return $this->getStats();
                case 'dashboard/active':
                    return $this->getActiveProcesses();
                case 'dashboard/history':
                    return $this->getHistory($params);
                case 'dashboard/activity':
                    return $this->getActivity($params);
                case 'dashboard/charts':
                    return $this->getCharts($params);

                // Process control endpoints
                case 'process/live':
                    return $this->getLiveProgress($params['id'] ?? '');
                case 'process/pause':
                    return $this->pauseProcess($params['id'] ?? '');
                case 'process/resume':
                    return $this->resumeProcess($params['id'] ?? '');
                case 'process/cancel':
                    return $this->cancelProcess($params['id'] ?? '');
                case 'process/delete':
                    return $this->deleteProcess($params['id'] ?? '');
                case 'process/reprocess':
                    return $this->reprocessProcess($params['id'] ?? '', $params);
                case 'process/details':
                    return $this->getProcessDetails($params['id'] ?? '');

                // URL validation/analysis endpoints
                case 'validate-urls':
                    return $this->validateUrls($params);
                case 'analyze-urls':
                    return $this->analyzeUrls($params);

                // Settings endpoints
                case 'settings/get':
                    return $this->getSettings();
                case 'settings/update':
                    return $this->updateSettings($params);

                default:
                    return $this->error("Unknown action: {$action}", 404);
            }
        } catch (\Exception $e) {
            return $this->error($e->getMessage(), 500);
        }
    }

    /**
     * GET /api/v1/dashboard/stats
     * Get dashboard statistics
     */
    private function getStats(): array
    {
        $stats = $this->dashboard->getStats();
        return $this->success($stats);
    }

    /**
     * GET /api/v1/dashboard/active
     * Get active processes
     */
    private function getActiveProcesses(): array
    {
        $processes = $this->dashboard->getActiveProcesses();
        return $this->success(['processes' => $processes]);
    }

    /**
     * GET /api/v1/dashboard/history
     * Get process history with pagination
     */
    private function getHistory(array $params): array
    {
        $page = max(1, (int)($params['page'] ?? 1));
        $limit = min(100, max(10, (int)($params['limit'] ?? 20)));
        $filters = [
            'status' => $params['status'] ?? null,
            'date_from' => $params['date_from'] ?? null,
            'date_to' => $params['date_to'] ?? null,
        ];

        $history = $this->dashboard->getHistory($page, $limit, array_filter($filters));
        return $this->success($history);
    }

    /**
     * GET /api/v1/dashboard/activity
     * Get recent activity feed
     */
    private function getActivity(array $params): array
    {
        $limit = min(100, max(5, (int)($params['limit'] ?? 20)));
        $activity = $this->dashboard->getRecentActivity($limit);
        return $this->success(['events' => $activity]);
    }

    /**
     * GET /api/v1/dashboard/charts
     * Get chart data for visualizations
     */
    private function getCharts(array $params): array
    {
        $period = $params['period'] ?? '7d';
        if (!in_array($period, ['7d', '30d', '90d'])) {
            $period = '7d';
        }

        $charts = $this->dashboard->getChartData($period);
        return $this->success($charts);
    }

    /**
     * GET /api/v1/process/{id}/live
     * Get live process progress for real-time updates
     */
    private function getLiveProgress(string $processId): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        $progress = $this->processManager->getLiveProgress($processId);

        if (!$progress) {
            return $this->error('Process not found', 404);
        }

        return $this->success($progress);
    }

    /**
     * POST /api/v1/process/{id}/pause
     * Pause a running process
     */
    private function pauseProcess(string $processId): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        $success = $this->processManager->pause($processId);

        if (!$success) {
            return $this->error('Failed to pause process', 400);
        }

        return $this->success(['message' => 'Process paused', 'process_id' => $processId]);
    }

    /**
     * POST /api/v1/process/{id}/resume
     * Resume a paused process
     */
    private function resumeProcess(string $processId): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        $success = $this->processManager->resume($processId);

        if (!$success) {
            return $this->error('Failed to resume process', 400);
        }

        return $this->success(['message' => 'Process resumed', 'process_id' => $processId]);
    }

    /**
     * POST /api/v1/process/{id}/cancel
     * Cancel a running or paused process
     */
    private function cancelProcess(string $processId): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        $success = $this->processManager->cancel($processId);

        if (!$success) {
            return $this->error('Failed to cancel process', 400);
        }

        return $this->success(['message' => 'Process cancelled', 'process_id' => $processId]);
    }

    /**
     * DELETE /api/v1/process/{id}
     * Delete a process and its data
     */
    private function deleteProcess(string $processId): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        $success = $this->dashboard->deleteProcess($processId);

        if (!$success) {
            return $this->error('Failed to delete process', 400);
        }

        return $this->success(['message' => 'Process deleted', 'process_id' => $processId]);
    }

    /**
     * POST /api/v1/process/{id}/reprocess
     * Create new process with same URLs from existing process
     */
    private function reprocessProcess(string $processId, array $params): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        // Get options from params (optional)
        $options = [];
        if (isset($params['mode'])) {
            $options['mode'] = $params['mode'];
        }

        $newProcessId = $this->dashboard->reprocessProcess($processId, $options);

        if (!$newProcessId) {
            return $this->error('Failed to reprocess. Process not found or no URLs available.', 400);
        }

        return $this->success([
            'message' => 'Process queued for reprocessing',
            'original_process_id' => $processId,
            'new_process_id' => $newProcessId,
            'redirect_url' => "/process/{$newProcessId}"
        ]);
    }

    /**
     * GET /api/v1/process/{id}/details
     * Get complete process details
     */
    private function getProcessDetails(string $processId): array
    {
        if (empty($processId)) {
            return $this->error('Process ID required', 400);
        }

        $details = $this->dashboard->getProcessDetails($processId);

        if (!$details) {
            return $this->error('Process not found', 404);
        }

        return $this->success($details);
    }

    /**
     * POST /api/v1/validate-urls
     * Validate URLs before processing
     */
    private function validateUrls(array $params): array
    {
        $urls = $params['urls'] ?? [];

        if (empty($urls)) {
            return $this->error('No URLs provided', 400);
        }

        if (is_string($urls)) {
            $urls = array_filter(array_map('trim', explode("\n", $urls)));
        }

        if (!$this->urlProcessor) {
            $this->urlProcessor = new UrlPreProcessor();
        }

        $result = $this->urlProcessor->process($urls);

        return $this->success([
            'valid_count' => count($result['valid']),
            'invalid_count' => count($result['invalid']),
            'valid_urls' => $result['valid'],
            'invalid_urls' => $result['invalid'],
            'stats' => $result['stats'],
        ]);
    }

    /**
     * POST /api/v1/analyze-urls
     * Analyze URLs before starting process
     */
    private function analyzeUrls(array $params): array
    {
        $urls = $params['urls'] ?? [];
        $mode = $params['mode'] ?? 'standard';

        if (empty($urls)) {
            return $this->error('No URLs provided', 400);
        }

        if (is_string($urls)) {
            $urls = array_filter(array_map('trim', explode("\n", $urls)));
        }

        if (!$this->urlProcessor) {
            $this->urlProcessor = new UrlPreProcessor();
        }

        // Validate and process URLs
        $result = $this->urlProcessor->process($urls);
        $validUrls = $result['valid'];

        // Get domain breakdown
        $domains = [];
        $socialMediaCount = 0;
        foreach ($validUrls as $url) {
            $host = parse_url($url, PHP_URL_HOST) ?? '';
            $domain = preg_replace('/^www\./', '', $host);

            if (!isset($domains[$domain])) {
                $domains[$domain] = [
                    'domain' => $domain,
                    'count' => 0,
                    'is_social_media' => $this->urlProcessor->isSocialMedia($url),
                    'success_rate' => $this->dashboard->getDomainSuccessRate($domain),
                ];
            }
            $domains[$domain]['count']++;

            if ($domains[$domain]['is_social_media']) {
                $socialMediaCount++;
            }
        }

        // Sort domains by count
        uasort($domains, fn($a, $b) => $b['count'] <=> $a['count']);

        // Get processing time estimates
        $estimates = $this->dashboard->estimateProcessingTime(count($validUrls), array_keys($domains));

        // Generate warnings
        $warnings = [];
        if ($socialMediaCount > 0) {
            $warnings[] = [
                'type' => 'social_media',
                'message' => "{$socialMediaCount} social media URLs detected - may have lower success rate",
            ];
        }
        foreach ($result['invalid'] as $invalid) {
            if (strpos($invalid['reason'] ?? '', 'Blocked') !== false) {
                $warnings[] = [
                    'type' => 'blocked',
                    'message' => $invalid['reason'],
                    'url' => $invalid['url'],
                ];
            }
        }

        return $this->success([
            'total_urls' => count($validUrls),
            'domains_count' => count($domains),
            'domains' => array_values($domains),
            'estimates' => $estimates,
            'social_media_count' => $socialMediaCount,
            'warnings' => $warnings,
            'invalid_count' => count($result['invalid']),
            'invalid_urls' => array_slice($result['invalid'], 0, 10), // First 10 only
        ]);
    }

    /**
     * GET /api/v1/settings
     * Get all settings
     */
    private function getSettings(): array
    {
        $settings = $this->dashboard->getSettings();
        return $this->success(['settings' => $settings]);
    }

    /**
     * POST /api/v1/settings
     * Update settings
     */
    private function updateSettings(array $params): array
    {
        $key = $params['key'] ?? '';
        $value = $params['value'] ?? null;

        if (empty($key)) {
            return $this->error('Setting key required', 400);
        }

        $success = $this->dashboard->updateSetting($key, $value);

        if (!$success) {
            return $this->error('Failed to update setting', 400);
        }

        return $this->success(['message' => 'Setting updated', 'key' => $key]);
    }

    /**
     * Format success response
     */
    private function success(array $data, int $code = 200): array
    {
        return [
            'success' => true,
            'data' => $data,
            'meta' => [
                'api_version' => self::VERSION,
                'timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
            ],
            'http_code' => $code,
        ];
    }

    /**
     * Format error response
     */
    private function error(string $message, int $code = 400): array
    {
        return [
            'success' => false,
            'error' => [
                'message' => $message,
                'code' => $code,
            ],
            'meta' => [
                'api_version' => self::VERSION,
                'timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
            ],
            'http_code' => $code,
        ];
    }
}
