<?php
/**
 * ===========================================
 * FLOWBOT DCI - DASHBOARD SERVICE v3.0
 * ===========================================
 * Provides data aggregation and statistics for the dashboard
 *
 * Features:
 * - Real-time process statistics
 * - Process history with pagination
 * - Activity feed
 * - Chart data for visualizations
 * - Domain success rate tracking
 */

declare(strict_types=1);

namespace FlowbotDCI\Services;

use FlowbotDCI\Core\Database;
use PDO;

class DashboardService
{
    private Database $db;
    private string $tempDir;

    public function __construct(Database $db, string $tempDir)
    {
        $this->db = $db;
        $this->tempDir = $tempDir;
    }

    /**
     * Get aggregated dashboard statistics
     */
    public function getStats(): array
    {
        $pdo = $this->db->getConnection();

        // Get counts from database
        $dbStats = $this->getDbStats($pdo);

        // Get active processes from temp files
        $activeProcesses = $this->getActiveProcessesFromTemp();

        return [
            'active' => count($activeProcesses),
            'completed' => $dbStats['completed'] ?? 0,
            'failed' => $dbStats['failed'] ?? 0,
            'today' => $dbStats['today'] ?? 0,
            'total_urls' => $dbStats['total_urls'] ?? 0,
            'total_processes' => $dbStats['total_processes'] ?? 0,
            'success_rate' => $this->calculateOverallSuccessRate($pdo),
            'avg_processing_time' => $dbStats['avg_time'] ?? 0,
            'last_updated' => date('Y-m-d H:i:s'),
        ];
    }

    /**
     * Get database statistics
     */
    private function getDbStats(PDO $pdo): array
    {
        try {
            $stmt = $pdo->query("
                SELECT
                    COUNT(*) as total_processes,
                    SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
                    SUM(CASE WHEN status IN ('failed', 'cancelled') THEN 1 ELSE 0 END) as failed,
                    SUM(CASE WHEN DATE(created_at) = CURDATE() THEN 1 ELSE 0 END) as today,
                    SUM(total_urls) as total_urls,
                    AVG(TIMESTAMPDIFF(SECOND, started_at, completed_at)) as avg_time
                FROM process_history
                WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
            ");
            return $stmt->fetch() ?: [];
        } catch (\PDOException $e) {
            // Table might not exist yet
            return [];
        }
    }

    /**
     * Calculate overall success rate
     */
    private function calculateOverallSuccessRate(PDO $pdo): float
    {
        try {
            $stmt = $pdo->query("
                SELECT
                    SUM(success_count) as total_success,
                    SUM(total_urls) as total_urls
                FROM process_history
                WHERE status = 'completed'
                AND created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
            ");
            $row = $stmt->fetch();
            if ($row && $row['total_urls'] > 0) {
                return round(($row['total_success'] / $row['total_urls']) * 100, 1);
            }
        } catch (\PDOException $e) {
            // Ignore if table doesn't exist
        }
        return 0.0;
    }

    /**
     * Get active processes from temp directory
     */
    public function getActiveProcesses(): array
    {
        return $this->getActiveProcessesFromTemp();
    }

    /**
     * Scan temp directory for active processes
     * Updated to support both batch_* and process_* directory formats
     */
    private function getActiveProcessesFromTemp(): array
    {
        $processes = [];

        if (!is_dir($this->tempDir)) {
            return $processes;
        }

        // Support both batch_* and process_* directory patterns
        $batchDirs = glob($this->tempDir . '/batch_*', GLOB_ONLYDIR);
        $processDirs = glob($this->tempDir . '/process_*', GLOB_ONLYDIR);
        $dirs = array_merge($batchDirs, $processDirs);

        foreach ($dirs as $dir) {
            $processId = basename($dir);

            // Try multiple progress file formats
            $progressFile = $dir . '/' . $processId . '_progress.json';
            if (!file_exists($progressFile)) {
                $progressFile = $dir . '/progress.json';
            }

            if (file_exists($progressFile)) {
                $data = json_decode(file_get_contents($progressFile), true);

                if ($data) {
                    // Check if complete using the actual field names
                    $totalRemaining = 0;
                    foreach ($data['phase_queues'] ?? [] as $queue) {
                        $totalRemaining += count($queue);
                    }
                    $isComplete = $totalRemaining === 0 && ($data['processed_links'] ?? 0) > 0;

                    if (!$isComplete) {
                        $totalUrls = $data['total_links'] ?? $data['totalUrls'] ?? 0;
                        $processedUrls = $data['processed_links'] ?? $data['processedUrls'] ?? 0;

                        $processes[] = [
                            'id' => $processId,
                            'total_urls' => $totalUrls,
                            'processed_urls' => $processedUrls,
                            'success_count' => $data['imported_links'] ?? $data['successUrls'] ?? 0,
                            'failed_count' => $data['error_links'] ?? $data['failedUrls'] ?? 0,
                            'progress_percent' => $totalUrls > 0 ? round(($processedUrls / $totalUrls) * 100, 1) : 0,
                            'phase' => $data['phase_index'] ?? $data['currentPhase'] ?? 0,
                            'current_url' => $data['currentUrl'] ?? null,
                            'status' => $data['isPaused'] ?? false ? 'paused' : 'running',
                            'started_at' => $data['startTime'] ?? null,
                            'eta_seconds' => $this->calculateEta($data),
                        ];
                    }
                }
            }
        }

        return $processes;
    }

    /**
     * Calculate ETA in seconds
     * Updated to support both new and old field formats
     */
    private function calculateEta(array $data): ?int
    {
        $processed = $data['processed_links'] ?? $data['processedUrls'] ?? 0;
        $total = $data['total_links'] ?? $data['totalUrls'] ?? 0;

        // Use remaining_time if already calculated
        if (isset($data['remaining_time']) && $data['remaining_time'] > 0) {
            return (int)$data['remaining_time'];
        }

        // Use elapsed_time and processing_rate if available
        if (isset($data['elapsed_time']) && isset($data['processing_rate']) && $data['processing_rate'] > 0) {
            $remaining = $total - $processed;
            return $remaining > 0 ? (int)($remaining / $data['processing_rate']) : 0;
        }

        $startTime = $data['startTime'] ?? null;
        if ($processed <= 0 || $total <= 0 || !$startTime) {
            return null;
        }

        $elapsed = time() - strtotime($startTime);
        $urlsPerSecond = $processed / max(1, $elapsed);
        $remaining = $total - $processed;

        return $urlsPerSecond > 0 ? (int)($remaining / $urlsPerSecond) : null;
    }

    /**
     * Get process history with pagination, search, and sorting
     */
    public function getHistory(int $page = 1, int $limit = 20, array $filters = []): array
    {
        $pdo = $this->db->getConnection();
        $offset = ($page - 1) * $limit;

        // Build query with filters
        $where = ['1=1'];
        $params = [];

        if (!empty($filters['status'])) {
            $where[] = 'status = ?';
            $params[] = $filters['status'];
        }

        if (!empty($filters['date_from'])) {
            $where[] = 'created_at >= ?';
            $params[] = $filters['date_from'];
        }

        if (!empty($filters['date_to'])) {
            $where[] = 'created_at <= ?';
            $params[] = $filters['date_to'] . ' 23:59:59';
        }

        // Search by ID
        if (!empty($filters['search'])) {
            $where[] = 'id LIKE ?';
            $params[] = '%' . $filters['search'] . '%';
        }

        $whereClause = implode(' AND ', $where);

        // Handle sorting
        $validColumns = ['id', 'total_urls', 'status', 'mode', 'created_at'];
        $sortBy = in_array($filters['sort'] ?? '', $validColumns) ? $filters['sort'] : 'created_at';
        $sortOrder = ($filters['order'] ?? 'desc') === 'asc' ? 'ASC' : 'DESC';
        $orderClause = "{$sortBy} {$sortOrder}";

        try {
            // Get total count
            $countStmt = $pdo->prepare("SELECT COUNT(*) FROM process_history WHERE {$whereClause}");
            $countStmt->execute($params);
            $total = (int)$countStmt->fetchColumn();

            // Get paginated results (including extra fields for expandable details)
            $stmt = $pdo->prepare("
                SELECT
                    id,
                    name,
                    total_urls,
                    processed_urls,
                    success_count,
                    failed_count,
                    status,
                    mode,
                    options,
                    error_message,
                    current_phase,
                    TIMESTAMPDIFF(SECOND, started_at, COALESCE(completed_at, NOW())) as duration_seconds,
                    started_at,
                    completed_at,
                    created_at
                FROM process_history
                WHERE {$whereClause}
                ORDER BY {$orderClause}
                LIMIT ? OFFSET ?
            ");
            $params[] = $limit;
            $params[] = $offset;
            $stmt->execute($params);
            $items = $stmt->fetchAll();

            return [
                'items' => $items,
                'total' => $total,
                'page' => $page,
                'limit' => $limit,
                'total_pages' => (int)ceil($total / $limit),
            ];
        } catch (\PDOException $e) {
            return [
                'items' => [],
                'total' => 0,
                'page' => $page,
                'limit' => $limit,
                'total_pages' => 0,
            ];
        }
    }

    /**
     * Get recent activity events
     */
    public function getRecentActivity(int $limit = 20): array
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                SELECT
                    al.id,
                    al.process_id,
                    al.event_type,
                    al.severity,
                    al.message,
                    al.metadata,
                    al.created_at,
                    ph.name as process_name
                FROM activity_log al
                LEFT JOIN process_history ph ON al.process_id = ph.id
                ORDER BY al.created_at DESC
                LIMIT ?
            ");
            $stmt->execute([$limit]);
            $events = $stmt->fetchAll();

            // Decode JSON metadata
            foreach ($events as &$event) {
                $event['metadata'] = json_decode($event['metadata'] ?? '{}', true);
            }

            return $events;
        } catch (\PDOException $e) {
            return [];
        }
    }

    /**
     * Get chart data for visualizations
     */
    public function getChartData(string $period = '7d'): array
    {
        $pdo = $this->db->getConnection();

        $days = match($period) {
            '30d' => 30,
            '90d' => 90,
            default => 7,
        };

        try {
            // Success rate over time
            $stmt = $pdo->prepare("
                SELECT
                    DATE(created_at) as date,
                    SUM(success_count) as success,
                    SUM(failed_count) as failed,
                    SUM(total_urls) as total,
                    COUNT(*) as processes
                FROM process_history
                WHERE created_at > DATE_SUB(NOW(), INTERVAL ? DAY)
                AND status = 'completed'
                GROUP BY DATE(created_at)
                ORDER BY date ASC
            ");
            $stmt->execute([$days]);
            $dailyStats = $stmt->fetchAll();

            // Domain distribution
            $stmt = $pdo->prepare("
                SELECT
                    domain,
                    total_requests,
                    success_count,
                    success_rate,
                    is_social_media
                FROM domain_stats
                ORDER BY total_requests DESC
                LIMIT 10
            ");
            $stmt->execute();
            $topDomains = $stmt->fetchAll();

            // Error distribution
            $stmt = $pdo->query("
                SELECT
                    SUM(error_403_count) as forbidden,
                    SUM(error_timeout_count) as timeout,
                    SUM(error_other_count) as other,
                    SUM(success_count) as success
                FROM domain_stats
            ");
            $errorDist = $stmt->fetch();

            return [
                'daily_stats' => $dailyStats,
                'top_domains' => $topDomains,
                'error_distribution' => $errorDist,
                'period' => $period,
            ];
        } catch (\PDOException $e) {
            return [
                'daily_stats' => [],
                'top_domains' => [],
                'error_distribution' => [],
                'period' => $period,
            ];
        }
    }

    /**
     * Estimate processing time for given URLs
     */
    public function estimateProcessingTime(int $urlCount, array $domains = []): array
    {
        // Base estimate: 2-5 seconds per URL depending on mode
        $estimates = [
            'fast' => [
                'time_seconds' => (int)($urlCount * 1.5),
                'success_rate' => 70,
            ],
            'standard' => [
                'time_seconds' => (int)($urlCount * 3),
                'success_rate' => 85,
            ],
            'thorough' => [
                'time_seconds' => (int)($urlCount * 6),
                'success_rate' => 95,
            ],
        ];

        // Adjust based on domain history if available
        if (!empty($domains)) {
            $avgSuccessRate = $this->getDomainsAvgSuccessRate($domains);
            if ($avgSuccessRate > 0) {
                foreach ($estimates as &$est) {
                    $est['success_rate'] = (int)(($est['success_rate'] + $avgSuccessRate) / 2);
                }
            }
        }

        return $estimates;
    }

    /**
     * Get average success rate for domains
     */
    private function getDomainsAvgSuccessRate(array $domains): float
    {
        if (empty($domains)) {
            return 0;
        }

        $pdo = $this->db->getConnection();

        try {
            $placeholders = implode(',', array_fill(0, count($domains), '?'));
            $stmt = $pdo->prepare("
                SELECT AVG(success_rate) as avg_rate
                FROM domain_stats
                WHERE domain IN ({$placeholders})
            ");
            $stmt->execute($domains);
            $result = $stmt->fetch();
            return (float)($result['avg_rate'] ?? 0);
        } catch (\PDOException $e) {
            return 0;
        }
    }

    /**
     * Get domain success rate
     */
    public function getDomainSuccessRate(string $domain): float
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                SELECT success_rate
                FROM domain_stats
                WHERE domain = ?
            ");
            $stmt->execute([$domain]);
            $result = $stmt->fetch();
            return (float)($result['success_rate'] ?? 0);
        } catch (\PDOException $e) {
            return 0;
        }
    }

    /**
     * Update domain statistics after processing
     */
    public function updateDomainStats(string $domain, bool $success, int $responseTime, ?int $httpCode = null, bool $isSocialMedia = false): void
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                INSERT INTO domain_stats (domain, total_requests, success_count, error_403_count, error_timeout_count, error_other_count, avg_response_time, last_success, last_failure, is_social_media)
                VALUES (?, 1, ?, ?, ?, ?, ?, ?, ?, ?)
                ON DUPLICATE KEY UPDATE
                    total_requests = total_requests + 1,
                    success_count = success_count + ?,
                    error_403_count = error_403_count + ?,
                    error_timeout_count = error_timeout_count + ?,
                    error_other_count = error_other_count + ?,
                    avg_response_time = (avg_response_time * (total_requests - 1) + ?) / total_requests,
                    last_success = IF(? = 1, NOW(), last_success),
                    last_failure = IF(? = 0, NOW(), last_failure),
                    is_social_media = GREATEST(is_social_media, ?)
            ");

            $isSuccess = $success ? 1 : 0;
            $is403 = (!$success && $httpCode === 403) ? 1 : 0;
            $isTimeout = (!$success && $httpCode === 0) ? 1 : 0;
            $isOther = (!$success && $httpCode !== 403 && $httpCode !== 0) ? 1 : 0;
            $isSocial = $isSocialMedia ? 1 : 0;

            $stmt->execute([
                $domain,
                $isSuccess,
                $is403,
                $isTimeout,
                $isOther,
                $responseTime,
                $success ? date('Y-m-d H:i:s') : null,
                !$success ? date('Y-m-d H:i:s') : null,
                $isSocial,
                // ON DUPLICATE KEY UPDATE values
                $isSuccess,
                $is403,
                $isTimeout,
                $isOther,
                $responseTime,
                $isSuccess,
                $isSuccess,
                $isSocial,
            ]);
        } catch (\PDOException $e) {
            error_log("Failed to update domain stats: " . $e->getMessage());
        }
    }

    /**
     * Log activity event
     */
    public function logActivity(string $eventType, string $message, ?string $processId = null, string $severity = 'info', array $metadata = []): void
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                INSERT INTO activity_log (process_id, event_type, severity, message, metadata)
                VALUES (?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $processId,
                $eventType,
                $severity,
                $message,
                json_encode($metadata),
            ]);
        } catch (\PDOException $e) {
            error_log("Failed to log activity: " . $e->getMessage());
        }
    }

    /**
     * Create process history record
     */
    public function createProcess(string $processId, int $totalUrls, string $mode = 'standard', array $options = []): bool
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                INSERT INTO process_history (id, total_urls, mode, options, status, created_at)
                VALUES (?, ?, ?, ?, 'pending', NOW())
            ");
            return $stmt->execute([
                $processId,
                $totalUrls,
                $mode,
                json_encode($options),
            ]);
        } catch (\PDOException $e) {
            error_log("Failed to create process: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Update process history record
     */
    public function updateProcess(string $processId, array $data): bool
    {
        $pdo = $this->db->getConnection();

        $fields = [];
        $values = [];

        foreach ($data as $key => $value) {
            $fields[] = "{$key} = ?";
            $values[] = $value;
        }

        $values[] = $processId;

        try {
            $stmt = $pdo->prepare("
                UPDATE process_history
                SET " . implode(', ', $fields) . "
                WHERE id = ?
            ");
            return $stmt->execute($values);
        } catch (\PDOException $e) {
            error_log("Failed to update process: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Get process by ID
     */
    public function getProcess(string $processId): ?array
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                SELECT * FROM process_history WHERE id = ?
            ");
            $stmt->execute([$processId]);
            $result = $stmt->fetch();
            return $result ?: null;
        } catch (\PDOException $e) {
            return null;
        }
    }

    /**
     * Delete process and related data
     * v5.0 FIX: Now checks ALL possible directory formats and deletes ALL matching
     */
    public function deleteProcess(string $processId): bool
    {
        $pdo = $this->db->getConnection();

        try {
            $this->db->beginTransaction();

            // Delete from process_history (cascades to activity_log and process_urls)
            $stmt = $pdo->prepare("DELETE FROM process_history WHERE id = ?");
            $stmt->execute([$processId]);

            // v5.0 FIX: Check ALL possible temp directory formats and delete ALL
            $possiblePaths = [
                $this->tempDir . '/' . $processId,           // Direct (e.g., batch_xxx)
                $this->tempDir . '/process_' . $processId,   // process_ prefix
                $this->tempDir . '/batch_' . $processId,     // batch_ prefix (if id doesn't have it)
            ];

            $deletedPaths = [];
            foreach ($possiblePaths as $tempPath) {
                if (is_dir($tempPath)) {
                    $this->deleteDirectory($tempPath);
                    $deletedPaths[] = $tempPath;
                    // v5.0 FIX: Continue checking ALL paths, don't break!
                    // This ensures we clean up any orphan directories
                }
            }

            if (!empty($deletedPaths)) {
                error_log("deleteProcess({$processId}) - Deleted directories: " . implode(', ', $deletedPaths));
            }

            $this->db->commit();
            return true;
        } catch (\PDOException $e) {
            $this->db->rollback();
            error_log("Failed to delete process: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Recursively delete directory
     */
    private function deleteDirectory(string $dir): void
    {
        if (!is_dir($dir)) {
            return;
        }

        $files = array_diff(scandir($dir), ['.', '..']);
        foreach ($files as $file) {
            $path = $dir . '/' . $file;
            is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
        }
        rmdir($dir);
    }

    /**
     * Get settings
     */
    public function getSettings(): array
    {
        $pdo = $this->db->getConnection();

        try {
            // Note: settings table uses `key`, `value`, `type` column names
            $stmt = $pdo->query("SELECT `key`, `value`, `type` FROM settings");
            $rows = $stmt->fetchAll();

            $settings = [];
            foreach ($rows as $row) {
                $value = $row['value'];
                switch ($row['type'] ?? 'string') {
                    case 'int':
                        $value = (int)$value;
                        break;
                    case 'float':
                        $value = (float)$value;
                        break;
                    case 'bool':
                        $value = $value === 'true' || $value === '1';
                        break;
                    case 'json':
                        $value = json_decode($value, true);
                        break;
                }
                $settings[$row['key']] = $value;
            }

            return $settings;
        } catch (\PDOException $e) {
            return [];
        }
    }

    /**
     * Update setting
     */
    public function updateSetting(string $key, $value): bool
    {
        $pdo = $this->db->getConnection();

        try {
            if (is_bool($value)) {
                $value = $value ? 'true' : 'false';
            } elseif (is_array($value)) {
                $value = json_encode($value);
            }

            // Note: settings table uses `key` and `value` column names
            $stmt = $pdo->prepare("
                UPDATE settings SET `value` = ? WHERE `key` = ?
            ");
            return $stmt->execute([(string)$value, $key]);
        } catch (\PDOException $e) {
            return false;
        }
    }

    /**
     * Get detailed process information
     */
    public function getProcessDetails(string $processId): ?array
    {
        $pdo = $this->db->getConnection();

        try {
            $stmt = $pdo->prepare("
                SELECT
                    id,
                    name,
                    total_urls,
                    processed_urls,
                    success_count,
                    failed_count,
                    status,
                    mode,
                    options,
                    error_message,
                    current_phase,
                    TIMESTAMPDIFF(SECOND, started_at, COALESCE(completed_at, NOW())) as duration_seconds,
                    started_at,
                    completed_at,
                    created_at,
                    updated_at
                FROM process_history
                WHERE id = ?
            ");
            $stmt->execute([$processId]);
            $process = $stmt->fetch();

            if (!$process) {
                return null;
            }

            // Decode options JSON
            $process['options'] = json_decode($process['options'] ?? '{}', true);

            // Calculate additional stats
            $process['progress_percent'] = $process['total_urls'] > 0
                ? round(($process['processed_urls'] / $process['total_urls']) * 100, 1)
                : 0;

            $process['success_rate'] = ($process['success_count'] + $process['failed_count']) > 0
                ? round(($process['success_count'] / ($process['success_count'] + $process['failed_count'])) * 100, 1)
                : 0;

            return $process;
        } catch (\PDOException $e) {
            return null;
        }
    }

    /**
     * Get URLs from a process (from temp files or database)
     */
    public function getProcessUrls(string $processId): array
    {
        // Try to get URLs from temp progress file
        $tempDir = $this->config['paths']['temp'] ?? sys_get_temp_dir();
        $progressFile = "{$tempDir}/{$processId}/progress.json";

        if (file_exists($progressFile)) {
            $data = json_decode(file_get_contents($progressFile), true);
            if (isset($data['urls']) && is_array($data['urls'])) {
                return $data['urls'];
            }
        }

        // Try to get from links file
        $linksFile = "{$tempDir}/{$processId}/links.json";
        if (file_exists($linksFile)) {
            $links = json_decode(file_get_contents($linksFile), true);
            if (is_array($links)) {
                return $links;
            }
        }

        // Try process_urls table if available
        $pdo = $this->db->getConnection();
        try {
            $stmt = $pdo->prepare("SELECT url FROM process_urls WHERE process_id = ?");
            $stmt->execute([$processId]);
            $urls = $stmt->fetchAll(\PDO::FETCH_COLUMN);
            if (!empty($urls)) {
                return $urls;
            }
        } catch (\PDOException $e) {
            // Table might not exist, continue
        }

        return [];
    }

    /**
     * Reprocess a process (create new process with same URLs)
     */
    public function reprocessProcess(string $processId, array $newOptions = []): ?string
    {
        // Get original process details
        $original = $this->getProcessDetails($processId);
        if (!$original) {
            return null;
        }

        // Get URLs from original process
        $urls = $this->getProcessUrls($processId);
        if (empty($urls)) {
            // If no URLs found, we can't reprocess
            return null;
        }

        // Generate new process ID
        $newProcessId = uniqid('batch_', true);

        // Merge options (new options override original)
        $options = array_merge($original['options'] ?? [], $newOptions);

        // Create new process record
        $created = $this->createProcess(
            $newProcessId,
            count($urls),
            $newOptions['mode'] ?? $original['mode'] ?? 'standard',
            $options
        );

        if (!$created) {
            return null;
        }

        // Store URLs for the new process
        $tempDir = $this->config['paths']['temp'] ?? sys_get_temp_dir();
        $processDir = "{$tempDir}/{$newProcessId}";
        if (!is_dir($processDir)) {
            mkdir($processDir, 0755, true);
        }

        // Save URLs to links file for new process
        file_put_contents("{$processDir}/links.json", json_encode($urls));

        // Initialize progress file
        $progress = [
            'total_links' => count($urls),
            'processed_links' => 0,
            'imported_links' => 0,
            'ignored_links' => 0,
            'error_links' => 0,
            'phase_index' => 0,
            'status' => 'pending',
            'urls' => $urls,
            'reprocessed_from' => $processId
        ];
        file_put_contents("{$processDir}/progress.json", json_encode($progress));

        return $newProcessId;
    }
}
