<?php
namespace App\Services;

use App\Repositories\ConfigRepository;
use App\Services\DidarApiService;
use App\Database\Connection;
use App\Utils\Logger;
use PDO;
use PDOException;

/**
 * Pipeline Service
 * Handles pipeline stages caching
 */
class PipelineService
{
    private $didarApi;
    private $configRepo;
    private $db;
    private static $cache = null;

    public function __construct(DidarApiService $didarApi, ConfigRepository $configRepo, Connection $db)
    {
        $this->didarApi = $didarApi;
        $this->configRepo = $configRepo;
        $this->db = $db;
    }

    public function getStages($pipelineId = null)
    {
        if (self::$cache !== null && $pipelineId === null) {
            return self::$cache;
        }
        
        try {
            $pdo = $this->db->getPdo();
            
            // Try to get from cache table
            if ($pipelineId) {
                $stmt = $pdo->prepare("SELECT stages_json FROM pipeline_cache WHERE pipeline_id = ?");
                $stmt->execute([$pipelineId]);
                $cached = $stmt->fetch(PDO::FETCH_ASSOC);
                if ($cached && !empty($cached['stages_json'])) {
                    $stages = json_decode($cached['stages_json'], true);
                    if ($stages) {
                        return $stages;
                    }
                }
            }

            if (method_exists($this->didarApi, 'isEnabled') && !$this->didarApi->isEnabled()) {
                Logger::logInfo("Didar API disabled - pipeline stages fetched from local cache only");
                if ($pipelineId) {
                    return [];
                }
                // Build in-memory cache from all locally cached pipelines if available
                $allRows = $pdo->query("SELECT pipeline_id, stages_json FROM pipeline_cache")->fetchAll(PDO::FETCH_ASSOC) ?: [];
                $allStages = [];
                foreach ($allRows as $row) {
                    $decoded = json_decode((string)($row['stages_json'] ?? ''), true);
                    if (is_array($decoded)) {
                        $allStages[$row['pipeline_id']] = $decoded;
                    }
                }
                self::$cache = $allStages;
                return $allStages;
            }
            
            // Fetch from API
            $res = $this->didarApi->call('/pipeline/list/0', 'POST');
            if (isset($res['error'])) {
                Logger::logError("Failed to fetch pipelines", null, ['error' => $res['error']]);
                return [];
            }
            
            $pipelines = $res['Response'] ?? [];
            $allStages = [];
            
            foreach ($pipelines as $pipeline) {
                $stages = $pipeline['Stages'] ?? [];
                $stageMap = [];
                foreach ($stages as $stage) {
                    $stageMap[$stage['Id']] = $stage['Title'];
                }
                $allStages[$pipeline['Id']] = $stageMap;
                
                // Cache it
                $maxRetries = 5;
                $attempt = 0;
                while ($attempt < $maxRetries) {
                    try {
                        // MySQL: INSERT ... ON DUPLICATE KEY UPDATE
                        $stmt = $pdo->prepare("INSERT INTO pipeline_cache (pipeline_id, pipeline_title, stages_json, cached_at) 
                                               VALUES (?, ?, ?, NOW())
                                               ON DUPLICATE KEY UPDATE 
                                               pipeline_title = VALUES(pipeline_title),
                                               stages_json = VALUES(stages_json),
                                               cached_at = NOW()");
                        $stmt->execute([
                            $pipeline['Id'],
                            $pipeline['Title'],
                            json_encode($stageMap, JSON_UNESCAPED_UNICODE)
                        ]);
                        break;
                    } catch (PDOException $e) {
                        $attempt++;
                        if ($attempt >= $maxRetries) {
                            Logger::logError("Failed to cache pipeline after $maxRetries attempts", $e);
                            break;
                        }
                        usleep(100000 * $attempt);
                    }
                }
            }
            
            self::$cache = $allStages;
            return $allStages;
        } catch (Exception $e) {
            Logger::logError("Error in getPipelineStages", $e);
            return [];
        }
    }

    public function getStageTitle($pipelineId, $stageId)
    {
        $stages = $this->getStages();
        if (isset($stages[$pipelineId][$stageId])) {
            return $stages[$pipelineId][$stageId];
        }
        return '';
    }
}

