<?php

namespace FlowSystems\WebhookActions;

defined('ABSPATH') || exit;

use FlowSystems\WebhookActions\Controllers\DispatcherController;
use FlowSystems\WebhookActions\Controllers\AdminController;
use FlowSystems\WebhookActions\Database\Migrator;
use FlowSystems\WebhookActions\Services\LogArchiver;
use FlowSystems\WebhookActions\Services\QueueService;
use FlowSystems\WebhookActions\Services\ActivityLogService;
use FlowSystems\WebhookActions\Services\HookDiscoveryService;
use FlowSystems\WebhookActions\Services\LocalDevHttp;
use FlowSystems\WebhookActions\Services\Scheduler;
use FlowSystems\WebhookActions\Integrations\IntegrationLoader;
use FlowSystems\WebhookActions\Abilities\AbilityRegistrar;

class App {
  /** Plugin version — single source of truth is FSWA_VERSION in the main file. */
  const VERSION = FSWA_VERSION;
  const SLUG = 'flowsystems-webhook-actions';

  public static string $path = '';
  public static string $url = '';

  private static ?self $_instance = null;

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

  private function __construct() {
    self::$_instance = $this;

    if (!self::$path) {
      self::$path = str_replace('/src', '', rtrim(plugin_dir_path(__FILE__), '/'));
    }

    if (!self::$url) {
      self::$url = str_replace('/src', '', rtrim(plugin_dir_url(__FILE__), '/'));
    }

    $this->init();
  }

  /**
   * Initialize the plugin
   *
   * @return void
   */
  public function init(): void {
    // Load translations. Hooked on `init` to satisfy WP 6.7+ just-in-time loading
    // expectations (calling earlier triggers a _doing_it_wrong notice).
    add_action('init', [$this, 'loadTextdomain']);

    // Register custom cron schedules (only needed when Action Scheduler is not active)
    if (!Scheduler::hasActionScheduler()) {
      add_filter('cron_schedules', [$this, 'registerCronSchedules']);
    }

    // Run migrations if needed
    if (Migrator::needsMigration()) {
      Migrator::migrate();
    }

    // Initialize controllers
    new DispatcherController();
    new AdminController();

    // Third-party integrations (loaded only when the plugin is active)
    (new IntegrationLoader())->load();

    // Local-dev only: skip TLS verification for loopback calls to our OWN host on
    // a self-signed local box (off by default; gated on wp_get_environment_type()
    // === 'local' AND same-host — external endpoints always keep full TLS).
    (new LocalDevHttp())->register();

    // Expose the AI Builder toolset to the WordPress Abilities API (WP 6.9+/7.0)
    // when available — additive, so the agent works on older versions too.
    (new AbilityRegistrar())->init();

    // Register cleanup cron
    add_action('fswa_cleanup_logs', [$this, 'runLogCleanup']);

    // Bust hook discovery cache when plugins or theme change.
    add_action('activated_plugin', [HookDiscoveryService::class, 'clearCache']);
    add_action('deactivated_plugin', [HookDiscoveryService::class, 'clearCache']);
    add_action('switch_theme', [HookDiscoveryService::class, 'clearCache']);

    // Schedule queue processor and cleanup if not already scheduled.
    // Deferred to `init` so Action Scheduler is fully initialized before we call as_* functions.
    add_action('init', [$this, 'ensureScheduled'], 1);
  }

  /**
   * Load the plugin text domain so translations resolve.
   */
  public function loadTextdomain(): void {
    load_plugin_textdomain(
      'flowsystems-webhook-actions',
      false,
      dirname(plugin_basename(FSWA_FILE)) . '/languages'
    );
  }

  /**
   * Register custom cron schedules
   */
  public function registerCronSchedules(array $schedules): array {
    if (!isset($schedules['every_minute'])) {
      $schedules['every_minute'] = [
        'interval' => 60,
        'display' => __('Every Minute', 'flowsystems-webhook-actions'),
      ];
    }
    return $schedules;
  }

  /**
   * Ensure recurring actions are scheduled (self-healing on every request)
   */
  public function ensureScheduled(): void {
    Scheduler::scheduleRecurring('fswa_process_queue', MINUTE_IN_SECONDS, 'every_minute');
    Scheduler::scheduleRecurring('fswa_cleanup_logs', DAY_IN_SECONDS, 'daily', strtotime('tomorrow 3:00am'));
  }

  /**
   * Run log cleanup and archiving
   */
  public function runLogCleanup(): void {
    $retentionDays = (int) get_option('fswa_log_retention_days', 30);
    $archiveEnabled = (bool) get_option('fswa_archive_logs', true);

    $archiver = new LogArchiver();

    if ($archiveEnabled) {
      // Archive logs before deleting
      $archiver->archiveLogs($retentionDays);
    } else {
      // Delete old logs (aggregates stats before deletion)
      $archiver->deleteLogsWithoutArchive($retentionDays);
    }

    // Also cleanup old completed queue jobs (keep for 7 days)
    $queueService = new QueueService();
    $queueService->cleanupCompletedJobs(7);

    // Prune activity logs
    $activityRetentionDays = (int) get_option('fswa_activity_log_retention_days', 90);
    (new ActivityLogService())->pruneOlderThan($activityRetentionDays);
  }

  /**
   * Deactivate plugin
   */
  public static function deactivate(): void {
    Activation::deactivate();
  }
}
