/**
 * Descomplicar® Crescimento Digital
 * https://descomplicar.pt
 */

<?php

defined('BASEPATH') or exit('No direct script access allowed');

/**
 * Desk-Moloni Queue Controller
 * Handles queue management and bulk operations
 * 
 * @package    Desk-Moloni
 * @version    3.0.0
 * @author     Descomplicar Business Solutions
 */
class Queue extends AdminController
{
    public function __construct()
    {
        parent::__construct();
        
        // Check if user is authenticated
        if (!is_staff_logged_in()) {
            redirect(admin_url('authentication'));
        }
        
        // Load models with correct names
        $this->load->model('desk_moloni/desk_moloni_config_model', 'config_model');
        $this->load->model('desk_moloni/desk_moloni_sync_queue_model', 'queue_model');
        $this->load->model('desk_moloni/desk_moloni_mapping_model', 'mapping_model');
        $this->load->model('desk_moloni/desk_moloni_sync_log_model', 'sync_log_model');
        $this->load->helper('desk_moloni');
        $this->load->library('form_validation');
    }

    /**
     * Queue management interface
     */
    public function index()
    {
        if (!has_permission('desk_moloni', '', 'view')) {
            access_denied('desk_moloni');
        }

        $data = [
            'title' => _l('desk_moloni_queue_management'),
            'queue_summary' => $this->_get_queue_summary(),
            'task_types' => $this->_get_task_types(),
            'entity_types' => ['client', 'product', 'invoice', 'estimate', 'credit_note']
        ];

        $this->load->view('admin/includes/header', $data);
        $this->load->view('admin/queue_management', $data);
        $this->load->view('admin/includes/footer');
    }

    /**
     * Get queue status with pagination and filtering
     */
    public function get_queue_status()
    {
        if (!has_permission('desk_moloni', '', 'view')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $filters = [
                'status' => $this->input->get('status'),
                'entity_type' => $this->input->get('entity_type'),
                'task_type' => $this->input->get('task_type'),
                'priority' => $this->input->get('priority'),
                'date_from' => $this->input->get('date_from'),
                'date_to' => $this->input->get('date_to')
            ];

            $pagination = [
                'limit' => (int) $this->input->get('limit') ?: 50,
                'offset' => (int) $this->input->get('offset') ?: 0
            ];

            $queue_data = $this->queue_model->get_filtered_queue($filters, $pagination);

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'data' => [
                        'total_tasks' => $queue_data['total'],
                        'tasks' => $queue_data['tasks'],
                        'summary' => $this->queue_model->get_filtered_summary($filters),
                        'pagination' => [
                            'current_page' => floor($pagination['offset'] / $pagination['limit']) + 1,
                            'per_page' => $pagination['limit'],
                            'total_items' => $queue_data['total'],
                            'total_pages' => ceil($queue_data['total'] / $pagination['limit'])
                        ]
                    ]
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni queue status error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(500)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Add new sync task to queue
     */
    public function add_task()
    {
        if (!has_permission('desk_moloni', '', 'create')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $task_data = [
                'task_type' => $this->input->post('task_type'),
                'entity_type' => $this->input->post('entity_type'),
                'entity_id' => (int) $this->input->post('entity_id'),
                'priority' => (int) $this->input->post('priority') ?: 5,
                'payload' => $this->input->post('payload') ? json_decode($this->input->post('payload'), true) : null
            ];

            // Validate required fields
            if (empty($task_data['task_type']) || empty($task_data['entity_type']) || empty($task_data['entity_id'])) {
                throw new Exception(_l('desk_moloni_task_missing_required_fields'));
            }

            // Validate entity exists
            if (!$this->_validate_entity_exists($task_data['entity_type'], $task_data['entity_id'])) {
                throw new Exception(_l('desk_moloni_entity_not_found'));
            }

            $task_id = $this->queue_model->add_task($task_data);

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'message' => _l('desk_moloni_task_added_successfully'),
                    'data' => ['task_id' => $task_id]
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni add task error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(400)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Cancel sync task
     */
    public function cancel_task($task_id)
    {
        if (!has_permission('desk_moloni', '', 'edit')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $task_id = (int) $task_id;
            
            if (!$task_id) {
                throw new Exception(_l('desk_moloni_invalid_task_id'));
            }

            $result = $this->queue_model->cancel_task($task_id);

            if (!$result) {
                throw new Exception(_l('desk_moloni_task_cancel_failed'));
            }

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'message' => _l('desk_moloni_task_cancelled_successfully')
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni cancel task error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(400)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Retry sync task
     */
    public function retry_task($task_id)
    {
        if (!has_permission('desk_moloni', '', 'edit')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $task_id = (int) $task_id;
            
            if (!$task_id) {
                throw new Exception(_l('desk_moloni_invalid_task_id'));
            }

            $result = $this->queue_model->retry_task($task_id);

            if (!$result) {
                throw new Exception(_l('desk_moloni_task_retry_failed'));
            }

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'message' => _l('desk_moloni_task_retried_successfully')
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni retry task error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(400)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Bulk operations on tasks
     */
    public function bulk_operation()
    {
        if (!has_permission('desk_moloni', '', 'edit')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $operation = $this->input->post('operation');
            $task_ids = $this->input->post('task_ids');
            
            if (empty($operation) || empty($task_ids) || !is_array($task_ids)) {
                throw new Exception(_l('desk_moloni_bulk_operation_invalid_params'));
            }

            $results = [];
            $success_count = 0;
            $error_count = 0;

            foreach ($task_ids as $task_id) {
                try {
                    $task_id = (int) $task_id;
                    $result = false;

                    switch ($operation) {
                        case 'retry':
                            $result = $this->queue_model->retry_task($task_id);
                            break;
                        case 'cancel':
                            $result = $this->queue_model->cancel_task($task_id);
                            break;
                        case 'delete':
                            $result = $this->queue_model->delete_task($task_id);
                            break;
                        case 'priority_high':
                            $result = $this->queue_model->set_task_priority($task_id, 1);
                            break;
                        case 'priority_normal':
                            $result = $this->queue_model->set_task_priority($task_id, 5);
                            break;
                        case 'priority_low':
                            $result = $this->queue_model->set_task_priority($task_id, 9);
                            break;
                        default:
                            throw new Exception(_l('desk_moloni_invalid_bulk_operation'));
                    }

                    if ($result) {
                        $success_count++;
                        $results[$task_id] = ['success' => true];
                    } else {
                        $error_count++;
                        $results[$task_id] = ['success' => false, 'error' => 'Operation failed'];
                    }

                } catch (Exception $e) {
                    $error_count++;
                    $results[$task_id] = ['success' => false, 'error' => $e->getMessage()];
                }
            }

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => $success_count > 0,
                    'message' => sprintf(
                        _l('desk_moloni_bulk_operation_results'),
                        $success_count,
                        $error_count
                    ),
                    'data' => [
                        'success_count' => $success_count,
                        'error_count' => $error_count,
                        'results' => $results
                    ]
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni bulk operation error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(400)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Clear completed tasks from queue
     */
    public function clear_completed()
    {
        if (!has_permission('desk_moloni', '', 'delete')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $days_old = (int) $this->input->post('days_old') ?: 7;
            $deleted_count = $this->queue_model->clear_completed_tasks($days_old);

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'message' => sprintf(
                        _l('desk_moloni_completed_tasks_cleared'),
                        $deleted_count
                    ),
                    'data' => ['deleted_count' => $deleted_count]
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni clear completed error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(500)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Pause/Resume queue processing
     */
    public function toggle_processing()
    {
        if (!has_permission('desk_moloni', '', 'edit')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $current_status = $this->config_model->get_config('queue_processing_enabled') === '1';
            $new_status = !$current_status;
            
            $this->config_model->set_config('queue_processing_enabled', $new_status ? '1' : '0');

            $message = $new_status 
                ? _l('desk_moloni_queue_processing_resumed')
                : _l('desk_moloni_queue_processing_paused');

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'message' => $message,
                    'data' => ['queue_processing_enabled' => $new_status]
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni toggle processing error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(500)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Get queue statistics
     */
    public function get_statistics()
    {
        if (!has_permission('desk_moloni', '', 'view')) {
            $this->output
                ->set_status_header(403)
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => _l('access_denied')]));
            return;
        }

        try {
            $days = (int) $this->input->get('days') ?: 7;
            
            $statistics = [
                'queue_summary' => $this->queue_model->get_queue_summary(),
                'processing_stats' => method_exists($this->queue_model, 'get_processing_statistics') ? $this->queue_model->get_processing_statistics($days) : [],
                'performance_metrics' => method_exists($this->queue_model, 'get_performance_metrics') ? $this->queue_model->get_performance_metrics($days) : [],
                'error_analysis' => method_exists($this->queue_model, 'get_error_analysis') ? $this->queue_model->get_error_analysis($days) : []
            ];

            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => true,
                    'data' => $statistics
                ]));

        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni queue statistics error: ' . $e->getMessage());
            
            $this->output
                ->set_status_header(500)
                ->set_content_type('application/json')
                ->set_output(json_encode([
                    'success' => false,
                    'message' => $e->getMessage()
                ]));
        }
    }

    /**
     * Validate that entity exists in Perfex
     */
    private function _validate_entity_exists($entity_type, $entity_id)
    {
        $this->load->model('clients_model');
        $this->load->model('invoices_model');
        $this->load->model('estimates_model');
        $this->load->model('credit_notes_model');
        $this->load->model('items_model');

        switch ($entity_type) {
            case 'client':
                return $this->clients_model->get($entity_id) !== false;
            case 'invoice':
                return $this->invoices_model->get($entity_id) !== false;
            case 'estimate':
                return $this->estimates_model->get($entity_id) !== false;
            case 'credit_note':
                return $this->credit_notes_model->get($entity_id) !== false;
            case 'product':
                return $this->items_model->get($entity_id) !== false;
            default:
                return false;
        }
    }

    /**
     * Get queue summary statistics
     */
    private function _get_queue_summary()
    {
        try {
            return [
                'total_tasks' => $this->queue_model->countTasks(),
                'pending_tasks' => $this->queue_model->countTasks(['status' => 'pending']),
                'processing_tasks' => $this->queue_model->countTasks(['status' => 'processing']),
                'failed_tasks' => $this->queue_model->countTasks(['status' => 'failed']),
                'completed_tasks' => $this->queue_model->countTasks(['status' => 'completed'])
            ];
        } catch (Exception $e) {
            log_message('error', 'Desk-Moloni queue summary error: ' . $e->getMessage());
            return [];
        }
    }

    /**
     * Get available task types
     */
    private function _get_task_types()
    {
        return [
            'sync_client' => 'Client Sync',
            'sync_product' => 'Product Sync',
            'sync_invoice' => 'Invoice Sync',
            'sync_estimate' => 'Estimate Sync',
            'sync_credit_note' => 'Credit Note Sync'
        ];
    }
}