<?php

namespace FleekDash\Controllers;

// Load debug helpers
if (!function_exists('fleekdash_log_error')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

use FleekDash\Core\DebugException;
use FleekDash\Core\DebugLogService;
use FleekDash\Core\WpConfigConstantEditor;
use WP_REST_Request;
use WP_REST_Response;

/**
 * Controller for managing wp-config.php modifications
 */
class WpConfigController
{
    /**
     * API namespace
     */
    const API_NAMESPACE = 'fleekdash/v1';

    private const ALLOWED_DEBUG_CONSTANTS = ['WP_DEBUG', 'WP_DEBUG_LOG', 'WP_DEBUG_DISPLAY'];

    private const ERROR_PREFIX = 'Error: ';

    /** @var string */
    private $wpConfigPath;

    /** @var DebugLogService */
    private $logService;

    public function __construct()
    {
        $this->wpConfigPath = ABSPATH . 'wp-config.php';
        $this->logService = new DebugLogService();
    }

    /**
     * Initialize hooks
     */
    public function bootstrap(): void
    {
        \add_action('rest_api_init', [$this, 'registerRoutes']);
    }

    /**
     * Register API routes
     */
    public function registerRoutes(): void
    {
        \register_rest_route(self::API_NAMESPACE, '/debug/wp-config', [
            'methods' => 'POST',
            'callback' => [$this, 'updateWpConfigConstant'],
            'permission_callback' => [$this, 'checkAdminPermissions'],
            'args' => [
                'constant' => [
                    'required' => true,
                    'type' => 'string',
                    'validate_callback' => [$this, 'validateConstantName'],
                ],
                'value' => [
                    'required' => true,
                    'type' => 'boolean',
                ],
            ],
        ]);

        \register_rest_route(self::API_NAMESPACE, '/debug/force-reset', [
            'methods' => 'POST',
            'callback' => [$this, 'resetForceDebug'],
            'permission_callback' => [$this, 'checkAdminPermissions'],
        ]);
    }

    /**
     * Check admin permissions using AuthMiddleware
     *
     * Security (v2.2): Only admins can modify wp-config.php
     *
     * @return bool
     */
    public function checkAdminPermissions()
    {
        try {
            if (!class_exists('FleekDash\\Core\\AuthMiddleware')) {
                require_once dirname(__DIR__, 1) . '/Core/AuthMiddleware.php';
            }

            $auth = \FleekDash\Core\AuthMiddleware::check('admin');

            if (!$auth['authenticated']) {
                fleekdash_log_error(sprintf(
                    'FleekDash Security: Unauthorized wp-config access attempt - IP: %s, Reason: %s',
                    $_SERVER['REMOTE_ADDR'] ?? 'unknown',
                    $auth['reason'] ?? 'unknown'
                ));
                return false;
            }

            return true;
        } catch (\Exception $e) {
            fleekdash_log_error('FleekDash Security: Auth check failed - ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Validate constant name (WP REST validate_callback signature).
     *
     * @param mixed $param Constant value from request
     * @param WP_REST_Request $request REST request
     * @param string $key Parameter name being validated
     * @return bool
     */
    public function validateConstantName($param, WP_REST_Request $request, string $key)
    {
        if ($key !== 'constant' || $request->get_method() !== 'POST') {
            return false;
        }

        return \in_array($param, self::ALLOWED_DEBUG_CONSTANTS, true);
    }

    /**
     * Update wp-config.php constant
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function updateWpConfigConstant(WP_REST_Request $request)
    {
        try {
            $constant = (string) $request->get_param('constant');
            $value = (bool) $request->get_param('value');

            if (!is_writable($this->wpConfigPath)) {
                throw new DebugException('wp-config.php file is not writable.');
            }

            $configContent = file_get_contents($this->wpConfigPath);
            if ($configContent === false) {
                throw new DebugException('Failed to read wp-config.php file.');
            }

            $logCleared = false;
            if ($constant === 'WP_DEBUG') {
                $clearResult = $this->logService->clearDebugLog();
                $logCleared = (bool) ($clearResult['success'] ?? false);
            }

            $backupPath = $this->wpConfigPath . '.backup-' . date('Y-m-d-H-i-s');
            file_put_contents($backupPath, $configContent);

            $newContent = WpConfigConstantEditor::updateConstantInConfig($configContent, $constant, $value);

            if (file_put_contents($this->wpConfigPath, $newContent) === false) {
                throw new DebugException('Failed to write to wp-config.php file.');
            }

            if (function_exists('opcache_invalidate')) {
                opcache_invalidate($this->wpConfigPath, true);
            }

            if ($constant === 'WP_DEBUG' && $logCleared) {
                fleekdash_log_info('FleekDash Debug: WP_DEBUG ' . ($value ? 'enabled' : 'disabled') .
                    ' by user ID ' . \get_current_user_id() . ' (debug.log automatically cleared)');
            }

            $message = "Successfully updated {$constant}";
            if ($logCleared) {
                $message .= ' and debug.log cleared';
            }

            return new WP_REST_Response([
                'success' => true,
                'message' => $message,
                'data' => [
                    'constant' => $constant,
                    'value' => $value,
                    'log_cleared' => $logCleared,
                ],
            ], 200);
        } catch (DebugException $e) {
            fleekdash_log_error('FleekDash: ' . self::ERROR_PREFIX . $e->getMessage());

            return new WP_REST_Response([
                'success' => false,
                'message' => self::ERROR_PREFIX . $e->getMessage(),
            ], 500);
        } catch (\Exception $e) {
            fleekdash_log_error('FleekDash: ' . self::ERROR_PREFIX . $e->getMessage());

            return new WP_REST_Response([
                'success' => false,
                'message' => self::ERROR_PREFIX . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Reset force debug override
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function resetForceDebug(WP_REST_Request $request)
    {
        if ($request->get_method() !== 'POST') {
            return new WP_REST_Response([
                'success' => false,
                'message' => 'Method not allowed',
            ], 405);
        }

        try {
            \delete_option('fleekdash_force_debug');

            return new WP_REST_Response([
                'success' => true,
                'message' => 'Force debug override has been reset.',
            ], 200);
        } catch (\Exception $e) {
            return new WP_REST_Response([
                'success' => false,
                'message' => self::ERROR_PREFIX . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Check if wp-config.php is writable
     *
     * @return bool
     */
    public function isWpConfigWritable()
    {
        return is_writable($this->wpConfigPath);
    }

    /**
     * Get wp-config.php file info
     *
     * @return array<string, mixed>
     */
    public function getWpConfigInfo()
    {
        return [
            'path' => $this->wpConfigPath,
            'exists' => file_exists($this->wpConfigPath),
            'writable' => $this->isWpConfigWritable(),
            'size' => file_exists($this->wpConfigPath) ? filesize($this->wpConfigPath) : 0,
            'last_modified' => file_exists($this->wpConfigPath) ? filemtime($this->wpConfigPath) : 0,
        ];
    }
}
