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

<?php
/**
 * Desk-Moloni v3.0 - Perfex CRM Module
 * 
 * Bidirectional synchronization between Perfex CRM and Moloni ERP
 * 
 * @package     DeskMoloni
 * @author      Descomplicar.pt
 * @version     3.0.1
 * @link        https://descomplicar.pt
 */

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

/*
Module Name: Desk-Moloni Integration v3.0
Description: Complete bidirectional synchronization between Perfex CRM and Moloni ERP with OAuth 2.0, queue processing, and client portal
Version: 3.0.1
Requires at least: 3.0.*
Author: Descomplicar.pt
Author URI: https://descomplicar.pt
*/

// Define constants only if they don't already exist
if (!defined('DESK_MOLONI_MODULE_NAME')) {
    define('DESK_MOLONI_MODULE_NAME', 'desk_moloni');
}

if (!defined('DESK_MOLONI_VERSION')) {
    define('DESK_MOLONI_VERSION', '3.0.1');
}

if (!defined('DESK_MOLONI_MODULE_PATH')) {
    define('DESK_MOLONI_MODULE_PATH', dirname(__FILE__));
}

// Load Composer autoloader
if (file_exists(DESK_MOLONI_MODULE_PATH . '/vendor/autoload.php')) {
    require_once DESK_MOLONI_MODULE_PATH . '/vendor/autoload.php';
}

/**
 * Register hooks for module functionality - only if hooks() function exists
 */
if (function_exists('hooks')) {
    hooks()->add_action('after_client_added', 'desk_moloni_sync_customer_added');
    hooks()->add_action('after_client_updated', 'desk_moloni_sync_customer_updated');
    hooks()->add_action('after_invoice_added', 'desk_moloni_sync_invoice_added');
    hooks()->add_action('after_invoice_updated', 'desk_moloni_sync_invoice_updated');
    hooks()->add_action('after_estimate_added', 'desk_moloni_sync_estimate_added');
    hooks()->add_action('after_estimate_updated', 'desk_moloni_sync_estimate_updated');
    hooks()->add_action('after_item_added', 'desk_moloni_sync_item_added');
    hooks()->add_action('after_item_updated', 'desk_moloni_sync_item_updated');

    /**
     * Register admin menu hooks
     */
    hooks()->add_action('admin_init', 'desk_moloni_admin_init_hook');
    hooks()->add_action('admin_init', 'desk_moloni_init_admin_menu');

    /**
     * Register client portal hooks
     */
    hooks()->add_action('client_init', 'desk_moloni_client_init_hook');
}

// Optionally initialize the advanced PerfexHooks class if available
if (class_exists('PerfexHooks') && function_exists('hooks')) {
    // Instantiate once to register internal handlers (safe to try)
    try { new PerfexHooks(); } catch (Throwable $e) { /* ignore */ }
}

/**
 * Module lifecycle hooks - only register if functions exist
 */
if (function_exists('register_activation_hook')) {
    register_activation_hook(DESK_MOLONI_MODULE_NAME, 'desk_moloni_activation_hook');
}

if (function_exists('register_deactivation_hook')) {
    register_deactivation_hook(DESK_MOLONI_MODULE_NAME, 'desk_moloni_deactivation_hook');
}

if (function_exists('register_uninstall_hook')) {
    register_uninstall_hook(DESK_MOLONI_MODULE_NAME, 'desk_moloni_uninstall_hook');
}

/**
 * Hook functions
 */

function desk_moloni_admin_init_hook()
{
    $CI = &get_instance();
    
    // Load module configuration safely
    try {
        $config_file = DESK_MOLONI_MODULE_PATH . '/config/config.php';
        if (file_exists($config_file)) {
            include_once $config_file;
        }
    } catch (Exception $e) {
        log_message('error', 'Desk-Moloni: Failed to load config: ' . $e->getMessage());
    }
    
    // Ensure version option is up to date
    if (function_exists('update_option')) {
        update_option('desk_moloni_module_version', DESK_MOLONI_VERSION);
    }

    // Add CSS and JS for admin if files exist
    $css_file = DESK_MOLONI_MODULE_PATH . '/assets/css/admin.css';
    $js_file = DESK_MOLONI_MODULE_PATH . '/assets/js/admin.js';
    
    if (file_exists($css_file)) {
        $CI->app_css->add('desk-moloni-admin-css', base_url('modules/desk_moloni/assets/css/admin.css'));
    }
    if (file_exists($js_file)) {
        $CI->app_scripts->add('desk-moloni-admin-js', base_url('modules/desk_moloni/assets/js/admin.js'));
    }
}

function desk_moloni_init_admin_menu()
{
    $CI = &get_instance();
    
    if (has_permission('desk_moloni', '', 'view')) {
        $CI->app_menu->add_sidebar_menu_item('desk-moloni', [
            'name'     => 'Desk-Moloni',
            'href'     => admin_url('desk_moloni/admin'),
            'icon'     => 'fa fa-refresh',
            'position' => 35,
        ]);
        
        $CI->app_menu->add_sidebar_children_item('desk-moloni', [
            'slug'     => 'desk-moloni-dashboard',
            'name'     => _l('Dashboard'),
            'href'     => admin_url('desk_moloni/dashboard'),
            'position' => 1,
        ]);
        
        $CI->app_menu->add_sidebar_children_item('desk-moloni', [
            'slug'     => 'desk-moloni-config',
            'name'     => _l('Configuration'),
            'href'     => admin_url('desk_moloni/admin/config'),
            'position' => 2,
        ]);
        
        $CI->app_menu->add_sidebar_children_item('desk-moloni', [
            'slug'     => 'desk-moloni-sync',
            'name'     => _l('Synchronization'),
            'href'     => admin_url('desk_moloni/admin/manual_sync'),
            'position' => 3,
        ]);
        
        $CI->app_menu->add_sidebar_children_item('desk-moloni', [
            'slug'     => 'desk-moloni-queue',
            'name'     => _l('Queue Status'),
            'href'     => admin_url('desk_moloni/queue'),
            'position' => 4,
        ]);
        
        $CI->app_menu->add_sidebar_children_item('desk-moloni', [
            'slug'     => 'desk-moloni-mapping',
            'name'     => _l('Mappings'),
            'href'     => admin_url('desk_moloni/mapping'),
            'position' => 5,
        ]);
        
        $CI->app_menu->add_sidebar_children_item('desk-moloni', [
            'slug'     => 'desk-moloni-logs',
            'name'     => _l('Sync Logs'),
            'href'     => admin_url('desk_moloni/logs'),
            'position' => 6,
        ]);
    }
}

function desk_moloni_client_init_hook()
{
    $CI = &get_instance();
    
    // Add client portal CSS and JS only if files exist
    $css_path = DESK_MOLONI_MODULE_PATH . '/assets/css/client.css';
    if (file_exists($css_path)) {
        $CI->app_css->add('desk-moloni-client-css', base_url('modules/desk_moloni/assets/css/client.css'));
    }
    
    // Skip non-existent JS file to avoid 404 errors
    // Client portal JavaScript will be loaded when the frontend is properly built
    
    // Add client portal tab if helper exists
    if (function_exists('hooks')) {
        hooks()->add_action('clients_navigation_end', 'desk_moloni_add_client_tab');
    }
}

function desk_moloni_add_client_tab()
{
    $CI = &get_instance();
    echo '<li role="presentation">';
    echo '<a href="' . site_url('clients/desk_moloni') . '" aria-controls="desk_moloni" role="tab" data-toggle="tab">';
    echo '<i class="fa fa-file-text-o"></i> ' . _l('My Documents');
    echo '</a>';
    echo '</li>';
}

/**
 * Synchronization hook functions
 */

function desk_moloni_sync_customer_added($customer_id)
{
    desk_moloni_add_sync_task('sync_client', 'client', $customer_id);
}

function desk_moloni_sync_customer_updated($customer_id)
{
    desk_moloni_add_sync_task('sync_client', 'client', $customer_id);
}

function desk_moloni_sync_invoice_added($invoice_id)
{
    desk_moloni_add_sync_task('sync_invoice', 'invoice', $invoice_id);
}

function desk_moloni_sync_invoice_updated($invoice_id)
{
    desk_moloni_add_sync_task('sync_invoice', 'invoice', $invoice_id);
}

function desk_moloni_sync_estimate_added($estimate_id)
{
    desk_moloni_add_sync_task('sync_estimate', 'estimate', $estimate_id);
}

function desk_moloni_sync_estimate_updated($estimate_id)
{
    desk_moloni_add_sync_task('sync_estimate', 'estimate', $estimate_id);
}

function desk_moloni_sync_item_added($item_id)
{
    desk_moloni_add_sync_task('sync_product', 'product', $item_id);
}

function desk_moloni_sync_item_updated($item_id)
{
    desk_moloni_add_sync_task('sync_product', 'product', $item_id);
}

/**
 * Add task to sync queue
 */
function desk_moloni_add_sync_task($task_type, $entity_type, $entity_id, $priority = 5)
{
    $CI = &get_instance();
    
    // Check if sync is enabled
    $sync_enabled = get_option('desk_moloni_sync_enabled');
    if (!$sync_enabled) {
        return false;
    }
    
    // Check if specific entity sync is enabled
    $entity_sync_key = 'desk_moloni_auto_sync_' . $entity_type . 's';
    $entity_sync_enabled = get_option($entity_sync_key);
    if (!$entity_sync_enabled) {
        return false;
    }
    
    // Load sync queue model with correct path and alias
    $CI->load->model('desk_moloni/desk_moloni_sync_queue_model', 'sync_queue_model');
    
    // Add task to queue
    if (method_exists($CI->sync_queue_model, 'addTask')) {
        return $CI->sync_queue_model->addTask($task_type, $entity_type, $entity_id, [], $priority);
    }
    if (method_exists($CI->sync_queue_model, 'add_task')) {
        return $CI->sync_queue_model->add_task([
            'task_type' => $task_type,
            'entity_type' => $entity_type,
            'entity_id' => $entity_id,
            'priority' => $priority,
        ]);
    }
    return false;
}

/**
 * Module lifecycle hooks
 */

function desk_moloni_activation_hook()
{
    $CI = &get_instance();
    
    try {
        // Run database migrations
        $migration_success = desk_moloni_run_migrations();
        
        if (!$migration_success) {
            log_message('warning', 'Desk-Moloni: Migration failed, but continuing activation');
        }
        
        // Create default configuration
        desk_moloni_create_default_config();
        
        // Setup permissions
        desk_moloni_setup_permissions();
        
        // Load and run install.php for complete setup
        $install_file = DESK_MOLONI_MODULE_PATH . '/install.php';
        if (file_exists($install_file)) {
            include_once $install_file;
        }
        
        log_activity('Desk-Moloni module activated successfully');
        
    } catch (Exception $e) {
        log_message('error', 'Desk-Moloni activation error: ' . $e->getMessage());
        log_activity('Desk-Moloni module activation failed: ' . $e->getMessage());
    }
}

function desk_moloni_deactivation_hook()
{
    log_activity('Desk-Moloni module deactivated');
}

function desk_moloni_uninstall_hook()
{
    $CI = &get_instance();
    
    // Remove module data (optional - admin choice)
    $remove_data = get_option('desk_moloni_remove_data_on_uninstall');
    if ($remove_data) {
        desk_moloni_remove_database_tables();
        desk_moloni_remove_module_options();
        desk_moloni_remove_permissions();
    }
    
    log_activity('Desk-Moloni module uninstalled');
}

/**
 * Database migration functions
 */

function desk_moloni_run_migrations()
{
    $CI = &get_instance();
    
    try {
        $CI->load->database();
        
        $migration_path = DESK_MOLONI_MODULE_PATH . '/database/migrations/';
        
        // Check if migrations directory exists
        if (!is_dir($migration_path)) {
            log_message('info', 'Desk-Moloni: No migrations directory found, using install.php for database setup');
            return true;
        }
        
        // Get all migration files
        $migrations = glob($migration_path . '*.sql');
        
        if (empty($migrations)) {
            log_message('info', 'Desk-Moloni: No migration files found, using install.php for database setup');
            return true;
        }
        
        sort($migrations);
        
        // Ensure migrations table exists
        $table_name = db_prefix() . 'desk_moloni_migrations';
        if (!$CI->db->table_exists($table_name)) {
            $CI->db->query("CREATE TABLE IF NOT EXISTS `{$table_name}` (
                id INT AUTO_INCREMENT PRIMARY KEY,
                migration VARCHAR(255) NOT NULL UNIQUE,
                executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        }
        
        foreach ($migrations as $migration_file) {
            $migration_name = basename($migration_file, '.sql');
            
            // Check if this specific migration has been run
            $executed = $CI->db->get_where($table_name, ['migration' => $migration_name])->num_rows();
            
            if ($executed == 0) {
                // Execute migration
                $sql = file_get_contents($migration_file);
                
                if (!empty($sql)) {
                    $queries = explode(';', $sql);
                    
                    foreach ($queries as $query) {
                        $query = trim($query);
                        if (!empty($query) && strlen($query) > 10) {
                            try {
                                $CI->db->query($query);
                            } catch (Exception $e) {
                                log_message('error', 'Desk-Moloni migration error in ' . $migration_name . ': ' . $e->getMessage());
                                // Continue with other queries
                            }
                        }
                    }
                    
                    // Record migration as executed
                    $CI->db->insert($table_name, [
                        'migration' => $migration_name,
                        'executed_at' => date('Y-m-d H:i:s')
                    ]);
                    
                    log_activity("Desk-Moloni migration executed: {$migration_name}");
                }
            }
        }
        
        return true;
        
    } catch (Exception $e) {
        log_message('error', 'Desk-Moloni migration error: ' . $e->getMessage());
        return false;
    }
}

function desk_moloni_create_default_config()
{
    $default_options = [
        'desk_moloni_sync_enabled' => '0',
        'desk_moloni_auto_sync_clients' => '1',
        'desk_moloni_auto_sync_products' => '0',
        'desk_moloni_auto_sync_invoices' => '1',
        'desk_moloni_auto_sync_estimates' => '1',
        'desk_moloni_queue_processing_enabled' => '1',
        'desk_moloni_max_retry_attempts' => '3',
        'desk_moloni_sync_timeout' => '30',
        'desk_moloni_remove_data_on_uninstall' => '0'
    ];
    
    foreach ($default_options as $key => $value) {
        if (get_option($key) === false) {
            add_option($key, $value);
        }
    }
}

function desk_moloni_setup_permissions()
{
    $CI = &get_instance();
    
    // Check if permission already exists
    $permission_exists = $CI->db->get_where('tblpermissions', ['name' => 'desk_moloni'])->num_rows();
    
    if ($permission_exists == 0) {
        // Add module permissions
        $permissions = [
            'view' => 'View Desk-Moloni',
            'create' => 'Create Sync Tasks',
            'edit' => 'Edit Configuration',
            'delete' => 'Delete Sync Tasks'
        ];
        
        foreach ($permissions as $short_name => $description) {
            $CI->db->insert('tblpermissions', [
                'name' => 'desk_moloni',
                'shortname' => $short_name,
                'description' => $description
            ]);
        }
    }
}

function desk_moloni_remove_database_tables()
{
    $CI = &get_instance();
    $CI->load->database();
    
    // Drop both legacy and current table names for safety
    $legacyTables = [
        'desk_moloni_config',
        'desk_moloni_mapping',
        'desk_moloni_sync_queue', 
        'desk_moloni_sync_log',
        'desk_moloni_migrations'
    ];
    $currentTables = [
        'tbldeskmoloni_config',
        'tbldeskmoloni_mapping',
        'tbldeskmoloni_sync_queue',
        'tbldeskmoloni_sync_log',
        'tbldeskmoloni_migrations'
    ];
    
    foreach (array_merge($legacyTables, $currentTables) as $table) {
        $CI->db->query("DROP TABLE IF EXISTS {$table}");
    }
}

function desk_moloni_remove_module_options()
{
    $CI = &get_instance();
    
    // Remove all module options
    $CI->db->like('name', 'desk_moloni_', 'after');
    $CI->db->delete('tbloptions');
}

function desk_moloni_remove_permissions()
{
    $CI = &get_instance();
    
    // Remove module permissions
    $CI->db->where('name', 'desk_moloni');
    $CI->db->delete('tblpermissions');
}
/**
 * Client portal route handler
 */
function desk_moloni_client_portal_route()
{
    $CI = &get_instance();
    
    // Check if client is logged in
    if (!is_client_logged_in()) {
        redirect("clients/login");
        return;
    }
    
    // Load the client portal view
    $CI->load->view("desk_moloni/client_portal/index");
}

/**
 * Register client portal routes
 */
if (function_exists('hooks')) {
    hooks()->add_action("clients_init", function() {
        $CI = &get_instance();
        
        // Register the main client portal route if router is available
        if (isset($CI->router) && property_exists($CI->router, 'route') && is_array($CI->router->route)) {
            $CI->router->route["clients/desk_moloni"] = "desk_moloni_client_portal_route";
        }
    });
}
