<?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_Universal {

	private $login;
	private $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;
	}

	/**
	 * Generate a unique cache key for API requests
	 *
	 * @param string $method Method name
	 * @param array  $params Parameters for the API call
	 * @return string Cache key
	 */
	private function generate_cache_key( $method, $params ) {
		return 'wisewand_dataforseo_' . md5( $method . '_' . wp_json_encode( $params ) );
	}

	/**
	 * Get cached data or fetch from API
	 *
	 * @param string   $cache_key   Cache key
	 * @param callable $callback    Function to call if cache miss
	 * @param int      $expiration  Cache expiration in seconds (default: 1 hour)
	 * @return mixed                Cached or fresh data
	 */
	private function get_cached_or_fetch( $cache_key, $callback, $expiration = 3600 ) {
		// Try to get cached data
		$cached_data = get_transient( $cache_key );

		if ( $cached_data !== false ) {
			if ( $this->logger ) {
				$this->logger->debug( 'DataForSEO cache hit', array( 'cache_key' => $cache_key ) );
			}
			return $cached_data;
		}

		// Cache miss - fetch fresh data
		if ( $this->logger ) {
			$this->logger->debug( 'DataForSEO cache miss', array( 'cache_key' => $cache_key ) );
		}

		$data = $callback();

		// Only cache successful responses
		if ( ! is_wp_error( $data ) ) {
			set_transient( $cache_key, $data, $expiration );
		}

		return $data;
	}

	/**
	 * Auto-detect best location and language for any website
	 */
	private function detect_site_settings( $domain ) {
		// Get WordPress locale
		$wp_locale = get_locale();

		// Smart location/language detection based on domain and WP settings
		$location_mapping = array(
			'fr_FR' => array(
				'location' => 2250,
				'language' => 'fr',
			), // France
			'en_US' => array(
				'location' => 2840,
				'language' => 'en',
			), // United States
			'en_GB' => array(
				'location' => 2826,
				'language' => 'en',
			), // United Kingdom
			'de_DE' => array(
				'location' => 2276,
				'language' => 'de',
			), // Germany
			'es_ES' => array(
				'location' => 2724,
				'language' => 'es',
			), // Spain
			'it_IT' => array(
				'location' => 2380,
				'language' => 'it',
			), // Italy
		);

		// Check if we have mapping for current locale
		if ( isset( $location_mapping[ $wp_locale ] ) ) {
			return $location_mapping[ $wp_locale ];
		}

		// Check domain TLD for hints
		if ( preg_match( '/\.fr$/i', $domain ) ) {
			return array(
				'location' => 2250,
				'language' => 'fr',
			);
		} elseif ( preg_match( '/\.de$/i', $domain ) ) {
			return array(
				'location' => 2276,
				'language' => 'de',
			);
		} elseif ( preg_match( '/\.es$/i', $domain ) ) {
			return array(
				'location' => 2724,
				'language' => 'es',
			);
		} elseif ( preg_match( '/\.it$/i', $domain ) ) {
			return array(
				'location' => 2380,
				'language' => 'it',
			);
		}

		// Default to US/English for maximum data availability
		return array(
			'location' => 2840,
			'language' => 'en',
		);
	}

	/**
	 * Get domain overview with automatic location detection
	 */
	public function get_domain_overview( $domain ) {
		$settings = $this->detect_site_settings( $domain );

		$data = array(
			array(
				'target'        => $domain,
				'location_code' => $settings['location'],
				'language_code' => $settings['language'],
			),
		);

		// Generate cache key based on domain and settings
		$cache_key = $this->generate_cache_key(
			'domain_overview',
			array(
				'domain'   => $domain,
				'location' => $settings['location'],
				'language' => $settings['language'],
			)
		);

		// Use cached data or fetch from API (cache for 24 hours - domain overview changes slowly)
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $domain, $settings, $data ) {
				if ( $this->logger ) {
					$this->logger->info(
						'DataForSEO domain overview request',
						array(
							'domain'        => $domain,
							'location_code' => $settings['location'],
							'language_code' => $settings['language'],
							'wp_locale'     => get_locale(),
						)
					);
				}

				return $this->request( 'POST', '/dataforseo_labs/google/domain_rank_overview/live', $data );
			},
			DAY_IN_SECONDS
		); // Cache for 24 hours
	}

	/**
	 * Get domain keywords with automatic settings
	 */
	public function get_domain_keywords( $domain, $limit = 100 ) {
		$settings = $this->detect_site_settings( $domain );

		$data = array(
			array(
				'target'        => $domain,
				'location_code' => $settings['location'],
				'language_code' => $settings['language'],
				'limit'         => $limit,
			),
		);

		// Generate cache key
		$cache_key = $this->generate_cache_key(
			'domain_keywords',
			array(
				'domain'   => $domain,
				'location' => $settings['location'],
				'language' => $settings['language'],
				'limit'    => $limit,
			)
		);

		// Cache for 12 hours - keyword rankings change gradually
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $data ) {
				return $this->request( 'POST', '/dataforseo_labs/google/ranked_keywords/live', $data );
			},
			12 * HOUR_IN_SECONDS
		);
	}

	/**
	 * Get keyword ideas - comprehensive keyword suggestions for seed keywords
	 */
	public function get_keyword_ideas( $seed_keywords, $language_code, $location_code, $limit = 100 ) {
		if ( is_string( $seed_keywords ) ) {
			$seed_keywords = array( $seed_keywords );
		}

		// Limit to manageable number per seed
		$safe_limit = min( $limit, 20 );

		$data = array(
			array(
				'keywords'             => $seed_keywords,
				'location_code'        => $location_code,
				'language_code'        => $language_code,
				'include_seed_keyword' => true,
				'include_serp_info'    => true,
				'limit'                => $safe_limit,
			),
		);

		// Generate cache key
		$cache_key = $this->generate_cache_key(
			'keyword_ideas',
			array(
				'keywords' => $seed_keywords,
				'location' => $location_code,
				'language' => $language_code,
				'limit'    => $safe_limit,
			)
		);

		// Cache for 7 days - keyword ideas are very stable
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $seed_keywords, $location_code, $language_code, $limit, $data ) {
				if ( $this->logger ) {
					$this->logger->info(
						'DataForSEO keyword_ideas request',
						array(
							'endpoint'      => '/dataforseo_labs/google/keyword_ideas/live',
							'seed_keywords' => $seed_keywords,
							'location_code' => $location_code,
							'language_code' => $language_code,
							'limit'         => $limit,
							'full_payload'  => wp_json_encode( $data ),
						)
					);
				}

				// Revert to keyword_ideas - it works for getting suggestions (we'll enrich separately)
				$response = $this->request( 'POST', '/dataforseo_labs/google/keyword_ideas/live', $data );

				if ( $this->logger ) {
					$this->logger->debug(
						'DataForSEO keyword_ideas response received',
						array(
							'is_error'          => is_wp_error( $response ),
							'response_type'     => gettype( $response ),
							'has_tasks'         => is_array( $response ) && isset( $response[0] ),
							'task_count'        => is_array( $response ) ? count( $response ) : 0,
							'first_task_status' => isset( $response[0]['status_message'] ) ? $response[0]['status_message'] : 'n/a',
							'first_task_keys'   => isset( $response[0] ) ? array_keys( $response[0] ) : array(),
							'result_available'  => isset( $response[0]['result'] ) ? 'yes' : 'no',
						)
					);
				}

				return $response;
			},
			7 * DAY_IN_SECONDS
		);
	}

	/**
	 * Get keywords for site - discover new keyword opportunities
	 */
	public function get_keywords_for_site( $domain, $language_code, $location_code, $limit = 100 ) {
		$clean_domain = preg_replace( '/^www\./i', '', $domain );

		$data = array(
			array(
				'target'             => $clean_domain,
				'location_code'      => $location_code,
				'language_code'      => $language_code,
				'limit'              => $limit,
				'include_subdomains' => false,
			),
		);

		// Generate cache key
		$cache_key = $this->generate_cache_key(
			'keywords_for_site',
			array(
				'domain'   => $clean_domain,
				'location' => $location_code,
				'language' => $language_code,
				'limit'    => $limit,
			)
		);

		// Cache for 12 hours - site keywords change gradually
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $clean_domain, $location_code, $language_code, $limit, $data ) {
				if ( $this->logger ) {
					$this->logger->info(
						'DataForSEO keywords_for_site request',
						array(
							'domain'        => $clean_domain,
							'location_code' => $location_code,
							'language_code' => $language_code,
							'limit'         => $limit,
						)
					);
				}

				return $this->request( 'POST', '/dataforseo_labs/google/keywords_for_site/live', $data );
			},
			12 * HOUR_IN_SECONDS
		);
	}

	/**
	 * Get competitors with automatic settings
	 */
	public function get_top_competitors( $domain, $limit = 10 ) {
		$settings = $this->detect_site_settings( $domain );

		$data = array(
			array(
				'target'        => $domain,
				'location_code' => $settings['location'],
				'language_code' => $settings['language'],
				'limit'         => $limit,
				'order_by'      => array( 'intersections', 'desc' ),
			),
		);

		// Generate cache key
		$cache_key = $this->generate_cache_key(
			'top_competitors',
			array(
				'domain'   => $domain,
				'location' => $settings['location'],
				'language' => $settings['language'],
				'limit'    => $limit,
			)
		);

		// Cache for 3 days - competitor landscape changes slowly
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $data ) {
				return $this->request( 'POST', '/dataforseo_labs/google/domain_intersection/live', $data );
			},
			3 * DAY_IN_SECONDS
		);
	}

	/**
	 * Process domain metrics with correct DataForSEO structure
	 */
	public function process_domain_metrics_safe( $overview_data ) {
		$task   = $overview_data[0] ?? array();
		$result = $task['result'][0] ?? array();
		$items  = $result['items'] ?? array();

		if ( $this->logger ) {
			$this->logger->info(
				'Processing DataForSEO domain metrics',
				array(
					'task_status'     => $task['status_message'] ?? 'unknown',
					'result_keys'     => array_keys( $result ),
					'items_count'     => count( $items ),
					'first_item_keys' => ! empty( $items[0] ) ? array_keys( $items[0] ) : array(),
				)
			);
		}

		// Check if we have any items
		if ( empty( $items ) ) {
			return array(
				'domain_rank'      => 0,
				'organic_keywords' => 0,
				'organic_traffic'  => 0,
				'organic_cost'     => 0,
				'domain'           => $result['target'] ?? '',
				'data_available'   => false,
				'message'          => __( 'No ranking data available in DataForSEO for this domain.', 'wisewand-ai-content-writer-seo-content-generator' ),
			);
		}

		// Get metrics from first item
		$item    = $items[0] ?? array();
		$metrics = $item['metrics']['organic'] ?? array();

		if ( empty( $metrics ) ) {
			return array(
				'domain_rank'      => 0,
				'organic_keywords' => 0,
				'organic_traffic'  => 0,
				'organic_cost'     => 0,
				'domain'           => $result['target'] ?? '',
				'data_available'   => false,
				'message'          => __( 'No organic metrics available for this domain.', 'wisewand-ai-content-writer-seo-content-generator' ),
			);
		}

		// Process real metrics
		return array(
			'domain_rank'           => $metrics['count'] ?? 0,
			'organic_keywords'      => $metrics['count'] ?? 0,
			'organic_traffic'       => round( $metrics['etv'] ?? 0 ),
			'organic_cost'          => round( $metrics['estimated_paid_traffic_cost'] ?? 0, 2 ),
			'domain'                => $result['target'] ?? '',
			'data_available'        => $metrics['count'] > 0,
			'top_positions'         => ( $metrics['pos_1'] ?? 0 ) + ( $metrics['pos_2_3'] ?? 0 ),
			'position_distribution' => array(
				'pos_1'     => $metrics['pos_1'] ?? 0,
				'pos_2_3'   => $metrics['pos_2_3'] ?? 0,
				'pos_4_10'  => $metrics['pos_4_10'] ?? 0,
				'pos_11_20' => $metrics['pos_11_20'] ?? 0,
				'pos_21_30' => $metrics['pos_21_30'] ?? 0,
			),
			'keyword_movements'     => array(
				'new'  => $metrics['is_new'] ?? 0,
				'up'   => $metrics['is_up'] ?? 0,
				'down' => $metrics['is_down'] ?? 0,
				'lost' => $metrics['is_lost'] ?? 0,
			),
		);
	}

	/**
	 * Process keyword opportunities with fallback
	 */
	public function process_keyword_opportunities_safe( $keywords_data, $domain ) {
		$task = $keywords_data[0] ?? array();

		if ( $task['status_code'] !== 20000 ) {
			// API error - provide helpful message
			return array(
				'opportunities' => array(),
				'error'         => $task['status_message'] ?? 'Unknown API error',
				'suggestions'   => $this->generate_generic_suggestions( $domain ),
			);
		}

		$result = $task['result'][0] ?? array();
		$items  = $result['items'] ?? array();

		if ( empty( $items ) ) {
			// No keyword data - suggest generic content based on domain
			return array(
				'opportunities' => array(),
				'error'         => null,
				'suggestions'   => $this->generate_generic_suggestions( $domain ),
				'message'       => __( 'No specific keyword data available. Here are content suggestions based on your domain.', 'wisewand-ai-content-writer-seo-content-generator' ),
			);
		}

		$opportunities = array();
		foreach ( $items as $item ) {
			$keyword       = $item['keyword'] ?? '';
			$rank_info     = $item['ranked_serp_element']['serp_item'] ?? array();
			$rank          = $rank_info['rank_group'] ?? $rank_info['rank_absolute'] ?? 999;
			$keyword_info  = $item['keyword_info'] ?? array();
			$search_volume = $keyword_info['search_volume'] ?? 0;

			// Look for improvement opportunities (ranking 11-50)
			if ( $rank >= 11 && $rank <= 50 && $search_volume > 100 ) {
				$content_type = $this->smart_content_type_detection( $keyword, $domain );

				$opportunities[] = array(
					'keyword'           => $keyword,
					'current_rank'      => $rank,
					'search_volume'     => $search_volume,
					'content_type'      => $content_type,
					'wisewand_url'      => $this->get_wisewand_url( $content_type ),
					'opportunity_score' => $this->calculate_opportunity_score( $rank, $search_volume ),
				);
			}
		}

		// Sort by opportunity score
		usort(
			$opportunities,
			function ( $a, $b ) {
				return $b['opportunity_score'] - $a['opportunity_score'];
			}
		);

		return array(
			'opportunities'  => array_slice( $opportunities, 0, 10 ),
			'error'          => null,
			'total_keywords' => count( $items ),
		);
	}

	/**
	 * NO FAKE SUGGESTIONS - Only use real DataForSEO data
	 * If no data available, return empty array and let UI handle it properly
	 */
	private function generate_generic_suggestions( $domain ) {
		// DO NOT generate fake suggestions
		// Only return real data from DataForSEO API
		return array();
	}

	/**
	 * Smart content type detection based on keyword and domain context
	 */
	private function smart_content_type_detection( $keyword, $domain ) {
		$keyword_lower = strtolower( $keyword );
		$domain_lower  = strtolower( $domain );

		// Commercial intent keywords
		if ( preg_match( '/\b(best|top|review|compare|buy|price|cost)\b/', $keyword_lower ) ) {
			return 'affiliate';
		}

		// Category/collection keywords
		if ( preg_match( '/\b(category|categories|types|collection|list|library)\b/', $keyword_lower ) ) {
			return 'category';
		}

		// Product-specific keywords
		if ( preg_match( '/\b(product|item|tool|app|software|service)\b/', $keyword_lower ) ) {
			return 'product';
		}

		// Default to blog content
		return 'blog';
	}

	/**
	 * Get appropriate Wisewand URL for content type
	 */
	private function get_wisewand_url( $content_type ) {
		$urls = array(
			'blog'      => 'https://app.wisewand.ai/articles/blog',
			'affiliate' => 'https://app.wisewand.ai/articles/affiliation',
			'category'  => 'https://app.wisewand.ai/e-commerce/category-page',
			'product'   => 'https://app.wisewand.ai/e-commerce/product-page',
		);

		return $urls[ $content_type ] ?? $urls['blog'];
	}

	private function calculate_opportunity_score( $rank, $search_volume ) {
		$rank_score   = max( 0, 60 - $rank );
		$volume_score = min( $search_volume / 100, 40 );
		return round( $rank_score + $volume_score );
	}

	/**
	 * Make HTTP request to DataForSEO API with proper error handling
	 */
	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',
			),
		);

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

		if ( $this->logger ) {
			$this->logger->debug(
				'DataForSEO Universal API request',
				array(
					'endpoint'      => $endpoint,
					'domain'        => $data[0]['target'] ?? 'unknown',
					'location_code' => $data[0]['location_code'] ?? 'auto',
					'language_code' => $data[0]['language_code'] ?? 'auto',
				)
			);
		}

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

		if ( is_wp_error( $response ) ) {
			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';

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

		$data = json_decode( $response_body, true );

		if ( json_last_error() !== JSON_ERROR_NONE ) {
			return new WP_Error( 'dataforseo_invalid_json', 'Invalid JSON response' );
		}

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

	/**
	 * Store credentials using WordPress options
	 */
	public static function store_credentials( $login, $password ) {
		update_option( 'wisewand_dataforseo_login', $login );
		update_option( 'wisewand_dataforseo_password', $password );

		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', '' ),
		);
	}

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

	/**
	 * Test connection with current domain
	 */
	public function test_connection_for_domain( $domain ) {
		$settings = $this->detect_site_settings( $domain );

		$test_data = array(
			array(
				'target'        => $domain,
				'location_code' => $settings['location'],
				'language_code' => $settings['language'],
			),
		);

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

		return $response;
	}

	/**
	 * Get ranked keywords for a domain (Competitor Spy)
	 */
	public function get_ranked_keywords( $domain, $language_code, $location_code, $limit = 500, $filters = array() ) {
		$payload = array(
			array(
				'target'             => $domain,
				'language_code'      => $language_code,
				'location_code'      => $location_code,
				'limit'              => $limit,
				'load_rank_absolute' => true,
				'item_types'         => array( 'organic' ),
				'include_serp_info'  => true,
			),
		);

		if ( ! empty( $filters ) ) {
			$payload[0]['filters'] = $filters;
		}

		// Generate cache key
		$cache_key = $this->generate_cache_key(
			'ranked_keywords',
			array(
				'domain'   => $domain,
				'language' => $language_code,
				'location' => $location_code,
				'limit'    => $limit,
				'filters'  => $filters,
			)
		);

		// Cache for 12 hours - keyword rankings change gradually
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $payload ) {
				return $this->request( 'POST', '/dataforseo_labs/google/ranked_keywords/live', $payload );
			},
			12 * HOUR_IN_SECONDS
		);
	}

	/**
	 * Get domain intersection (keyword gaps)
	 */
	public function get_domain_intersection( $target1, $target2, $language_code, $location_code, $intersections = false, $limit = 500, $filters = array() ) {
		$payload = array(
			array(
				'target1'           => $target1,
				'target2'           => $target2,
				'language_code'     => $language_code,
				'location_code'     => $location_code,
				'intersections'     => $intersections,
				'limit'             => $limit,
				'include_serp_info' => true,
			),
		);

		if ( ! empty( $filters ) ) {
			$payload[0]['filters'] = $filters;
		}

		// Generate cache key
		$cache_key = $this->generate_cache_key(
			'domain_intersection',
			array(
				'target1'       => $target1,
				'target2'       => $target2,
				'language'      => $language_code,
				'location'      => $location_code,
				'intersections' => $intersections,
				'limit'         => $limit,
				'filters'       => $filters,
			)
		);

		// Cache for 3 days - domain overlap changes slowly
		return $this->get_cached_or_fetch(
			$cache_key,
			function () use ( $payload ) {
				return $this->request( 'POST', '/dataforseo_labs/google/domain_intersection/live', $payload );
			},
			3 * DAY_IN_SECONDS
		);
	}

	/**
	 * Discover competitor domains (simplified approach using ranked keywords)
	 */
	public function discover_competitors( $user_domain, $language_code, $location_code, $limit = 5 ) {
		// Get user's top keywords first
		$user_keywords_response = $this->get_ranked_keywords( $user_domain, $language_code, $location_code, 10 );

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

		// Extract top keywords
		$task  = $user_keywords_response[0] ?? array();
		$items = $task['result'][0]['items'] ?? array();

		$top_keywords = array();
		foreach ( array_slice( $items, 0, 5 ) as $item ) {
			$keyword = $item['keyword_data']['keyword'] ?? '';
			if ( $keyword ) {
				$top_keywords[] = $keyword;
			}
		}

		if ( empty( $top_keywords ) ) {
			return new WP_Error( 'no_keywords', 'No keywords found for user domain' );
		}

		// For each top keyword, find competing domains
		// Note: This is a simplified approach. Full implementation would use SERP endpoint
		$competitors = array();

		// Placeholder: In production, fetch SERP for each keyword and extract domains
		// For now, return empty array - will be enhanced with SERP crawling

		return $competitors;
	}
}
