<?php

namespace AIPT\Api\BulkGenerator\Desc\Controllers;

use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use AIPT\Api\BulkGenerator\Desc\ContentGenerator;
use AIPT\Api\BulkGenerator\Desc\Services\ProductFilterService;
use AIPT\Utils\ProductFilter\ProductFilterBuilder;
use AIPT\Utils\ProductFilter\ProductFilterMapper;
use AIPT\Core\FsManager;

require_once AIPT_PLUGIN_DIR . 'src/Core/CreditSystem/index.php';
use AIPT\Core\CreditSystem\CreditManager;

class GenerationController extends BaseController {

	private ContentGenerator $generator;
	private ProductFilterService $productFilterService;

	public function __construct( ?ContentGenerator $generator = null, ?ProductFilterService $productFilterService = null ) {
		$this->generator = $generator ?? new ContentGenerator();
		$this->productFilterService = $productFilterService ?? new ProductFilterService();
		\AIPT\Core\CreditSystem\setupCreditSystem();
	}

	public function register_routes(): void {
		register_rest_route(
			self::REST_NAMESPACE,
			'/products',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_products' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => $this->get_product_args(),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/categories',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_categories' ),
				'permission_callback' => array( $this, 'check_permissions' ),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/tags',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_tags' ),
				'permission_callback' => array( $this, 'check_permissions' ),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE . '/description-generator',
			'/generate',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'generate_single' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE . '/description-generator',
			'/bulk-generate',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'bulk_generate' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
			)
		);
	}

	public function get_products( WP_REST_Request $request ): WP_REST_Response {
		try {
			$response = $this->productFilterService->fetchFilteredProducts( (array) $request->get_params() );
			return new WP_REST_Response( $response, 200 );

		} catch ( \Throwable $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			}

			return new WP_REST_Response(
				array(
					'success'    => false,
					'products'   => array(),
					'total'      => 0,
					'totalPages' => 0,
					'page'       => absint( $request->get_param( 'page' ) ?: 1 ),
					'perPage'    => absint( $request->get_param( 'per_page' ) ?: 10 ),
					'error'      => 'An error occurred while fetching products.',
				),
				200
			);
		}
	}

	public function get_categories(): WP_REST_Response {
		try {
			$categories = ProductFilterMapper::getCategories();
			return new WP_REST_Response( $categories, 200 );

		} catch ( \Throwable $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			}
			return new WP_REST_Response( array(), 200 );
		}
	}

	public function get_tags(): WP_REST_Response {
		try {
			$tags = ProductFilterMapper::getTags();
			return new WP_REST_Response( $tags, 200 );

		} catch ( \Throwable $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			}
			return new WP_REST_Response( array(), 200 );
		}
	}

	public function generate_single( WP_REST_Request $request ) {
		$data       = $request->get_json_params();
		$product_id = absint( $data['productId'] ?? 0 );
		$options    = $this->sanitize_generation_options( $data['options'] ?? array() );

		if ( ! $product_id ) {
			return $this->error_response( 'invalid_product', __( 'Invalid product ID', 'ai-product-tools' ), 400 );
		}

		$content_types = $this->extract_content_types( $options );
		if ( empty( $content_types ) ) {
			return $this->error_response( 'no_content_types', __( 'No content types selected', 'ai-product-tools' ), 400 );
		}

		$credit_result = $this->validate_credits( 1, $content_types, $options );
		if ( is_wp_error( $credit_result ) ) {
			return $credit_result;
		}

		$result = $this->generator->generateForProduct( $product_id, $content_types, $options );

		if ( ! $result->success ) {
			$error_msg = ! empty( $result->errors ) ? implode( ', ', $result->errors ) : __( 'Generation failed', 'ai-product-tools' );
			return $this->error_response( 'generation_failed', $error_msg, 500 );
		}

		$this->deduct_credits( $credit_result, $content_types );

		return $this->success_response(
			array(
				'product_id'      => $product_id,
				'content'         => $result->content,
				'current_balance' => $this->get_current_balance(),
			),
			__( 'Content generated successfully', 'ai-product-tools' )
		);
	}

	public function bulk_generate( WP_REST_Request $request ) {
		$rate_check = $this->checkRateLimit( (int) get_current_user_id(), 'desc' );

		if ( ! $rate_check['allowed'] ) {
			return $this->rateLimitResponse( $rate_check );
		}

		$data        = $request->get_json_params();
		$product_ids = array_filter( array_map( 'absint', $data['productIds'] ?? array() ) );
		$options     = $this->sanitize_generation_options( $data['options'] ?? array() );

		if ( empty( $product_ids ) ) {
			return $this->error_response( 'no_products', __( 'No products selected', 'ai-product-tools' ), 400 );
		}

		$content_types = $this->extract_content_types( $options );
		if ( empty( $content_types ) ) {
			return $this->error_response( 'no_content_types', __( 'No content types selected', 'ai-product-tools' ), 400 );
		}

		$credit_result = $this->validate_credits( count( $product_ids ), $content_types, $options );
		if ( is_wp_error( $credit_result ) ) {
			return $credit_result;
		}

		$result = $this->generator->generate( $product_ids, $content_types, $options );

		$this->deduct_credits( $credit_result, $content_types, $result->successCount );

		$formatted_results = $this->format_bulk_results( $result );

		return new WP_REST_Response(
			array(
				'success'         => true,
				'results'         => $formatted_results,
				'summary'         => array(
					'total'          => count( $product_ids ),
					'successful'     => $result->successCount,
					'failed'         => $result->failureCount,
					'processingTime' => round( $result->processingTime, 2 ),
				),
				'current_balance' => $this->get_current_balance(),
			),
			200
		);
	}

	private function validate_credits( int $product_count, array $content_types, array $options ) {
		$credit     = CreditManager::getInstance();
		$fs_manager = FsManager::getInstance();
		$plan_type  = $fs_manager->getPlanType();

		$descriptions_per_product = count( $content_types );
		if ( ! empty( $options['improveExistingDescription'] ) ) {
			$descriptions_per_product *= 2;
		}

		$total_descriptions = $product_count * $descriptions_per_product;
		$result             = $credit->check( 'description', $total_descriptions );

		if ( 'business' === $plan_type || PHP_INT_MAX === $result->remaining ) {
			return array(
				'plan_type'                => $plan_type,
				'total_descriptions'       => $total_descriptions,
				'descriptions_per_product' => $descriptions_per_product,
				'has_enough'               => true,
				'cost_per_item'            => 0,
				'total_cost'               => 0,
				'is_unlimited'             => true,
			);
		}

		if ( ! $result->allowed ) {
			return new WP_Error(
				'insufficient_credits',
				sprintf(
					/* translators: 1: required optimization requests, 2: available optimization requests */
					__( 'Not enough optimization requests. Required: %1$d, Available: %2$d', 'ai-product-tools' ),
					$result->cost,
					$result->remaining
				),
				array( 'status' => 403 )
			);
		}

		$costs = $credit->getCosts();

		return array(
			'plan_type'                => $plan_type,
			'total_descriptions'       => $total_descriptions,
			'descriptions_per_product' => $descriptions_per_product,
			'has_enough'               => true,
			'cost_per_item'            => $costs['description'] ?? 1,
			'total_cost'               => $result->cost,
			'is_unlimited'             => false,
		);
	}

	private function deduct_credits( array $credit_result, array $content_types, int $success_count = 1 ): void {
		if ( $credit_result['is_unlimited'] || 'business' === $credit_result['plan_type'] ) {
			return;
		}

		$credit            = CreditManager::getInstance();
		$items_per_product = $credit_result['descriptions_per_product'] ?? count( $content_types );
		$total_to_deduct   = $success_count * $items_per_product;

		$credit->use( 'description', $total_to_deduct );
	}

	private function get_current_balance(): array {
		$credit  = CreditManager::getInstance();
		$balance = $credit->getBalance();

		return array(
			'total'        => $balance['total'] ?? 0,
			'used'         => $balance['used'] ?? 0,
			'available'    => $balance['available'] ?? 0,
			'is_unlimited' => $balance['is_unlimited'] ?? false,
		);
	}

	private function format_bulk_results( $result ): array {
		$formatted = array();

		foreach ( $result->results as $product_id => $product_result ) {
			$item = array(
				'product_id' => $product_id,
				'success'    => $product_result->success,
			);

			if ( $product_result->success ) {
				foreach ( $product_result->content as $type => $text ) {
					$db_type     = $this->map_type_to_db( $type );
					$formatted[] = array_merge(
						$item,
						array(
							'type'   => $db_type,
							'text'   => $text,
							'status' => 'pending',
						)
					);
				}
			} else {
				$formatted[] = array_merge(
					$item,
					array(
						'error' => $product_result->errors,
					)
				);
			}
		}

		return $formatted;
	}

	private function map_type_to_db( string $type ): string {
		$mapping = array(
			'short_description' => 'short',
			'description'       => 'full',
			'tags'              => 'tags',
		);

		return $mapping[ $type ] ?? $type;
	}

	private function get_product_args(): array {
		return array(
			'search'            => array(
				'type'              => 'string',
				'required'          => false,
				'sanitize_callback' => 'sanitize_text_field',
			),
			'category'          => array(
				'type'              => 'string',
				'required'          => false,
				'sanitize_callback' => 'sanitize_text_field',
			),
			'tag'               => array(
				'type'              => 'string',
				'required'          => false,
				'sanitize_callback' => 'sanitize_text_field',
			),
			'status'            => array(
				'type'              => 'string',
				'required'          => false,
				'sanitize_callback' => 'sanitize_text_field',
			),
			'stock_status'      => array(
				'type'              => 'string',
				'required'          => false,
				'enum'              => array( 'instock', 'outofstock', 'onbackorder' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
			'descriptionFilter' => array(
				'type'              => 'string',
				'required'          => false,
				'enum'              => array( 'with_both', 'with_full', 'with_short', 'without_both', 'without_full', 'without_short', 'with_tags', 'without_tags' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
			'product_type'      => array(
				'type'              => 'string',
				'required'          => false,
				'enum'              => array( 'simple', 'variable', 'grouped', 'external' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
			'featured'          => array(
				'type'     => 'boolean',
				'required' => false,
			),
			'on_sale'           => array(
				'type'     => 'boolean',
				'required' => false,
			),
			'price_min'         => array(
				'type'              => 'number',
				'required'          => false,
				'sanitize_callback' => 'floatval',
			),
			'price_max'         => array(
				'type'              => 'number',
				'required'          => false,
				'sanitize_callback' => 'floatval',
			),
			'date_after'        => array(
				'type'              => 'string',
				'required'          => false,
				'sanitize_callback' => 'sanitize_text_field',
			),
			'date_before'       => array(
				'type'              => 'string',
				'required'          => false,
				'sanitize_callback' => 'sanitize_text_field',
			),
			'filter_logic'      => array(
				'type'              => 'string',
				'required'          => false,
				'default'           => 'and',
				'enum'              => array( 'and', 'or' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
			'has_image'         => array(
				'type'     => 'boolean',
				'required' => false,
			),
			'has_gallery'       => array(
				'type'     => 'boolean',
				'required' => false,
			),
			'sku_status'        => array(
				'type'              => 'string',
				'required'          => false,
				'enum'              => array( 'has_sku', 'no_sku' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
			'stock_qty_min'     => array(
				'type'              => 'integer',
				'required'          => false,
				'sanitize_callback' => 'absint',
			),
			'stock_qty_max'     => array(
				'type'              => 'integer',
				'required'          => false,
				'sanitize_callback' => 'absint',
			),
			'page'              => array(
				'type'              => 'integer',
				'required'          => false,
				'default'           => 1,
				'sanitize_callback' => 'absint',
			),
			'per_page'          => array(
				'type'              => 'integer',
				'required'          => false,
				'default'           => 10,
				'minimum'           => 1,
				'maximum'           => 500,
				'sanitize_callback' => 'absint',
			),
			'orderby'           => array(
				'type'              => 'string',
				'required'          => false,
				'default'           => 'date',
				'sanitize_callback' => 'sanitize_text_field',
			),
			'order'             => array(
				'type'              => 'string',
				'required'          => false,
				'default'           => 'DESC',
				'enum'              => array( 'ASC', 'DESC' ),
				'sanitize_callback' => 'sanitize_text_field',
			),
		);
	}
}
