<?php
/**
 * This file is part of the Wisewand WordPress plugin.
 *
 * @package Wisewand
 * @since 1.0.0
 * @license GPL-2.0-or-later
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
namespace Wisewand\Utils;

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use WP_Error;

class DataForSEO_Client {

	public $login;
	public $password;
	private $base_url;
	private $logger;

	public function __construct( $login, $password, $logger = null ) {
		$this->login    = $login;
		$this->password = $password;
		$this->base_url = 'https://api.dataforseo.com/v3';
		$this->logger   = $logger;
	}

	/**
	 * Get domain overview and ranking data using correct DataForSEO endpoint
	 */
	public function get_domain_overview( $domain ) {
		$data = array(
			array(
				'target'        => $domain,
				'location_code' => 2840, // US location for better data availability
				'language_code' => 'en',  // English for tellmestories.ai
			),
		);

		return $this->request( 'POST', '/dataforseo_labs/google/domain_rank_overview/live', $data );
	}

	/**
	 * Get keywords ranking for domain using correct DataForSEO endpoint
	 */
	public function get_domain_keywords( $domain, $limit = 100 ) {
		$data = array(
			array(
				'target'        => $domain,
				'location_code' => 2840, // Switch to US for better data availability
				'language_code' => 'en',  // English for tellmestories.ai
				'limit'         => $limit,
				// Remove invalid order_by parameter
			),
		);

		return $this->request( 'POST', '/dataforseo_labs/google/ranked_keywords/live', $data );
	}

	/**
	 * Find keyword opportunities (keywords competitors rank for but you don't)
	 */
	public function get_keyword_opportunities( $domain, $competitors = array(), $limit = 50 ) {
		if ( empty( $competitors ) ) {
			return new WP_Error( 'no_competitors', 'At least one competitor domain is required' );
		}

		$data = array(
			array(
				'target'        => $domain,
				'competitors'   => array_slice( $competitors, 0, 5 ), // Max 5 competitors
				'location_name' => 'France',
				'language_name' => 'French',
				'limit'         => $limit,
				'filters'       => array(
					array( 'target_rank', '=', null ), // Keywords we don't rank for
					array( 'avg_competitors_rank', '<=', 10 ), // But competitors rank in top 10
				),
			),
		);

		return $this->request( 'POST', '/dataforseo_labs/google/competitors_domain/live', $data );
	}

	/**
	 * Track ranking changes over time
	 */
	public function get_ranking_changes( $domain, $days_back = 30 ) {
		$data = array(
			array(
				'target'        => $domain,
				'location_name' => 'France',
				'language_name' => 'French',
				'date_from'     => gmdate( 'Y-m-d', strtotime( "-{$days_back} days" ) ),
				'date_to'       => gmdate( 'Y-m-d' ),
			),
		);

		return $this->request( 'POST', '/dataforseo_labs/google/historical_rank_overview/live', $data );
	}

	/**
	 * Find declining keywords (losing positions)
	 */
	public function get_declining_keywords( $domain, $days_back = 30, $min_rank_drop = 5 ) {
		$keywords_data = $this->get_domain_keywords( $domain, 200 );

		if ( is_wp_error( $keywords_data ) ) {
			return $keywords_data;
		}

		// Filter for keywords that have dropped in rankings
		$declining = array();
		$keywords  = $keywords_data[0]['result'] ?? array();

		foreach ( $keywords as $keyword_data ) {
			$rank_info     = $keyword_data['rank_info'] ?? array();
			$current_rank  = $rank_info['rank'] ?? 999;
			$previous_rank = $rank_info['previous_rank'] ?? $current_rank;

			if ( $current_rank > $previous_rank + $min_rank_drop ) {
				$declining[] = array(
					'keyword'       => $keyword_data['keyword'],
					'current_rank'  => $current_rank,
					'previous_rank' => $previous_rank,
					'rank_drop'     => $current_rank - $previous_rank,
					'search_volume' => $keyword_data['search_volume'] ?? 0,
					'cpc'           => $keyword_data['cpc'] ?? 0,
				);
			}
		}

		// Sort by biggest drops first
		usort(
			$declining,
			function ( $a, $b ) {
				return $b['rank_drop'] - $a['rank_drop'];
			}
		);

		return array_slice( $declining, 0, 20 ); // Top 20 declining keywords
	}

	/**
	 * Get top competitors for the domain using correct endpoint
	 */
	public function get_top_competitors( $domain, $limit = 10 ) {
		$data = array(
			array(
				'target'        => $domain,
				'location_code' => 2250, // France
				'language_code' => 'fr',
				'limit'         => $limit,
				'order_by'      => array( 'intersections', 'desc' ),
			),
		);

		return $this->request( 'POST', '/dataforseo_labs/google/domain_intersection/live', $data );
	}

	/**
	 * Get content suggestions based on trending keywords
	 */
	public function get_content_suggestions( $domain, $niche_keywords = array() ) {
		$suggestions = array();

		// Get current domain keywords
		$domain_keywords = $this->get_domain_keywords( $domain, 50 );
		if ( is_wp_error( $domain_keywords ) ) {
			return $domain_keywords;
		}

		// Find related trending keywords
		foreach ( $niche_keywords as $seed_keyword ) {
			$related_data = $this->get_related_keywords( $seed_keyword );
			if ( ! is_wp_error( $related_data ) ) {
				$suggestions = array_merge( $suggestions, $this->extract_content_opportunities( $related_data ) );
			}
		}

		return array_slice( $suggestions, 0, 10 );
	}

	/**
	 * Get related keywords for content ideas
	 */
	public function get_related_keywords( $keyword, $limit = 20 ) {
		$data = array(
			array(
				'keyword'       => $keyword,
				'location_name' => 'France',
				'language_name' => 'French',
				'limit'         => $limit,
			),
		);

		return $this->request( 'POST', '/keywords_data/google_ads/keywords_for_keywords/live', $data );
	}

	/**
	 * Calculate SEO opportunity score for a keyword
	 */
	public function calculate_opportunity_score( $keyword_data ) {
		$search_volume = $keyword_data['search_volume'] ?? 0;
		$competition   = $keyword_data['competition'] ?? 1;
		$current_rank  = $keyword_data['current_rank'] ?? 999;

		// Higher score = better opportunity
		$volume_score      = min( $search_volume / 100, 100 ); // 0-100
		$competition_score = ( 1 - $competition ) * 100; // 0-100 (lower competition = higher score)
		$rank_score        = max( 0, 100 - $current_rank ); // 0-100 (better rank = higher score)

		return ( $volume_score + $competition_score + $rank_score ) / 3;
	}

	/**
	 * Make HTTP request to DataForSEO API
	 */
	public function request( $method, $endpoint, $data = null ) {
		$url = $this->base_url . $endpoint;

		$args = array(
			'method'  => $method,
			'timeout' => 60,
			'headers' => array(
				'Authorization' => 'Basic ' . base64_encode( $this->login . ':' . $this->password ),
				'Content-Type'  => 'application/json',
				'Accept'        => 'application/json',
				'User-Agent'    => 'Wisewand-plugin/' . WISEWAND_PLUGIN_VERSION,
			),
		);

		if ( $data !== null && in_array( $method, array( 'POST', 'PUT', 'PATCH' ) ) ) {
			$args['body'] = wp_json_encode( $data );
		}

		if ( $this->logger ) {
			$this->logger->debug(
				'DataForSEO API request',
				array(
					'method'       => $method,
					'endpoint'     => $endpoint,
					'url'          => $url,
					'has_data'     => $data !== null,
					'auth_header'  => substr( $args['headers']['Authorization'], 0, 15 ) . '...',
					'request_body' => $args['body'] ?? 'no_body',
				)
			);
		}

		$response = wp_remote_request( $url, $args );

		if ( is_wp_error( $response ) ) {
			if ( $this->logger ) {
				$this->logger->error(
					'DataForSEO API request failed',
					array(
						'error'    => $response->get_error_message(),
						'endpoint' => $endpoint,
					)
				);
			}
			return $response;
		}

		$response_code = wp_remote_retrieve_response_code( $response );
		$response_body = wp_remote_retrieve_body( $response );

		if ( $response_code >= 400 ) {
			$error_data    = json_decode( $response_body, true );
			$error_message = $error_data['error']['message'] ?? 'API request failed';

			if ( $this->logger ) {
				$this->logger->error(
					'DataForSEO API error',
					array(
						'status_code'   => $response_code,
						'error_message' => $error_message,
						'endpoint'      => $endpoint,
					)
				);
			}

			return new WP_Error( 'dataforseo_api_error', $error_message, array( 'status_code' => $response_code ) );
		}

		$data = json_decode( $response_body, true );

		if ( json_last_error() !== JSON_ERROR_NONE ) {
			if ( $this->logger ) {
				$this->logger->error(
					'DataForSEO API invalid JSON',
					array(
						'json_error' => json_last_error_msg(),
						'endpoint'   => $endpoint,
					)
				);
			}
			return new WP_Error( 'dataforseo_invalid_json', 'Invalid JSON response' );
		}

		return $data['tasks'] ?? $data;
	}

	/**
	 * Extract content opportunities from keyword data
	 */
	private function extract_content_opportunities( $keyword_data ) {
		$opportunities = array();
		$results       = $keyword_data[0]['result'] ?? array();

		foreach ( $results as $item ) {
			$keyword       = $item['keyword'] ?? '';
			$search_volume = $item['search_volume'] ?? 0;
			$competition   = $item['competition'] ?? 0;

			if ( $search_volume > 100 && $competition < 0.7 ) { // Good opportunity thresholds
				$opportunities[] = array(
					'keyword'            => $keyword,
					'search_volume'      => $search_volume,
					'competition'        => $competition,
					'opportunity_score'  => $this->calculate_opportunity_score( $item ),
					'content_suggestion' => $this->generate_content_suggestion( $keyword ),
				);
			}
		}

		return $opportunities;
	}

	/**
	 * Generate content suggestion based on keyword
	 */
	private function generate_content_suggestion( $keyword ) {
		// Simple content suggestion based on keyword
		$templates = array(
			'guide'      => 'Ultimate Guide to {keyword}',
			'tips'       => '10 Expert Tips for {keyword}',
			'comparison' => 'Best {keyword} Compared',
			'howto'      => 'How to Master {keyword}',
			'review'     => '{keyword} Review and Analysis',
		);

		$template_key = array_rand( $templates );
		return str_replace( '{keyword}', $keyword, $templates[ $template_key ] );
	}

	/**
	 * Store DataForSEO API credentials securely
	 */
	public static function store_credentials( $login, $password ) {
		update_option( 'wisewand_dataforseo_login', $login );
		update_option( 'wisewand_dataforseo_password', $password ); // In production, this should be encrypted

		do_action( 'wisewand_dataforseo_credentials_updated' );

		return true;
	}

	/**
	 * Get stored credentials
	 */
	public static function get_stored_credentials() {
		return array(
			'login'    => get_option( 'wisewand_dataforseo_login', '' ),
			'password' => get_option( 'wisewand_dataforseo_password', '' ),
		);
	}

	/**
	 * Test API connection with stored credentials
	 */
	public function test_connection() {
		$test_data = array(
			array(
				'target'        => 'example.com',
				'location_code' => 2840, // United States
				'language_code' => 'en',
				'limit'         => 1,
			),
		);

		$response = $this->request( 'POST', '/dataforseo_labs/google/domain_rank_overview/live', $test_data );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		// Check if response is valid
		$task   = $response[0] ?? array();
		$status = $task['status_message'] ?? '';

		if ( $this->logger ) {
			$this->logger->debug(
				'DataForSEO test connection response',
				array(
					'status'     => $status,
					'task_keys'  => array_keys( $task ),
					'has_result' => isset( $task['result'] ),
				)
			);
		}

		return $response;
	}

	/**
	 * Check if DataForSEO is configured
	 */
	public static function is_configured() {
		$credentials = self::get_stored_credentials();
		return ! empty( $credentials['login'] ) && ! empty( $credentials['password'] );
	}
}
