<?php

namespace SerpIQ\Api\Controllers;

use SerpIQ\Gsc\Sync;

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

final class Sync_Controller {
	private static ?Sync_Controller $instance = null;

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

	public function register_routes(): void {
		register_rest_route(
			'serpiq/v1',
			'/sync/run',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'run' ),
				'permission_callback' => array( \SerpIQ\Api\Rest_Permission::class, 'admin_rest_request' ),
				'args'                => array(
					'days' => array(
						'type'              => 'integer',
						'default'           => 3,
						'enum'              => array( 3, 7, 30, 90, 365, 485 ),
						'sanitize_callback' => 'absint',
					),
				),
			)
		);
	}

	public function run( \WP_REST_Request $request ): \WP_REST_Response {
		$days = absint( $request->get_param( 'days' ) );
		$allowed = array( 3, 7, 30, 90, 365, 485 );
		if ( ! in_array( $days, $allowed, true ) ) {
			$days = 3;
		}

		if ( 485 === $days ) {
			$res = Sync::instance()->run_last_485_days();
		} elseif ( 365 === $days ) {
			$res = Sync::instance()->run_last_365_days();
		} elseif ( 90 === $days ) {
			$res = Sync::instance()->run_last_90_days();
		} elseif ( 30 === $days ) {
			$res = Sync::instance()->run_last_30_days();
		} elseif ( 7 === $days ) {
			$res = Sync::instance()->run_last_7_days();
		} else {
			$res = Sync::instance()->run_last_3_days();
		}

		if ( is_wp_error( $res ) ) {
			$enriched = $this->enrich_sync_error( $res );
			return new \WP_REST_Response(
				array(
					'error'              => $res->get_error_code(),
					'message'            => $res->get_error_message(),
					'what_happened'      => $enriched['what_happened'],
					'recommendation'     => $enriched['recommendation'],
					'recommendation_key' => $enriched['recommendation_key'],
				),
				400
			);
		}

		return new \WP_REST_Response( array( 'success' => true, 'data' => $res ), 200 );
	}

	/**
	 * Maps a sync WP_Error to user-facing "what happened" and "recommended action".
	 *
	 * @param \WP_Error $error
	 * @return array{what_happened:string,recommendation:string,recommendation_key:string}
	 */
	private function enrich_sync_error( \WP_Error $error ): array {
		$code    = $error->get_error_code();
		$message = (string) $error->get_error_message();
		$msg_lower = strtolower( $message );

		$default = array(
			'what_happened'      => __( 'The import failed.', 'seotune-search-insights' ),
			'recommendation'     => __( 'Try a shorter time range (e.g. 3 or 7 days) or use Import range (background). If the problem persists, check the Import diagnostics section.', 'seotune-search-insights' ),
			'recommendation_key' => 'generic',
		);

		if ( 'serpiq_sync_locked' === $code ) {
			return array(
				'what_happened'      => __( 'Another sync is already running.', 'seotune-search-insights' ),
				'recommendation'     => __( 'Wait a few minutes and try again, or use Import range (background).', 'seotune-search-insights' ),
				'recommendation_key' => 'retry_later',
			);
		}

		if ( 'serpiq_gsc_query_failed' === $code ) {
			if ( strpos( $msg_lower, 'quota' ) !== false || strpos( $msg_lower, 'rate limit' ) !== false || strpos( $msg_lower, 'ratelimit' ) !== false ) {
				return array(
					'what_happened'      => __( 'Google has limited the request (quota or rate limit).', 'seotune-search-insights' ),
					'recommendation'     => __( 'Use a shorter range (e.g. 3 or 7 days) or use Import range (background), which spreads requests over time.', 'seotune-search-insights' ),
					'recommendation_key' => 'use_background_import',
				);
			}
			return array(
				'what_happened'      => __( 'The Search Console request failed.', 'seotune-search-insights' ),
				'recommendation'     => __( 'Check the connection in the Google Search Console tab, then try a shorter range or use Import range (background).', 'seotune-search-insights' ),
				'recommendation_key' => 'check_connection',
			);
		}

		if ( 'serpiq_sync_failed' === $code || 'serpiq_missing_searchanalytics' === $code || 'serpiq_missing_query_request' === $code ) {
			if ( strpos( $msg_lower, 'timeout' ) !== false || strpos( $msg_lower, 'maximum execution time' ) !== false || strpos( $msg_lower, 'max_execution_time' ) !== false ) {
				return array(
					'what_happened'      => __( 'The request took too long and was interrupted.', 'seotune-search-insights' ),
					'recommendation'     => __( 'Use a shorter range (e.g. 3 or 7 days) or use Import range (background).', 'seotune-search-insights' ),
					'recommendation_key' => 'use_background_import',
				);
			}
			if ( strpos( $msg_lower, 'memory' ) !== false || strpos( $msg_lower, 'out of memory' ) !== false ) {
				return array(
					'what_happened'      => __( 'The server ran out of memory during the import.', 'seotune-search-insights' ),
					'recommendation'     => __( 'Use a shorter range (e.g. 3 or 7 days) or use Import range (background). If possible, ask your host to increase the PHP memory_limit.', 'seotune-search-insights' ),
					'recommendation_key' => 'use_background_import',
				);
			}
		}

		return $default;
	}
}

