<?php
/**
 * Cast Conductor Proprietary License v5
 * SPDX-License-Identifier: LicenseRef-CastConductor-Proprietary-v5
 * 
 * Copyright (c) 2025 CastConductor.com. All Rights Reserved.
 * See LICENSE file or https://castconductor.com/eula for full terms.
 */

/**
 * Feed Controller - REST API for feed parsing and management
 * 
 * Provides endpoints for:
 * - Fetching and parsing external feeds
 * - Managing feed configurations
 * - Caching and refresh control
 * 
 * @since 5.6.9
 */

if (!defined('ABSPATH')) {
    exit;
}

require_once plugin_dir_path(__FILE__) . '../utils/class-feed-parser.php';

class CastConductor_Feed_Controller extends WP_REST_Controller {
    
    /**
     * Namespace for REST routes
     */
    protected $namespace = 'castconductor/v5';
    
    /**
     * Base for REST routes
     */
    protected $rest_base = 'feeds';
    
    /**
     * Feed parser instance
     */
    private $parser;
    
    /**
     * Constructor
     */
    public function __construct() {
        $this->parser = new CastConductor_Feed_Parser();
    }
    
    /**
     * Register REST routes
     */
    public function register_routes() {
        // Parse feed endpoint (admin only - for configuration)
        register_rest_route($this->namespace, '/' . $this->rest_base . '/parse', array(
            array(
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => array($this, 'parse_feed'),
                'permission_callback' => array($this, 'admin_permission_check'),
                'args' => $this->get_parse_args(),
            ),
        ));
        
        // Get feed by URL (public - for Roku app)
        register_rest_route($this->namespace, '/' . $this->rest_base . '/get', array(
            array(
                'methods' => WP_REST_Server::READABLE,
                'callback' => array($this, 'get_feed'),
                'permission_callback' => '__return_true', // Public endpoint
                'args' => array(
                    'url' => array(
                        'required' => true,
                        'type' => 'string',
                        'description' => 'Feed URL to fetch',
                        'sanitize_callback' => 'esc_url_raw',
                    ),
                    'type' => array(
                        'required' => false,
                        'type' => 'string',
                        'default' => 'auto',
                        'enum' => array('auto', 'rss', 'mrss', 'atom', 'json', 'roku', 'youtube', 'soundcloud'),
                    ),
                    'max_items' => array(
                        'required' => false,
                        'type' => 'integer',
                        'default' => 50,
                        'minimum' => 1,
                        'maximum' => 100,
                    ),
                ),
            ),
        ));
        
        // Preview feed (for Canvas Editor)
        register_rest_route($this->namespace, '/' . $this->rest_base . '/preview', array(
            array(
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => array($this, 'preview_feed'),
                'permission_callback' => array($this, 'admin_permission_check'),
                'args' => $this->get_parse_args(),
            ),
        ));
        
        // Clear cache
        register_rest_route($this->namespace, '/' . $this->rest_base . '/cache/clear', array(
            array(
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => array($this, 'clear_cache'),
                'permission_callback' => array($this, 'admin_permission_check'),
                'args' => array(
                    'url' => array(
                        'required' => false,
                        'type' => 'string',
                        'description' => 'Specific feed URL to clear, or empty for all',
                    ),
                ),
            ),
        ));
        
        // Supported feed types
        register_rest_route($this->namespace, '/' . $this->rest_base . '/types', array(
            array(
                'methods' => WP_REST_Server::READABLE,
                'callback' => array($this, 'get_feed_types'),
                'permission_callback' => '__return_true',
            ),
        ));
    }
    
    /**
     * Check admin permissions
     * 
     * @param WP_REST_Request $request Request object
     * @return bool|WP_Error True if user can manage options
     */
    public function admin_permission_check($request) {
        if (!current_user_can('manage_options')) {
            return new WP_Error(
                'rest_forbidden',
                'You do not have permission to access this endpoint.',
                array('status' => 403)
            );
        }
        return true;
    }
    
    /**
     * Get parse endpoint arguments
     * 
     * @return array Argument definitions
     */
    private function get_parse_args() {
        return array(
            'url' => array(
                'required' => true,
                'type' => 'string',
                'description' => 'Feed URL to parse',
                'sanitize_callback' => 'esc_url_raw',
            ),
            'type' => array(
                'required' => false,
                'type' => 'string',
                'default' => 'auto',
                'enum' => array('auto', 'rss', 'mrss', 'atom', 'json', 'roku', 'youtube', 'soundcloud'),
                'description' => 'Feed type (auto-detect if not specified)',
            ),
            'max_items' => array(
                'required' => false,
                'type' => 'integer',
                'default' => 50,
                'minimum' => 1,
                'maximum' => 100,
                'description' => 'Maximum number of items to return',
            ),
            'api_key' => array(
                'required' => false,
                'type' => 'string',
                'description' => 'API key for YouTube/SoundCloud feeds',
            ),
            'force_refresh' => array(
                'required' => false,
                'type' => 'boolean',
                'default' => false,
                'description' => 'Bypass cache and fetch fresh data',
            ),
            'field_mappings' => array(
                'required' => false,
                'type' => 'object',
                'description' => 'Custom field mappings for JSON feeds',
            ),
        );
    }
    
    /**
     * Parse a feed URL
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response
     */
    public function parse_feed($request) {
        $url = $request->get_param('url');
        $type = $request->get_param('type');
        
        $options = array(
            'max_items' => $request->get_param('max_items'),
            'api_key' => $request->get_param('api_key'),
            'force_refresh' => $request->get_param('force_refresh'),
            'field_mappings' => $request->get_param('field_mappings'),
        );
        
        $result = $this->parser->parse($url, $type, $options);
        
        if (is_wp_error($result)) {
            return $result;
        }
        
        return rest_ensure_response(array(
            'success' => true,
            'feed' => $result,
            'meta' => array(
                'url' => $url,
                'type' => $result['type'],
                'item_count' => count($result['items']),
                'cached' => !$request->get_param('force_refresh'),
            ),
        ));
    }
    
    /**
     * Get feed (public endpoint for Roku)
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response
     */
    public function get_feed($request) {
        $url = $request->get_param('url');
        $type = $request->get_param('type');
        $max_items = $request->get_param('max_items');
        
        // For public endpoint, use stored API keys from settings
        $options = array(
            'max_items' => $max_items,
            'api_key' => get_option('castconductor_youtube_api_key', ''),
        );
        
        $result = $this->parser->parse($url, $type, $options);
        
        if (is_wp_error($result)) {
            return new WP_REST_Response(array(
                'success' => false,
                'error' => $result->get_error_message(),
            ), 400);
        }
        
        return rest_ensure_response($result);
    }
    
    /**
     * Preview feed for Canvas Editor
     * Returns formatted preview with limited items
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response
     */
    public function preview_feed($request) {
        $url = $request->get_param('url');
        $type = $request->get_param('type');
        
        $options = array(
            'max_items' => min($request->get_param('max_items') ?? 5, 10), // Limit preview to 10 items
            'api_key' => $request->get_param('api_key'),
            'force_refresh' => true, // Always fresh for preview
        );
        
        $result = $this->parser->parse($url, $type, $options);
        
        if (is_wp_error($result)) {
            return $result;
        }
        
        // Format for preview display
        $preview_items = array_map(function($item) {
            return array(
                'id' => $item['id'],
                'title' => $this->truncate($item['title'], 80),
                'description' => $this->truncate($item['description'], 150),
                'thumbnail' => $item['thumbnail'],
                'media_type' => $item['media_type'],
                'duration_formatted' => $this->format_duration($item['duration']),
                'published_relative' => $this->relative_time($item['published_date']),
            );
        }, $result['items']);
        
        return rest_ensure_response(array(
            'success' => true,
            'preview' => array(
                'title' => $result['title'],
                'type' => $result['type'],
                'image' => $result['image'],
                'item_count' => count($result['items']),
                'items' => $preview_items,
            ),
        ));
    }
    
    /**
     * Clear feed cache
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response Response
     */
    public function clear_cache($request) {
        $url = $request->get_param('url');
        
        if (!empty($url)) {
            $this->parser->clear_cache($url);
            $message = 'Cache cleared for: ' . $url;
        } else {
            $this->parser->clear_all_caches();
            $message = 'All feed caches cleared';
        }
        
        return rest_ensure_response(array(
            'success' => true,
            'message' => $message,
        ));
    }
    
    /**
     * Get supported feed types
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response Response
     */
    public function get_feed_types($request) {
        return rest_ensure_response(array(
            'types' => array(
                array(
                    'id' => 'rss',
                    'name' => 'RSS Feed',
                    'description' => 'Standard RSS 2.0 podcast/blog feed',
                    'example' => 'https://example.com/feed.rss',
                ),
                array(
                    'id' => 'mrss',
                    'name' => 'Media RSS (MRSS)',
                    'description' => 'RSS with media extensions for video/audio',
                    'example' => 'https://example.com/media-feed.xml',
                ),
                array(
                    'id' => 'atom',
                    'name' => 'Atom Feed',
                    'description' => 'Atom syndication format',
                    'example' => 'https://example.com/feed.atom',
                ),
                array(
                    'id' => 'json',
                    'name' => 'JSON Feed',
                    'description' => 'JSON Feed or custom JSON API',
                    'example' => 'https://example.com/feed.json',
                ),
                array(
                    'id' => 'roku',
                    'name' => 'Roku Direct Publisher',
                    'description' => 'Roku-native JSON feed format',
                    'example' => 'https://example.com/roku-feed.json',
                ),
                array(
                    'id' => 'youtube',
                    'name' => 'YouTube',
                    'description' => 'YouTube playlist or channel (requires API key)',
                    'example' => 'https://youtube.com/playlist?list=XXXXX',
                    'requires_api_key' => true,
                ),
                array(
                    'id' => 'soundcloud',
                    'name' => 'SoundCloud',
                    'description' => 'SoundCloud playlists and tracks (requires API)',
                    'example' => 'https://soundcloud.com/artist/sets/playlist',
                    'requires_api_key' => true,
                ),
            ),
        ));
    }
    
    /**
     * Truncate text to specified length
     * 
     * @param string $text Text to truncate
     * @param int $length Maximum length
     * @return string Truncated text
     */
    private function truncate($text, $length) {
        if (strlen($text) <= $length) {
            return $text;
        }
        return substr($text, 0, $length - 3) . '...';
    }
    
    /**
     * Format duration in seconds to human readable
     * 
     * @param int $seconds Duration in seconds
     * @return string Formatted duration (e.g., "1:23:45" or "45:30")
     */
    private function format_duration($seconds) {
        if ($seconds <= 0) {
            return '';
        }
        
        $hours = floor($seconds / 3600);
        $minutes = floor(($seconds % 3600) / 60);
        $secs = $seconds % 60;
        
        if ($hours > 0) {
            return sprintf('%d:%02d:%02d', $hours, $minutes, $secs);
        }
        return sprintf('%d:%02d', $minutes, $secs);
    }
    
    /**
     * Format date to relative time
     * 
     * @param string $date ISO date string
     * @return string Relative time (e.g., "2 days ago")
     */
    private function relative_time($date) {
        if (empty($date)) {
            return '';
        }
        
        $timestamp = strtotime($date);
        if ($timestamp === false) {
            return '';
        }
        
        return human_time_diff($timestamp, current_time('timestamp')) . ' ago';
    }
}
