<?php

/**
 * Plugin Name:       Easy Chat Support - Capripio
 * Plugin URI:         https://capripio.com/capripio-easy-chat-support
 * Description:        A fast live chat widget for your WordPress site, with optional Pro features for teams: multiple agents, canned replies, file uploads, visitor insights, and more.
 * Version:             1.0.3
 * Requires at least:  5.8
 * Requires PHP:        7.4
 * Author:              Capripio
 * Author URI:          https://capripio.com
 * License:             GPL v2 or later
 * License URI:         https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:         capripio-easy-chat-support
 *
 */
// Exit if accessed directly.
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
// ---------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------
define( 'CPECS_VERSION', '1.0.3' );
define( 'CPECS_DB_VERSION', '1.0.0' );
define( 'CPECS_PLUGIN_FILE', __FILE__ );
define( 'CPECS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'CPECS_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'CPECS_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
// Branding backlink (opt-in, off by default — see Settings > Branding).
define( 'CPECS_BRAND_NAME', 'Capripio' );
define( 'CPECS_BRAND_URL', 'https://capripio.com/capripio-easy-chat-support' );
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
    require_once __DIR__ . '/vendor/autoload.php';
}
if ( !function_exists( 'fs_dynamic_init' ) ) {
    // vendor/ hasn't been installed (run `composer install`). Don't
    // fatal-error the whole site over a missing dependency — just
    // tell whoever can fix it, and stop loading this plugin's code.
    add_action( 'admin_notices', function () {
        if ( !current_user_can( 'activate_plugins' ) ) {
            return;
        }
        echo '<div class="notice notice-error"><p>';
        echo esc_html__( 'Easy Chat Support - Capripio: the Freemius SDK is missing. Run "composer install" in the plugin folder, then reload this page.', 'capripio-easy-chat-support' );
        echo '</p></div>';
    } );
    return;
}
if ( !function_exists( 'cecs_fs' ) ) {
    // Create a helper function for easy SDK access.
    function cecs_fs() {
        global $cecs_fs;
        if ( !isset( $cecs_fs ) ) {
            // Include Freemius SDK (auto-loaded through Composer).
            $cecs_fs = fs_dynamic_init( array(
                'id'               => '33376',
                'slug'             => 'capripio-easy-chat-support',
                'premium_slug'     => 'capripio-easy-chat-support-pro',
                'type'             => 'plugin',
                'public_key'       => 'pk_1050a975b37ae339c15d45479c1d1',
                'is_premium'       => false,
                'is_premium_only'  => false,
                'has_addons'       => false,
                'has_paid_plans'   => true,
                'is_org_compliant' => true,
                'is_live'          => true,
            ) );
        }
        return $cecs_fs;
    }

    // Init Freemius.
    cecs_fs();
    // Signal that SDK was initiated.
    do_action( 'cecs_fs_loaded' );
}
/**
 * Main plugin class. Bootstraps the free feature set unconditionally,
 * and the premium feature set behind cecs_fs()->is__premium_only() so
 * Freemius's deployment preprocessor can strip that code when it
 * auto-generates the free (WordPress.org) version from this same
 * codebase. See includes/class-cpecs-license.php for finer-grained
 * runtime license checks inside already-loaded premium classes.
 */
final class CPECS_Plugin {
    /**
     * @var CPECS_Plugin|null
     */
    private static $instance = null;

    // Core (free) modules.
    /** @var CPECS_DB */
    public $db;

    /** @var CPECS_Settings */
    public $settings;

    /** @var CPECS_REST */
    public $rest;

    /** @var CPECS_Cleanup */
    public $cleanup;

    /** @var CPECS_Notifications */
    public $notifications;

    /** @var CPECS_Admin */
    public $admin;

    /** @var CPECS_Widget */
    public $widget;

    // Premium modules — always constructed (each class checks
    // CPECS_License::is_pro() internally where it matters), so a
    // license activated later unlocks features without a reinstall.
    /** @var CPECS_Pro_Settings */
    public $pro_settings;

    /** @var CPECS_Pro_Agents */
    public $agents;

    /** @var CPECS_Pro_Status */
    public $status;

    /** @var CPECS_Pro_Notes */
    public $notes;

    /** @var CPECS_Pro_Tags */
    public $tags;

    /** @var CPECS_Pro_Canned */
    public $canned;

    /** @var CPECS_Pro_Uploads */
    public $uploads;

    /** @var CPECS_Pro_Insights */
    public $insights;

    /** @var CPECS_Pro_Export */
    public $export;

    /** @var CPECS_Pro_Notify */
    public $notify;

    public static function instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        $this->includes();
        $this->init_modules();
        $this->hooks();
    }

    private function includes() {
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-license.php';
        // Core.
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-install.php';
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-db.php';
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-settings.php';
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-rest.php';
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-cleanup.php';
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-notifications.php';
        require_once CPECS_PLUGIN_DIR . 'public/class-cpecs-widget.php';
        if ( is_admin() ) {
            require_once CPECS_PLUGIN_DIR . 'admin/class-cpecs-admin.php';
        }
    }

    private function init_modules() {
        $this->db = new CPECS_DB();
        $this->settings = new CPECS_Settings();
        $this->rest = new CPECS_REST($this->db, $this->settings);
        $this->cleanup = new CPECS_Cleanup($this->db, $this->settings);
        $this->notifications = new CPECS_Notifications($this->settings);
        $this->widget = new CPECS_Widget($this->settings);
        if ( is_admin() ) {
            $this->admin = new CPECS_Admin($this->db, $this->settings, $this->cleanup);
        }
    }

    private function hooks() {
        add_action( 'plugins_loaded', array($this, 'maybe_upgrade') );
    }

    /**
     * Runs a lightweight version check on every load so table upgrades
     * apply even if activation hook was missed (e.g. plugin updated
     * without deactivate/reactivate).
     */
    public function maybe_upgrade() {
        $installed = get_option( 'cpecs_db_version' );
        if ( $installed !== CPECS_DB_VERSION ) {
            CPECS_Install::create_tables();
            update_option( 'cpecs_db_version', CPECS_DB_VERSION );
        }
    }

    /**
     * The visitor-facing widget's typing indicator and file-upload
     * button are premium features layered on top of the free widget
     * via the 'cpecs_widget_enqueued' action.
     */
    public function enqueue_premium_widget_assets() {
        wp_enqueue_style(
            'cpecs-pro-widget',
            CPECS_PLUGIN_URL . 'assets/css/premium/pro-widget.css',
            array('cpecs-widget'),
            CPECS_VERSION
        );
        wp_enqueue_script(
            'cpecs-pro-widget',
            CPECS_PLUGIN_URL . 'assets/js/premium/pro-widget.js',
            array('cpecs-widget'),
            CPECS_VERSION,
            true
        );
        wp_localize_script( 'cpecs-pro-widget', 'CPECS_PRO_WIDGET', array(
            'restUrl' => esc_url_raw( rest_url( 'cpecs/v1' ) ),
            'nonce'   => wp_create_nonce( 'cpecs_widget' ),
        ) );
    }

}

/**
 * Access the single plugin instance from anywhere:
 *
 *   if ( function_exists( 'cpecs' ) ) { $db = cpecs()->db; }
 */
function cpecs() {
    return CPECS_Plugin::instance();
}

/**
 * Returns ' cpecs-theme-dark' if dark mode is on, else ''. Used both
 * as the 'cpecs_admin_app_class' filter callback (for the core
 * Inbox/Settings pages) and directly inside the premium admin pages'
 * own render_*_page() methods.
 */
function cpecs_dark_mode_class() {
    if ( !function_exists( 'cpecs' ) || !cpecs()->pro_settings ) {
        return '';
    }
    $settings = cpecs()->pro_settings->get_all();
    return ( !empty( $settings['dark_mode'] ) ? ' cpecs-theme-dark' : '' );
}

/**
 * Shared by every premium admin page (Agents, Canned Replies, Pro
 * Settings) to guarantee the glass dashboard shell (base CSS/JS + the
 * premium admin/dark CSS) is present, since the core Inbox/Settings
 * pages only auto-enqueue the base shell on themselves.
 *
 * @param string $page_slug The current page's data-view / CPECS_ADMIN.page value.
 */
function cpecs_enqueue_admin_shell(  $page_slug  ) {
    wp_enqueue_style(
        'cpecs-admin',
        CPECS_PLUGIN_URL . 'assets/css/admin.css',
        array(),
        CPECS_VERSION
    );
    wp_enqueue_script(
        'cpecs-admin',
        CPECS_PLUGIN_URL . 'assets/js/admin-inbox.js',
        array(),
        CPECS_VERSION,
        true
    );
    wp_localize_script( 'cpecs-admin', 'CPECS_ADMIN', array(
        'restUrl'     => esc_url_raw( rest_url( 'cpecs/v1' ) ),
        'restNonce'   => wp_create_nonce( 'wp_rest' ),
        'ajaxUrl'     => admin_url( 'admin-ajax.php' ),
        'ajaxNonce'   => wp_create_nonce( 'cpecs_admin' ),
        'settings'    => array(),
        'lastCleanup' => array(
            'ran_at' => '',
            'count'  => 0,
        ),
        'page'        => $page_slug,
        'navItems'    => apply_filters( 'cpecs_admin_nav_items', array(array(
            'key'   => 'inbox',
            'label' => __( 'Inbox', 'capripio-easy-chat-support' ),
            'url'   => admin_url( 'admin.php?page=cpecs-inbox' ),
        ), array(
            'key'   => 'settings',
            'label' => __( 'Settings', 'capripio-easy-chat-support' ),
            'url'   => admin_url( 'admin.php?page=cpecs-settings' ),
        )) ),
    ) );
    wp_enqueue_style(
        'cpecs-pro-admin',
        CPECS_PLUGIN_URL . 'assets/css/premium/pro-admin.css',
        array('cpecs-admin'),
        CPECS_VERSION
    );
    wp_enqueue_style(
        'cpecs-pro-dark',
        CPECS_PLUGIN_URL . 'assets/css/premium/pro-dark.css',
        array('cpecs-admin', 'cpecs-pro-admin'),
        CPECS_VERSION
    );
}

// ---------------------------------------------------------------------
// Activation / Deactivation
// ---------------------------------------------------------------------
function cpecs_activate() {
    require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-install.php';
    CPECS_Install::create_tables();
    update_option( 'cpecs_db_version', CPECS_DB_VERSION );
    require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-cleanup.php';
    CPECS_Cleanup::schedule_event();
    if ( false === get_option( 'cpecs_settings' ) ) {
        require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-settings.php';
        update_option( 'cpecs_settings', CPECS_Settings::defaults() );
    }
}

register_activation_hook( __FILE__, 'cpecs_activate' );
function cpecs_deactivate() {
    require_once CPECS_PLUGIN_DIR . 'includes/class-cpecs-cleanup.php';
    CPECS_Cleanup::unschedule_event();
}

register_deactivation_hook( __FILE__, 'cpecs_deactivate' );
// ---------------------------------------------------------------------
// Uninstall
//
// Freemius doesn't allow a standalone uninstall.php (it needs to run
// its own license/deactivation bookkeeping on uninstall too), so
// cleanup for both core and premium data is registered through its
// 'after_uninstall' action instead of a file WordPress calls directly.
// ---------------------------------------------------------------------
cecs_fs()->add_action( 'after_uninstall', function () {
    $cpecs_settings = get_option( 'cpecs_settings', array() );
    if ( empty( $cpecs_settings['delete_data_on_uninstall'] ) ) {
        return;
    }
    global $wpdb;
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- removing this plugin's own custom tables on uninstall; no core API exists for dropping a custom table.
    $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}cpecs_messages" );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- removing this plugin's own custom tables on uninstall; no core API exists for dropping a custom table.
    $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}cpecs_conversations" );
    delete_option( 'cpecs_settings' );
    delete_option( 'cpecs_db_version' );
    delete_option( 'cpecs_last_cleanup_run' );
    delete_option( 'cpecs_last_cleanup_count' );
    $cpecs_cleanup_timestamp = wp_next_scheduled( 'cpecs_daily_cleanup' );
    if ( $cpecs_cleanup_timestamp ) {
        wp_unschedule_event( $cpecs_cleanup_timestamp, 'cpecs_daily_cleanup' );
    }
    if ( class_exists( 'CPECS_Pro_Install' ) ) {
        CPECS_Pro_Install::drop_tables();
        delete_option( 'cpecs_pro_settings' );
    }
} );
// Boot.
cpecs();