<?php

declare(strict_types=1);

namespace KimaAI\Admin;

use KimaAI\Helper;

defined('ABSPATH') || exit;

class DebugInfo {

  /**
   * Registers debug information hooks.
   */
  public function registerHooks(): void {
    add_filter('debug_information', [$this, 'addDebugInformation']);
  }

  /**
   * Adds KimaAI-specific info into WordPress core Site Health debug info.
   */
  public function addDebugInformation(array $info): array {
    $settings_summary = $this->getKimaaiSettingsSummary();
    $debug_log = $this->getDebugLogData();
    $health_checks = $this->getCoreHealthChecks();

    $fields = [
      'kimaai_version' => [
        'label' => __('Version', 'kimaai'),
        'value' => defined('KIMAAI_VERSION') ? KIMAAI_VERSION : __('Unknown', 'kimaai'),
      ],
      'free_or_pro' => [
        'label' => __('Free or Pro', 'kimaai'),
        'value' => Helper::isPremium() ? __('Pro', 'kimaai') : __('Free', 'kimaai'),
      ],
      'php_version' => [
        'label' => __('PHP Version', 'kimaai'),
        'value' => PHP_VERSION,
      ],
      'wp_version' => [
        'label' => __('WordPress Version', 'kimaai'),
        'value' => get_bloginfo('version'),
      ],
      'rest_api_status' => [
        'label' => __('REST API Status', 'kimaai'),
        'value' => $health_checks['rest_api']['label'] . ' [' . $health_checks['rest_api']['status'] . ']',
      ],
      'rest_api_message' => [
        'label' => __('REST API Details', 'kimaai'),
        'value' => $health_checks['rest_api']['message'],
      ],
      'outbound_http_status' => [
        'label' => __('Outbound HTTP Status', 'kimaai'),
        'value' => $health_checks['dotorg']['label'] . ' [' . $health_checks['dotorg']['status'] . ']',
      ],
      'outbound_http_message' => [
        'label' => __('Outbound HTTP Details', 'kimaai'),
        'value' => $health_checks['dotorg']['message'],
      ],
      'loopback_status' => [
        'label' => __('Loopback Status', 'kimaai'),
        'value' => $health_checks['loopback']['label'] . ' [' . $health_checks['loopback']['status'] . ']',
      ],
      'loopback_message' => [
        'label' => __('Loopback Details', 'kimaai'),
        'value' => $health_checks['loopback']['message'],
      ],
      'debug_log_path' => [
        'label' => __('Debug Log Path', 'kimaai'),
        'value' => $debug_log['path'],
      ],
      'debug_log_exists' => [
        'label' => __('Debug Log Exists', 'kimaai'),
        'value' => $debug_log['exists'] ? __('Yes', 'kimaai') : __('No', 'kimaai'),
      ],
      'debug_log_readable' => [
        'label' => __('Debug Log Readable', 'kimaai'),
        'value' => $debug_log['readable'] ? __('Yes', 'kimaai') : __('No', 'kimaai'),
      ],
      'debug_log_tail' => [
        'label' => __('Debug Log Tail', 'kimaai'),
        'value' => $debug_log['tail'],
      ],
      'wp_debug' => [
        'label' => __('WP_DEBUG', 'kimaai'),
        'value' => $debug_log['wp_debug'],
      ],
      'wp_debug_log' => [
        'label' => __('WP_DEBUG_LOG', 'kimaai'),
        'value' => $debug_log['wp_debug_log'],
      ],
    ];

    foreach ($settings_summary['items'] as $setting_name => $setting_value) {
      $fields['setting_' . sanitize_key((string) $setting_name)] = [
        'label' => (string) $setting_name,
        'value' => (string) $setting_value,
      ];
    }

    $info['kimaai'] = [
      'label' => __('KimaAI', 'kimaai'),
      'description' => __('KimaAI-specific diagnostic information, including plugin settings and debug log details.', 'kimaai'),
      'show_count' => false,
      'fields' => $fields,
    ];

    return $info;
  }

  /**
   * Gets a summary of stored KimaAI settings.
   */
  private function getKimaaiSettingsSummary(): array {
    global $wpdb;

    $items = [];

    // phpcs:ignore
    $rows = $wpdb->get_results(
      "SELECT option_name, option_value
       FROM {$wpdb->options}
       WHERE option_name LIKE 'kimaai_%'
       ORDER BY option_name ASC",
      ARRAY_A
    );

    if (!is_array($rows)) {
      return [
        'items' => [],
      ];
    }

    foreach ($rows as $row) {
      $option_name = isset($row['option_name']) ? (string) $row['option_name'] : '';
      $option_value = isset($row['option_value']) ? maybe_unserialize($row['option_value']) : null;
      if ($option_name === '') {
        continue;
      }

      $items[$option_name] = $this->summarizeOptionValue($option_value);
    }

    return [
      'items' => $items,
    ];
  }

  /**
   * Summarizes an option value for display.
   *
   * @param mixed $value Option value.
   */
  private function summarizeOptionValue(mixed $value): string {
    if (is_bool($value)) {
      return $value ? 'true' : 'false';
    }

    if (is_null($value)) {
      return 'null';
    }

    if (is_int($value) || is_float($value)) {
      return (string) $value;
    }

    if (is_string($value)) {
      $trimmed = trim($value);

      if ($trimmed === '') {
        return '(empty string)';
      }

      if (strlen($trimmed) > 120) {
        return 'string(' . strlen($trimmed) . '): ' . substr($trimmed, 0, 120) . '…';
      }

      return $trimmed;
    }

    if (is_array($value)) {
      $keys = array_keys($value);
      $preview = array_slice($keys, 0, 8);
      $preview = array_map(static fn($item): string => (string) $item, $preview);

      return 'array(' . count($value) . ') keys: ' . implode(', ', $preview);
    }

    if (is_object($value)) {
      return 'object(' . get_class($value) . ')';
    }

    return gettype($value);
  }

  /**
   * Gets debug log metadata and tail data.
   */
  private function getDebugLogData(): array {
    $wp_debug = defined('WP_DEBUG') && WP_DEBUG ? 'Enabled' : 'Disabled';
    $wp_debug_log = defined('WP_DEBUG_LOG') ? WP_DEBUG_LOG : false;

    if (is_string($wp_debug_log) && $wp_debug_log !== '') {
      $path = $wp_debug_log;
    }
    elseif ($wp_debug_log) {
      $path = WP_CONTENT_DIR . '/debug.log';
    }
    else {
      $path = WP_CONTENT_DIR . '/debug.log';
    }

    $exists = file_exists($path);
    $readable = is_readable($path);

    return [
      'wp_debug' => $wp_debug,
      'wp_debug_log' => is_bool($wp_debug_log) ? ($wp_debug_log ? 'Enabled' : 'Disabled') : (string) $wp_debug_log,
      'path' => $path,
      'exists' => $exists,
      'readable' => $readable,
      'size' => $exists ? size_format((int) filesize($path)) : '—',
      'modified' => $exists ? wp_date('Y-m-d H:i:s', (int) filemtime($path)) : '—',
      'tail' => ($exists && $readable) ? $this->tailFile($path, 10) : __('debug.log not found or not readable.', 'kimaai'),
    ];
  }

  /**
   * Run core Site Health checks for the at-a-glance cards.
   */
  private function getCoreHealthChecks(): array {
    if (!class_exists('WP_Site_Health')) {
      require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
    }

    $site_health = \WP_Site_Health::get_instance();

    $rest = $site_health->get_test_rest_availability();
    $dotorg = $site_health->get_test_dotorg_communication();
    $loopback = $site_health->get_test_loopback_requests();

    return [
      'rest_api' => $this->normalizeSiteHealthResult($rest),
      'dotorg' => $this->normalizeSiteHealthResult($dotorg),
      'loopback' => $this->normalizeSiteHealthResult($loopback),
    ];
  }

  /**
   * Normalize a Site Health result to a simpler structure for cards/reports.
   */
  private function normalizeSiteHealthResult(array $result): array {
    $status = isset($result['status']) ? (string) $result['status'] : 'recommended';
    // Map WordPress Site Health statuses to emojis for quick visual scanning in the admin debug info section.
    $status = match ($status) {
      'good' => 'good ✅',
      'recommended' => 'recommended ⚠️',
      'critical' => 'critical ❌',
      default => $status . ' ❓',
    };

    $label = isset($result['label']) ? wp_strip_all_tags((string) $result['label']) : __('Unknown', 'kimaai');
    $description = isset($result['description']) ? wp_strip_all_tags((string) $result['description']) : '';

    return [
      'status' => $status,
      'ok' => $status === 'good',
      'label' => $label,
      'message' => trim((string) preg_replace('/\s+/', ' ', $description)),
    ];
  }

  /**
   * Reads the last lines of a file.
   *
   * @param string $file_path File path.
   * @param int $lines Number of lines to read.
   */
  private function tailFile(string $file_path, int $lines = 150): string {
    $lines = max(1, abs($lines));

    // phpcs:ignore
    $handle = @fopen($file_path, 'rb');

    if (!$handle) {
      return __('Could not open debug log file.', 'kimaai');
    }

    $buffer = '';
    $chunk_size = 4096;
    $line_count = 0;

    fseek($handle, 0, SEEK_END);
    $position = ftell($handle);

    while ($position > 0 && $line_count < $lines) {
      $seek = max($position - $chunk_size, 0);
      $read = $position - $seek;
      fseek($handle, $seek);

      // phpcs:ignore
      $chunk = fread($handle, $read);

      if ($chunk === false) {
        break;
      }

      $buffer = $chunk . $buffer;
      $line_count = substr_count($buffer, "\n");
      $position = $seek;
    }

    // phpcs:ignore
    fclose($handle);

    $buffer_lines = preg_split("/\r\n|\n|\r/", trim($buffer));
    if (!is_array($buffer_lines)) {
      return trim($buffer);
    }
    $tail = array_slice($buffer_lines, -$lines);

    return implode(PHP_EOL, $tail);
  }
}
