<?php
/**
 * Instagram Graph API Publishing Service
 * Handles publishing content to Instagram Business/Creator accounts
 */

require_once __DIR__ . '/../config/config.php';

class InstagramService {
    private $db;

    public function __construct() {
        $this->db = Database::getInstance()->getConnection();
    }

    /**
     * Publish content to Instagram
     * Instagram uses a two-step process: create container, then publish
     *
     * @param array $data Publication data
     * @return array Result with media_id
     */
    public function publish($data) {
        // Validate required fields
        if (empty($data['image_url']) && empty($data['video_url'])) {
            return ['success' => false, 'message' => 'Instagram requires image_url or video_url'];
        }

        // Get Instagram settings
        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        // Check if Instagram is enabled
        if (empty($config['ENABLED']) || $config['ENABLED'] !== '1') {
            return ['success' => false, 'message' => 'Instagram publishing is not enabled'];
        }

        // Validate configuration
        if (empty($config['USER_ID']) || empty($config['ACCESS_TOKEN'])) {
            return ['success' => false, 'message' => 'Instagram configuration incomplete'];
        }

        // Step 1: Create media container
        $containerResult = $this->createMediaContainer($config, $data);
        if (!$containerResult['success']) {
            $this->logPublication([
                'platform' => 'instagram',
                'post_id' => null,
                'content' => $data['caption'] ?? '',
                'status' => 'failed',
                'error_message' => $containerResult['message']
            ]);
            return $containerResult;
        }

        $containerId = $containerResult['data']['id'];

        // Step 2: Publish the container
        $publishResult = $this->publishContainer($config, $containerId);
        if (!$publishResult['success']) {
            $this->logPublication([
                'platform' => 'instagram',
                'post_id' => $containerId,
                'content' => $data['caption'] ?? '',
                'status' => 'failed',
                'error_message' => $publishResult['message']
            ]);
            return $publishResult;
        }

        // Log successful publication
        $this->logPublication([
            'platform' => 'instagram',
            'post_id' => $publishResult['data']['id'],
            'content' => $data['caption'] ?? '',
            'status' => 'published',
            'response' => json_encode($publishResult['data'])
        ]);

        return [
            'success' => true,
            'data' => [
                'media_id' => $publishResult['data']['id'],
                'platform' => 'instagram'
            ]
        ];
    }

    /**
     * Create Instagram media container
     *
     * @param array $config Instagram configuration
     * @param array $data Media data
     * @return array Container creation result
     */
    private function createMediaContainer($config, $data) {
        $params = [
            'access_token' => $config['ACCESS_TOKEN']
        ];

        // Add caption if provided
        if (!empty($data['caption'])) {
            $params['caption'] = $data['caption'];
        }

        // Determine media type
        if (!empty($data['video_url'])) {
            // Video post
            $params['media_type'] = 'VIDEO';
            $params['video_url'] = $data['video_url'];

            // Add video thumbnail if provided
            if (!empty($data['thumbnail_url'])) {
                $params['thumb_offset'] = $data['thumbnail_url'];
            }
        } else if (!empty($data['carousel_items'])) {
            // Carousel post (multiple images/videos)
            return $this->createCarouselContainer($config, $data);
        } else {
            // Single image post
            $params['image_url'] = $data['image_url'];
        }

        // Add location if provided
        if (!empty($data['location_id'])) {
            $params['location_id'] = $data['location_id'];
        }

        // Add user tags if provided
        if (!empty($data['user_tags'])) {
            $params['user_tags'] = json_encode($data['user_tags']);
        }

        return $this->callGraphAPI("/{$config['USER_ID']}/media", 'POST', $params);
    }

    /**
     * Create carousel container (multiple items)
     *
     * @param array $config Instagram configuration
     * @param array $data Carousel data
     * @return array Container creation result
     */
    private function createCarouselContainer($config, $data) {
        $childrenIds = [];

        // Create container for each item
        foreach ($data['carousel_items'] as $item) {
            $itemParams = [
                'access_token' => $config['ACCESS_TOKEN'],
                'is_carousel_item' => true
            ];

            if (!empty($item['video_url'])) {
                $itemParams['media_type'] = 'VIDEO';
                $itemParams['video_url'] = $item['video_url'];
            } else {
                $itemParams['image_url'] = $item['image_url'];
            }

            $result = $this->callGraphAPI("/{$config['USER_ID']}/media", 'POST', $itemParams);
            if (!$result['success']) {
                return $result;
            }

            $childrenIds[] = $result['data']['id'];
        }

        // Create carousel container
        $carouselParams = [
            'media_type' => 'CAROUSEL',
            'children' => implode(',', $childrenIds),
            'access_token' => $config['ACCESS_TOKEN']
        ];

        if (!empty($data['caption'])) {
            $carouselParams['caption'] = $data['caption'];
        }

        return $this->callGraphAPI("/{$config['USER_ID']}/media", 'POST', $carouselParams);
    }

    /**
     * Publish media container
     *
     * @param array $config Instagram configuration
     * @param string $containerId Container ID
     * @return array Publish result
     */
    private function publishContainer($config, $containerId) {
        return $this->callGraphAPI("/{$config['USER_ID']}/media_publish", 'POST', [
            'creation_id' => $containerId,
            'access_token' => $config['ACCESS_TOKEN']
        ]);
    }

    /**
     * Get media details
     *
     * @param string $mediaId Instagram media ID
     * @return array Media data
     */
    public function getMedia($mediaId) {
        if (empty($mediaId)) {
            return ['success' => false, 'message' => 'Media ID is required'];
        }

        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        return $this->callGraphAPI("/{$mediaId}", 'GET', [
            'fields' => 'id,caption,media_type,media_url,permalink,thumbnail_url,timestamp,username,like_count,comments_count',
            'access_token' => $config['ACCESS_TOKEN']
        ]);
    }

    /**
     * Delete Instagram media
     * Note: Only available for certain media types
     *
     * @param string $mediaId Media ID
     * @return array Result
     */
    public function deleteMedia($mediaId) {
        if (empty($mediaId)) {
            return ['success' => false, 'message' => 'Media ID is required'];
        }

        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        return $this->callGraphAPI("/{$mediaId}", 'DELETE', [
            'access_token' => $config['ACCESS_TOKEN']
        ]);
    }

    /**
     * Get account insights
     *
     * @param array $metrics Metrics to retrieve
     * @param string $period Time period
     * @return array Insights data
     */
    public function getInsights($metrics = [], $period = 'day') {
        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        if (empty($metrics)) {
            $metrics = ['impressions', 'reach', 'profile_views'];
        }

        $params = [
            'metric' => implode(',', $metrics),
            'period' => $period,
            'access_token' => $config['ACCESS_TOKEN']
        ];

        return $this->callGraphAPI("/{$config['USER_ID']}/insights", 'GET', $params);
    }

    /**
     * Get media insights
     *
     * @param string $mediaId Media ID
     * @param array $metrics Metrics to retrieve
     * @return array Insights data
     */
    public function getMediaInsights($mediaId, $metrics = []) {
        if (empty($mediaId)) {
            return ['success' => false, 'message' => 'Media ID is required'];
        }

        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        if (empty($metrics)) {
            $metrics = ['engagement', 'impressions', 'reach', 'saved'];
        }

        return $this->callGraphAPI("/{$mediaId}/insights", 'GET', [
            'metric' => implode(',', $metrics),
            'access_token' => $config['ACCESS_TOKEN']
        ]);
    }

    /**
     * Reply to comment
     *
     * @param string $commentId Comment ID
     * @param string $message Reply message
     * @return array Result
     */
    public function replyToComment($commentId, $message) {
        if (empty($commentId) || empty($message)) {
            return ['success' => false, 'message' => 'Comment ID and message are required'];
        }

        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        return $this->callGraphAPI("/{$commentId}/replies", 'POST', [
            'message' => $message,
            'access_token' => $config['ACCESS_TOKEN']
        ]);
    }

    /**
     * Test Instagram API connection
     *
     * @return array Test result
     */
    public function testConnection() {
        $settings = $this->getSettings();
        if (!$settings['success']) {
            return $settings;
        }

        $config = $settings['data'];

        if (empty($config['USER_ID']) || empty($config['ACCESS_TOKEN'])) {
            return ['success' => false, 'message' => 'Missing USER_ID or ACCESS_TOKEN'];
        }

        // Try to get account info
        $result = $this->callGraphAPI("/{$config['USER_ID']}", 'GET', [
            'fields' => 'id,username,account_type,media_count',
            'access_token' => $config['ACCESS_TOKEN']
        ]);

        if ($result['success']) {
            return [
                'success' => true,
                'message' => 'Connection successful',
                'data' => [
                    'username' => $result['data']['username'] ?? 'Unknown',
                    'user_id' => $result['data']['id'] ?? 'Unknown',
                    'account_type' => $result['data']['account_type'] ?? 'Unknown',
                    'media_count' => $result['data']['media_count'] ?? 0
                ]
            ];
        }

        return $result;
    }

    /**
     * Call Instagram Graph API
     *
     * @param string $endpoint API endpoint
     * @param string $method HTTP method
     * @param array $params Parameters
     * @return array Response data
     */
    private function callGraphAPI($endpoint, $method = 'GET', $params = []) {
        $baseUrl = 'https://graph.facebook.com/v18.0';
        $url = $baseUrl . $endpoint;

        $ch = curl_init();

        if ($method === 'GET') {
            if (!empty($params)) {
                $url .= '?' . http_build_query($params);
            }
            curl_setopt($ch, CURLOPT_URL, $url);
        } else {
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));

            if ($method === 'DELETE') {
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
            } else {
                curl_setopt($ch, CURLOPT_POST, true);
            }
        }

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60); // Instagram video uploads may take longer
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded'
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);

        curl_close($ch);

        if ($error) {
            return [
                'success' => false,
                'message' => 'cURL error: ' . $error
            ];
        }

        $data = json_decode($response, true);

        if ($httpCode >= 200 && $httpCode < 300) {
            return [
                'success' => true,
                'data' => $data
            ];
        }

        // Handle error response
        $errorMessage = 'API request failed';
        if (isset($data['error']['message'])) {
            $errorMessage = $data['error']['message'];
        }

        return [
            'success' => false,
            'message' => $errorMessage,
            'error_code' => $data['error']['code'] ?? null,
            'http_code' => $httpCode
        ];
    }

    /**
     * Get Instagram settings
     *
     * @return array Settings data
     */
    private function getSettings() {
        try {
            $stmt = $this->db->prepare("
                SELECT `key`, `value_encrypted` as value
                FROM settings
                WHERE section = 'instagram'
            ");
            $stmt->execute();
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $settings = [];
            foreach ($rows as $row) {
                // Map database keys to expected keys
                $key = strtoupper(str_replace('IG_', '', $row['key']));
                $settings[$key] = $row['value'];
            }

            // Add defaults if not set
            if (!isset($settings['ENABLED'])) {
                // Check from common settings
                $stmt = $this->db->prepare("SELECT value_encrypted FROM settings WHERE section='common' AND `key`='IG_ENABLED'");
                $stmt->execute();
                $result = $stmt->fetch(PDO::FETCH_ASSOC);
                $settings['ENABLED'] = $result ? ($result['value_encrypted'] === 'true' ? '1' : '0') : '0';
            }

            return ['success' => true, 'data' => $settings];

        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => 'Failed to load settings: ' . $e->getMessage()
            ];
        }
    }

    /**
     * Log publication record
     *
     * @param array $data Publication data
     */
    private function logPublication($data) {
        try {
            $stmt = $this->db->prepare("
                INSERT INTO publish_records (
                    schedule_date, content_id, platform, platform_post_id,
                    status, error_message, published_at
                ) VALUES (CURDATE(), ?, ?, ?, ?, ?, ?)
            ");

            $stmt->execute([
                'manual_' . time(),
                $data['platform'],
                $data['post_id'] ?? null,
                $data['status'],
                $data['error_message'] ?? null,
                $data['status'] === 'published' ? date('Y-m-d H:i:s') : null
            ]);

        } catch (Exception $e) {
            error_log('Failed to log publication: ' . $e->getMessage());
        }
    }
}
