<?php
namespace TrafficLight\ApiSdk;

/**
 * TrafficLight API PHP SDK
 * Easy integration with the TrafficLight API
 * 
 * @version 1.0.0
 */
class TrafficLightAPI {
    /**
     * API key for authentication
     * @var string
     */
    private $apiKey;
    
    /**
     * Base URL for API requests
     * @var string
     */
    private $baseUrl;
    
    /**
     * Initialize the TrafficLight API client
     * 
     * @param string $apiKey Your API key
     * @param string $baseUrl API base URL (optional)
     */
    public function __construct($apiKey, $baseUrl = 'https://imators.systems/traffic/api.php') {
        if (empty($apiKey)) {
            throw new \InvalidArgumentException('API key is required');
        }
        
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }
    
    /**
     * Make an API request
     * 
     * @param string $endpoint API endpoint
     * @param array $params Additional query parameters
     * @param string $method HTTP method (GET or POST)
     * @param array|null $data Request body for POST requests
     * @return array API response
     * @throws \Exception If the request fails
     */
    private function request($endpoint, $params = [], $method = 'GET', $data = null) {
        // Add endpoint and API key to parameters
        $params['endpoint'] = $endpoint;
        $params['api_key'] = $this->apiKey;
        
        // Build URL with query parameters
        $url = $this->baseUrl . '?' . http_build_query($params);
        
        // Initialize curl
        $ch = curl_init();
        
        // Set curl options
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            
            if ($data) {
                $jsonData = json_encode($data);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: application/json',
                    'Content-Length: ' . strlen($jsonData)
                ]);
            }
        }
        
        // Execute request
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        // Check for curl errors
        if (curl_errno($ch)) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new \Exception("cURL Error: $error");
        }
        
        curl_close($ch);
        
        // Parse JSON response
        $data = json_decode($response, true);
        
        if ($data === null) {
            throw new \Exception('Invalid JSON response');
        }
        
        // Check for API errors
        if ($httpCode >= 400 || (isset($data['status']) && $data['status'] === 'error')) {
            $message = isset($data['message']) ? $data['message'] : "HTTP Error: $httpCode";
            throw new \Exception($message);
        }
        
        // Return data
        return isset($data['data']) ? $data['data'] : $data;
    }
    
    /**
     * Get all traffic lights
     * 
     * @return array List of traffic lights
     * @throws \Exception If the request fails
     */
    public function getAllLights() {
        return $this->request('lights');
    }
    
    /**
     * Get a traffic light by ID
     * 
     * @param int $id Traffic light ID
     * @return array Traffic light details
     * @throws \Exception If the request fails
     */
    public function getLightById($id) {
        if (empty($id)) {
            throw new \InvalidArgumentException('ID is required');
        }
        
        return $this->request('light', ['id' => $id]);
    }
    
    /**
     * Get nearby traffic lights
     * 
     * @param float $lat Latitude
     * @param float $lng Longitude
     * @param float $radius Radius in kilometers (default: 1)
     * @return array List of nearby traffic lights
     * @throws \Exception If the request fails
     */
    public function getNearbyLights($lat, $lng, $radius = 1) {
        if (empty($lat) || empty($lng)) {
            throw new \InvalidArgumentException('Latitude and longitude are required');
        }
        
        return $this->request('nearby', [
            'lat' => $lat,
            'lng' => $lng,
            'radius' => $radius
        ]);
    }
    
    /**
     * Add a new traffic light
     * 
     * @param array $lightData Traffic light data
     * @return array Added traffic light
     * @throws \Exception If the request fails
     */
    public function addLight($lightData) {
        if (empty($lightData)) {
            throw new \InvalidArgumentException('Light data is required');
        }
        
        $requiredFields = ['name', 'latitude', 'longitude', 'direction', 'red_duration', 'green_duration'];
        foreach ($requiredFields as $field) {
            if (!isset($lightData[$field])) {
                throw new \InvalidArgumentException("$field is required");
            }
        }
        
        return $this->request('light', [], 'POST', $lightData);
    }
    
    /**
     * Update an existing traffic light
     * 
     * @param int $id Traffic light ID
     * @param array $lightData Updated traffic light data
     * @return array Updated traffic light
     * @throws \Exception If the request fails
     */
    public function updateLight($id, $lightData) {
        if (empty($id)) {
            throw new \InvalidArgumentException('ID is required');
        }
        
        if (empty($lightData) || !is_array($lightData)) {
            throw new \InvalidArgumentException('Update data is required');
        }
        
        $data = array_merge(['id' => $id], $lightData);
        return $this->request('update', [], 'POST', $data);
    }
    
    /**
     * Calculate the status of a traffic light
     * 
     * @param array $light Traffic light object
     * @return array Status information
     */
    public function calculateStatus($light) {
        $totalCycle = (int)$light['red_duration'] + (int)$light['green_duration'];
        $currentTime = time();
        $timeInCycle = $currentTime % $totalCycle;
        
        if ($timeInCycle < $light['red_duration']) {
            return [
                'current' => 'RED',
                'next_change' => $light['red_duration'] - $timeInCycle,
                'next_state' => 'GREEN',
                'cycle_position' => ($timeInCycle / $totalCycle) * 100
            ];
        } else {
            return [
                'current' => 'GREEN',
                'next_change' => $totalCycle - $timeInCycle,
                'next_state' => 'RED',
                'cycle_position' => ($timeInCycle / $totalCycle) * 100
            ];
        }
    }
}