<?php

namespace EasyCriticalCSS;

use WP_Error;
use WP_REST_Request;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Debug {
	/**
	 * Appends a JSON‐encoded debug entry to our ECC log.
	 *
	 * @param array $context  Key/value context entries (will be merged with timestamp, UA, etc).
	 *
	 * @return void
	 */
	public static function ecc_log( array $context ) {
		// Only log if Debug Mode is active.
		if ( ! Settings::get_global_debug_mode() ) {
			return;
		}

		$context = wp_parse_args(
			$context,
			[
				'time' => current_time( 'mysql' ),
				'ua'   => ! empty( $_SERVER['HTTP_USER_AGENT'] )
					? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) )
					: '',
				'rest' => ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ? 1 : 0,
				'ajax' => ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ? 1 : 0,
				'cron' => ( defined( 'DOING_CRON' ) && DOING_CRON ) ? 1 : 0,
			]
		);

		$line = '[' . $context['time'] . '] ' . wp_json_encode( $context ) . "\n";

		// Write into the easy-critical-css folder
		$upload_dir = wp_upload_dir();
		$base_dir   = trailingslashit( $upload_dir['basedir'] ) . 'easy-critical-css/';
		wp_mkdir_p( $base_dir );
		$file_path = $base_dir . 'ecc-debug.log';

		// make sure folder exists
		if ( ! file_exists( dirname( $file_path ) ) ) {
			wp_mkdir_p( dirname( $file_path ) );
		}

		// We are writing to wp-content/uploads which is writable on all standard WordPress installs.
		// WP_Filesystem is not needed here and may cause permission prompts on some hosts.
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
		file_put_contents( $file_path, $line, FILE_APPEND | LOCK_EX );
	}

	public static function debug_permission() {
		// Is Debug Mode enabled?
		if ( ! Settings::get_global_debug_mode() ) {
			return false;
		}

		// Are we coming as an authorized user?
		if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) {
			return false;
		}

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- wp_validate_auth_cookie() validates cookie.
		$user_id = wp_validate_auth_cookie( wp_unslash( $_COOKIE[ LOGGED_IN_COOKIE ] ), 'logged_in' );
		if ( $user_id ) {
			wp_set_current_user( $user_id );
		}

		return current_user_can( 'edit_posts' );
	}

	public static function debug( WP_REST_Request $request ) {
		if ( $request->has_param( 'all' ) ) {
			global $wpdb;
			$table = esc_sql( Database::get_table_name() );
			// This is for support. We don't want cached results.
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			$rows = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table}" ), ARRAY_A );
			return rest_ensure_response(
				[
					'count' => count( $rows ),
					'rows'  => $rows,
				]
			);
		}

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Only echoing safely in JSON response.
		$server_software = ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) ? wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) : 'unknown';

		return rest_ensure_response(
			[
				'site_url'                     => site_url(),
				'home_url'                     => home_url(),
				'wp_version'                   => get_bloginfo( 'version' ),
				'php_version'                  => PHP_VERSION,
				'is_ssl'                       => is_ssl(),
				'rest_url'                     => rest_url(),
				'headers'                      => getallheaders(),
				'server'                       => $server_software,
				'is_api_reachable'             => Helpers::is_rest_api_reachable( true ),
				'cached_is_api_reachable'      => Helpers::is_rest_api_reachable(),
				'is_local_site'                => Helpers::is_local_site( wp_parse_url( site_url(), PHP_URL_HOST ), true ),
				'cached_is_local_site'         => Helpers::is_local_site( wp_parse_url( site_url(), PHP_URL_HOST ) ),
				'is_rocket_installed'          => Compatibility_WP_Rocket::is_rocket_installed(),
				'is_rocket_critical_activated' => Compatibility_WP_Rocket::is_rocket_critical_activated(),
				'freemius_uid'                 => Helpers::get_uid(),
				'freemius_install_id'          => Helpers::get_install_id(),
				'freemius_api_key'             => Helpers::get_api_key(),
				'request'                      => $request,
			]
		);
	}

	public static function debug_generated_css( WP_REST_Request $request ) {
		$hash = $request->get_param( 'hash' );
		Critical_CSS::clear_cache( $hash );
		$data = Critical_CSS::get_generated_css( $hash );
		if ( empty( $data ) ) {
			return new \WP_Error(
				'not_found',
				__( 'No generated CSS found for that hash.', 'easy-critical-css' ),
				[ 'status' => 404 ]
			);
		}

		return rest_ensure_response( $data );
	}

	public static function clear_log() {
		$upload_dir = wp_upload_dir();
		$file_path  = trailingslashit( $upload_dir['basedir'] ) . 'easy-critical-css/ecc-debug.log';

		if ( ! file_exists( $file_path ) ) {
			// Nothing to delete
			return true;
		}

		return wp_delete_file( $file_path );
	}

	public static function view_log( WP_REST_Request $request ) {
		$upload_dir = wp_upload_dir();
		$file_path  = trailingslashit( $upload_dir['basedir'] ) . 'easy-critical-css/ecc-debug.log';

		// If ?clear=1 is passed, delete and return a success flag.
		if ( $request->has_param( 'clear' ) ) {
			$deleted = self::clear_log();
			return rest_ensure_response( [ 'cleared' => $deleted ] );
		}

		if ( ! file_exists( $file_path ) ) {
			return rest_ensure_response( [] );
		}

		// Only display the most recent 100 lines.
		$lines  = file( $file_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
		$recent = array_slice( $lines, -100 );

		// Convert each line to JSON output.
		$entries = [];
		foreach ( $recent as $line ) {
			// Find first JSON object start.
			$pos = strpos( $line, '{' );
			if ( $pos === false ) {
				continue;
			}
			$json = substr( $line, $pos );
			$data = json_decode( $json, true );
			if ( json_last_error() === JSON_ERROR_NONE ) {
				$entries[] = $data;
			}
		}

		return rest_ensure_response( $entries );
	}
}
