<?php
namespace GlpiPlugin\Wbstore;

use Config as GlpiConfig;
use Migration;

if (!defined('GLPI_ROOT')) {
   die("Sorry. You can't access this file directly");
}

class Installer {

   public function install(): bool {
      $migration = new Migration(120); // internal migration version for our plugin
      $this->installConfigDefaults();

      global $DB;

      // Packages table
      $table = self::packagesTable();
      $sql = "CREATE TABLE IF NOT EXISTS `{$table}` (
         `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
         `slug` VARCHAR(255) NOT NULL,
         `name` VARCHAR(255) NOT NULL,
         `version` VARCHAR(64) NOT NULL DEFAULT '',
         `plugin_dir` VARCHAR(255) NOT NULL,
         `sha256` CHAR(64) NOT NULL DEFAULT '',
         `installed_at` TIMESTAMP NULL DEFAULT NULL,
         PRIMARY KEY (`id`),
         UNIQUE KEY `uniq_slug` (`slug`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";

      try {
         if (method_exists($DB, 'doQuery')) {
            $DB->doQuery($sql);
         } else {
            $DB->request(['QUERY' => $sql]);
         }
      } catch (\Throwable $e) {
         error_log('[wbstore] Install failed creating packages table: ' . $e->getMessage());
         return false;
      }

      // Notifications table
      $ntable = self::notificationsTable();
      $nsql = "CREATE TABLE IF NOT EXISTS `{$ntable}` (
         `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
         `instance_id` VARCHAR(64) NOT NULL,
         `license_key` VARCHAR(80) NOT NULL,
         `title` VARCHAR(255) NOT NULL DEFAULT '',
         `message` TEXT NULL,
         `level` VARCHAR(20) NOT NULL DEFAULT 'info',
         `url` TEXT NULL,
         `is_read` TINYINT(1) NOT NULL DEFAULT 0,
         `created_at` DATETIME NOT NULL,
         PRIMARY KEY (`id`),
         KEY `idx_instance_license` (`instance_id`,`license_key`),
         KEY `idx_is_read` (`is_read`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";

      try {
         if (method_exists($DB, 'doQuery')) {
            $DB->doQuery($nsql);
         } else {
            $DB->request(['QUERY' => $nsql]);
         }
      } catch (\Throwable $e) {
         error_log('[wbstore] Install failed creating notifications table: ' . $e->getMessage());
         return false;
      }

      $migration->executeMigration();

      // Cron (sincronizar licença/pacotes) - best-effort
      try {
         if (class_exists('CronTask') && method_exists('CronTask', 'Register')) {
            // Frequência diária. A janela 01:00-04:00 é controlada dentro do cron.class.php.
            \CronTask::Register('PluginWbstoreCron', 'WbstoreSync', DAY_TIMESTAMP, [
               'mode'    => \CronTask::MODE_EXTERNAL,
               'comment' => 'WBStore: sincroniza licença/pacotes (cache local)'
            ]);
         }
      } catch (\Throwable $e) {
         // ignore
      }

      return true;
   }

   public function uninstall(): bool {
      // Remove config values
      $cfg = new \Config();
      $cfg->deleteByCriteria(['context' => Config::context()]);

      global $DB;

      // Drop packages table
      try {
         $DB->doQuery('DROP TABLE IF EXISTS `' . str_replace('`', '', self::packagesTable()) . '`');
      } catch (\Throwable $e) {
         error_log('[wbstore] Uninstall failed dropping packages table: ' . $e->getMessage());
      }

      // Drop notifications table
      try {
         $DB->doQuery('DROP TABLE IF EXISTS `' . str_replace('`', '', self::notificationsTable()) . '`');
      } catch (\Throwable $e) {
         error_log('[wbstore] Uninstall failed dropping notifications table: ' . $e->getMessage());
      }

      $migration = new Migration(120);
      $migration->executeMigration();
      return true;
   }

   private function installConfigDefaults(): void {
      GlpiConfig::setConfigurationValues(Config::context(), [
         'store_url'      => 'https://store.wbuarque.com.br',
         // Iframe de avisos (se vazio, usa {store_url}/wbstore/avisos)
         'notices_iframe_url' => '',
         'api_base'       => 'https://store.wbuarque.com.br/wp-json/wbstore/v1',
         'license_key'    => '',
         // Endpoints (relative) used by the Store server
         'register_path'  => '/register-free',
         'lookup_path'    => '/register-lookup',
         'donation_path'  => '/donation-verify',
         // Pix (donation) presentation (optional)
         'pix_qr_url'     => 'https://wbuarque.com.br/wp-content/uploads/public_html/img/pix.jpeg',
         'pix_code'       => '',
         // Optional: some stores validate by the licensed domain (not the GLPI host)
         'domain'         => '',
         // Optional: some stores require a separate token for download endpoints
         'token'          => '',
         'ssl_verify'     => 1,
         'instance_id'    => '',
         'safe_mode'      => 1, // do not auto-activate installed plugins
         'allow_download' => 1,

         // Client identity (saved after lookup/register)
         'client_name'    => '',
         'client_email'   => '',
         'client_phone'   => '',
         'client_company' => '',
         'client_plan'    => '',

         // License cache & offline grace
         'license_cache_hours' => 6,
         'offline_grace_days'  => 7,
         'license_valid_until' => 0,
         'license_last_ok_at'  => 0,

         // Portal -> GLPI notifications auth token
         'portal_token'        => '',

         // One-time activation events tracker (json)
         'activated_sent'      => '',
      ]);

      // Generate instance_id if missing
      $vals = GlpiConfig::getConfigurationValues(Config::context(), ['instance_id']);
      if (empty($vals['instance_id'])) {
         GlpiConfig::setConfigurationValues(Config::context(), [
            'instance_id' => Utils::uuidv4()
         ]);
      }

      // Generate portal_token if missing
      $vals2 = GlpiConfig::getConfigurationValues(Config::context(), ['portal_token']);
      if (empty($vals2['portal_token'])) {
         GlpiConfig::setConfigurationValues(Config::context(), [
            'portal_token' => bin2hex(random_bytes(24))
         ]);
      }
   }

   public static function packagesTable(): string {
      global $DB, $CFG_GLPI;

      if (method_exists($DB, 'getTable')) {
         return $DB->getTable('plugin_wbstore_packages');
      }

      $prefix = 'glpi_';
      if (isset($DB->prefix) && !empty($DB->prefix)) {
         $prefix = $DB->prefix;
      } elseif (isset($CFG_GLPI['dbprefix']) && !empty($CFG_GLPI['dbprefix'])) {
         $prefix = $CFG_GLPI['dbprefix'];
      }

      return $prefix . 'plugin_wbstore_packages';
   }

   public static function notificationsTable(): string {
      global $DB, $CFG_GLPI;

      if (method_exists($DB, 'getTable')) {
         return $DB->getTable('plugin_wbstore_notifications');
      }

      $prefix = 'glpi_';
      if (isset($DB->prefix) && !empty($DB->prefix)) {
         $prefix = $DB->prefix;
      } elseif (isset($CFG_GLPI['dbprefix']) && !empty($CFG_GLPI['dbprefix'])) {
         $prefix = $CFG_GLPI['dbprefix'];
      }

      return $prefix . 'plugin_wbstore_notifications';
   }
}
