<?php

/**
 * JCOGS Image Pro - Error Details AJAX Action Handler
 * ====================================================
 * Handles AJAX requests for error notification details
 * 
 * @category   ExpressionEngine Add-on
 * @package    JCOGS Image Pro
 * @author     JCOGS Design <contact@jcogs.net>
 * @copyright  Copyright (c) 2021 - 2025 JCOGS Design
 * @license    https://jcogs.net/add-ons/license/jcogs_img_pro
 * @version    2.0.6
 * @link       https://JCOGS.net/
 * @since      Enhanced Error Notifications Feature
 */

namespace JCOGSDesign\JCOGSImagePro\Actions;

use Exception;
use JCOGSDesign\JCOGSImagePro\Service\ErrorNotificationService;

/**
 * Error Details AJAX Action Handler
 * 
 * Provides AJAX endpoints for loading error notification details.
 * Used by the enhanced error notification system to load expandable
 * error details on demand.
 * 
 * Methods:
 * - error_details: Returns first 5 error details as HTML
 * - error_details_all: Returns all error details as HTML
 */
class ErrorDetailsAjax extends ImageAbstractAction
{
    /**
     * Main action entry point (required by ImageAbstractAction)
     * Routes to specific methods based on 'method' parameter.
     * 
     * @return string Empty string (HTML sent via headers)
     */
    public function process(): string
    {
        // Get the method parameter from the request
        $method = ee()->input->get('method') ?: ee()->input->post('method');
        
        // Route to the appropriate method
        switch ($method) {
            case 'error_details':
                $this->error_details();
                break;
                
            case 'error_details_all':
                $this->error_details_all();
                break;
                
            default:
                $this->send_error_response('Invalid method specified');
                break;
        }
        
        return '';
    }
    
    /**
     * Get initial error details (first 5 notifications)
     * 
     * @return void
     */
    public function error_details(): void
    {
        try {
            $error_service = new ErrorNotificationService();
            $unread_notifications = $error_service->getUnreadNotifications(5);
            
            $html = $this->buildErrorDetailsHtml($unread_notifications, $error_service);
            
            // Mark notifications as read after displaying details
            $notification_ids = array_column($unread_notifications, 'id');
            if (!empty($notification_ids)) {
                $error_service->markAsRead($notification_ids);
            }
            
            $this->send_html_response($html);
            
        } catch (Exception $e) {
            $this->utilities_service->debug_message(
                'Failed to load error details: ' . $e->getMessage(),
                'ErrorDetailsAjax::error_details'
            );
            $this->send_error_response('Failed to load error details: ' . $e->getMessage());
        }
    }
    
    /**
     * Get all error details
     * 
     * @return void
     */
    public function error_details_all(): void
    {
        try {
            $error_service = new ErrorNotificationService();
            // Use getRecentNotifications to get both read and unread recent notifications
            $all_notifications = $error_service->getRecentNotifications(50); // Get up to 50
            
            $html = $this->buildAllErrorDetailsHtml($all_notifications, $error_service);
            
            // Mark all unread notifications as read so the CP prompt reliably clears,
            // even when historical unread records exceed the display limit.
            $error_service->markAllUnreadAsRead();
            
            $this->send_html_response($html);
            
        } catch (Exception $e) {
            $this->utilities_service->debug_message(
                'Failed to load all error details: ' . $e->getMessage(),
                'ErrorDetailsAjax::error_details_all'
            );
            $this->send_error_response('Failed to load all error details: ' . $e->getMessage());
        }
    }
    
    /**
     * Build error details HTML (first 5 notifications)
     * 
     * @param array $notifications Error notifications
     * @param ErrorNotificationService $error_service Error service instance
     * @return string HTML content
     */
    private function buildErrorDetailsHtml(array $notifications, ErrorNotificationService $error_service): string
    {
        if (empty($notifications)) {
            return '<p>' . (lang('jcogs_img_pro_no_errors') ?: 'No recent errors found.') . '</p>';
        }
        
        $html = '<div class="jcogs-error-details">';
        
        foreach ($notifications as $notification) {
            $html .= '<div class="jcogs-error-row">';
            
            // Date
            $formatted_date = $this->formatErrorDate($notification['created_at'] ?? '');
            $html .= '<div class="jcogs-error-date">' . htmlspecialchars($formatted_date, ENT_QUOTES, 'UTF-8') . '</div>';
            
            // Error message
            $html .= '<div class="jcogs-error-message">' . htmlspecialchars($notification['error_message'] ?? 'Unknown error', ENT_QUOTES, 'UTF-8') . '</div>';
            
            // Template
            if (!empty($notification['template_name'])) {
                $html .= '<div class="jcogs-error-template">Template: ' . htmlspecialchars($notification['template_name'], ENT_QUOTES, 'UTF-8') . '</div>';
            }
            
            // Tag parameters
            if (!empty($notification['tag_parameters'])) {
                $params = $this->formatTagParametersCompact($notification['tag_parameters']);
                if (!empty($params)) {
                    $html .= '<div class="jcogs-error-params">Parameters: ' . $params . '</div>';
                }
            }
            
            $html .= '</div>';
        }
        
        // Check if there are more notifications
        $total_count = $error_service->getUnreadNotificationCount();
        if ($total_count > 5) {
            $remaining = $total_count - 5;
            $html .= '<div class="jcogs-show-all-btn">';
            $html .= '<button class="btn btn-sm btn-primary jcogs-show-all-errors" data-remaining="' . $remaining . '">';
            $html .= sprintf('Show all %d errors', $total_count);
            $html .= '</button>';
            $html .= '</div>';
            
            // Add JavaScript for "Show All" functionality
            $html .= $this->getShowAllScript();
        }
        
        $html .= '</div>';
        
        return $html;
    }
    
    /**
     * Build all error details HTML
     * 
     * @param array $notifications All error notifications
     * @param ErrorNotificationService $error_service Error service instance
     * @return string HTML content
     */
    private function buildAllErrorDetailsHtml(array $notifications, ErrorNotificationService $error_service): string
    {
        if (empty($notifications)) {
            return '<p>' . (lang('jcogs_img_pro_no_errors') ?: 'No recent errors found.') . '</p>';
        }
        
        $html = '<div class="jcogs-error-details-all">';
        
        // Header with count
        $count = count($notifications);
        $title_template = lang('jcogs_img_pro_all_errors_title');
        if (empty($title_template) || $title_template === 'jcogs_img_pro_all_errors_title') {
            $title_template = 'All Recent Errors (%d)';
        }
        $html .= '<h4>' . sprintf($title_template, $count) . '</h4>';
        
        foreach ($notifications as $notification) {
            $html .= '<div class="jcogs-error-row">';
            
            // Date
            $formatted_date = $this->formatErrorDate($notification['created_at'] ?? '');
            $html .= '<div class="jcogs-error-date">' . htmlspecialchars($formatted_date, ENT_QUOTES, 'UTF-8') . '</div>';
            
            // Error message
            $html .= '<div class="jcogs-error-message">' . htmlspecialchars($notification['error_message'] ?? 'Unknown error', ENT_QUOTES, 'UTF-8') . '</div>';
            
            // Template
            if (!empty($notification['template_name'])) {
                $html .= '<div class="jcogs-error-template">Template: ' . htmlspecialchars($notification['template_name'], ENT_QUOTES, 'UTF-8') . '</div>';
            }
            
            // Tag parameters (with full details for "show all" view)
            if (!empty($notification['tag_parameters'])) {
                $params = $this->formatTagParametersComplete($notification['tag_parameters']);
                if (!empty($params)) {
                    $html .= '<div class="jcogs-error-params">Parameters: ' . $params . '</div>';
                }
            }
            
            $html .= '</div>';
        }
        
        $html .= '</div>';
        
        return $html;
    }
    
    /**
     * Format error date for display
     * 
     * @param string $timestamp Database timestamp
     * @return string Formatted date
     */
    private function formatErrorDate(string $timestamp): string
    {
        if (empty($timestamp)) {
            return 'Unknown date';
        }
        
        // Handle both Unix timestamp and MySQL datetime format
        if (is_numeric($timestamp)) {
            $date = $timestamp;
        } else {
            $date = strtotime($timestamp);
        }
        
        if ($date === false) {
            return 'Invalid date';
        }
        
        return date('j M \a\t H:i', $date);
    }
    
    /**
     * Format tag parameters in compact format
     * 
     * @param string|array $parameters Tag parameters
     * @return string Formatted parameters
     */
    private function formatTagParametersCompact($parameters): string
    {
        if (empty($parameters)) {
            return '';
        }
        
        // Decode JSON if it's a string
        if (is_string($parameters)) {
            $params_array = json_decode($parameters, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                return htmlspecialchars($parameters, ENT_QUOTES, 'UTF-8'); // Return as-is if JSON decode fails
            }
            $parameters = $params_array;
        }
        
        if (!is_array($parameters)) {
            return htmlspecialchars((string)$parameters, ENT_QUOTES, 'UTF-8');
        }
        
        $param_strings = [];
        foreach ($parameters as $key => $value) {
            // Skip internal parameters that start with underscore
            if (strpos($key, '_') === 0) {
                continue;
            }
            
            // Skip common auto-added parameters that aren't user-supplied
            if (in_array($key, ['crop_position', 'crop_offset', 'face_sensitivity', 'face_crop_margin', 'face_detect_sensitivity', 'face_detect_crop_focus', 'save_as'])) {
                continue;
            }
            
            if (is_array($value)) {
                $value = '[array]';
            } elseif (strlen($value) > 30) {
                $value = substr($value, 0, 27) . '...';
            }
            $param_strings[] = htmlspecialchars($key, ENT_QUOTES, 'UTF-8') . '="' . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . '"';
        }
        
        return implode(' ', $param_strings);
    }
    
    /**
     * Format tag parameters with complete details
     * 
     * @param string|array $parameters Tag parameters
     * @return string Formatted parameters
     */
    private function formatTagParametersComplete($parameters): string
    {
        if (empty($parameters)) {
            return '';
        }
        
        // Decode JSON if it's a string
        if (is_string($parameters)) {
            $params_array = json_decode($parameters, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                return htmlspecialchars($parameters, ENT_QUOTES, 'UTF-8'); // Return as-is if JSON decode fails
            }
            $parameters = $params_array;
        }
        
        if (!is_array($parameters)) {
            return htmlspecialchars((string)$parameters, ENT_QUOTES, 'UTF-8');
        }
        
        $param_strings = [];
        foreach ($parameters as $key => $value) {
            // Skip internal parameters that start with underscore
            if (strpos($key, '_') === 0) {
                continue;
            }
            
            // Skip common auto-added parameters that aren't user-supplied
            if (in_array($key, ['crop_position', 'crop_offset', 'face_sensitivity', 'face_crop_margin', 'face_detect_sensitivity', 'face_detect_crop_focus', 'save_as'])) {
                continue;
            }
            
            if (is_array($value)) {
                $value = json_encode($value);
            }
            // No truncation for complete view
            $param_strings[] = htmlspecialchars($key, ENT_QUOTES, 'UTF-8') . '="' . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . '"';
        }
        
        return implode(' ', $param_strings);
    }
    

    
    /**
     * Get JavaScript for "Show All" functionality
     * 
     * @return string JavaScript code
     */
    private function getShowAllScript(): string
    {
        // Build action URL manually since we're in an action already
        $show_all_action_url = ee()->config->item('site_url') . '?ACT=' . ee()->input->get('ACT') . '&method=error_details_all';
        
        return '
        <script>
        $(document).ready(function() {
            $(".jcogs-show-all-errors").click(function() {
                let button = $(this);
                button.prop("disabled", true).text("Loading...");
                
                // Hide the view details button since it will no longer be functional
                $(".jcogs-expand-errors").hide();
                
                $.ajax({
                    url: "' . $show_all_action_url . '",
                    method: "GET",
                    success: function(data) {
                        $(".jcogs-error-details").html(data);
                    },
                    error: function() {
                        button.prop("disabled", false).text("Show All (Error)");
                        // Show the view details button again on error
                        $(".jcogs-expand-errors").show();
                        alert("Failed to load all errors. Please try again.");
                    }
                });
            });
        });
        </script>
        ';
    }
    
    /**
     * Send HTML response
     * 
     * @param string $html HTML content
     * @return void
     */
    private function send_html_response(string $html): void
    {
        // Set headers for AJAX response
        header('Content-Type: text/html; charset=utf-8');
        header('Cache-Control: no-cache, must-revalidate');
        
        ee()->output->set_output($html);
        // Ensure output is sent immediately
        ee()->output->_display();
        exit();
    }
    
    /**
     * Send error response
     * 
     * @param string $message Error message
     * @return void
     */
    private function send_error_response(string $message): void
    {
        // Set headers for AJAX error response
        header('Content-Type: text/html; charset=utf-8');
        header('Cache-Control: no-cache, must-revalidate');
        
        $error_html = '<div class="alert alert-danger">';
        $error_html .= '<p><strong>Error:</strong> ' . htmlspecialchars($message, ENT_QUOTES, 'UTF-8') . '</p>';
        $error_html .= '</div>';
        
        ee()->output->set_output($error_html);
        // Ensure output is sent immediately
        ee()->output->_display();
        exit();
    }
}