<?php

namespace Pixalia\ImageAssistant\Api;

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

use DOMDocument;
use Pixalia\ImageAssistant\Base\Const\MetaKeyConst;
use Pixalia\ImageAssistant\Base\Const\PixaliaConst;
use Pixalia\ImageAssistant\Repository\OptionRepository;
use Pixalia\ImageAssistant\Repository\PostRepository;
use Pixalia\ImageAssistant\Service\ImageAttacher;
use Pixalia\ImageAssistant\Service\ImageChecker;
use Pixalia\ImageAssistant\Service\MediaUploader;

/**
 * AjaxHandler Class
 */
class AjaxHandler {

	private PixaliaClient $client;
	private ImageAttacher $attacher;
	private ImageChecker $checker;
	private PostRepository $postRepository;
	private OptionRepository $optionRepository;
	private MediaUploader $uploader;

	public function __construct(
		PixaliaClient $client,
		ImageAttacher $attacher,
		ImageChecker $checker,
		PostRepository $postRepository,
		OptionRepository $optionRepository,
		MediaUploader $uploader
	) {
		$this->client           = $client;
		$this->attacher         = $attacher;
		$this->checker          = $checker;
		$this->postRepository   = $postRepository;
		$this->optionRepository = $optionRepository;
		$this->uploader         = $uploader;
	}

	/**
	 * AJAXアクションフックを登録します。
	 */
	public function register_hooks() {
		add_action( 'wp_ajax_pixalia_generate_image', [ $this, 'handle_generate_image' ] );
		add_action( 'wp_ajax_pixalia_save_api_key', [ $this, 'handle_save_api_key' ] );
		add_action( 'wp_ajax_pixalia_get_unchecked_count', [ $this, 'handleGetUncheckedCount' ] );
		add_action( 'wp_ajax_pixalia_bulk_check_posts', [ $this, 'handleBulkCheckPosts' ] );
		add_action( 'wp_ajax_pixalia_get_user_status', [ $this, 'handle_get_user_status' ] );

		add_action( 'wp_ajax_pixalia_check_task_status', [ $this, 'handle_check_task_status' ] );
		add_action( 'wp_ajax_pixalia_attach_image', [ $this, 'handle_attach_image' ] );
	}

	/**
	 * ユーザーのステータス（プラン・クレジット）を取得する
	 */
	public function handle_get_user_status() {
		check_ajax_referer( 'wp_rest', 'nonce' );

		// 権限チェック
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => '権限がありません。' ], 403 );
		}

		// 保存済みのAPIキーを使って問い合わせる
		// (PixaliaClient内部で get_option してくれます)
		$user_status = $this->client->get_user_status();

		if ( is_wp_error( $user_status ) ) {
			// APIキー未設定の場合や通信エラー
			wp_send_json_error( [ 'message' => $user_status->get_error_message() ] );
		}

		wp_send_json_success( [
			'plan_name' => $user_status['plan_name'] ?? 'Free',
			'credits'   => $user_status['credits'] ?? 0,
		] );
	}

	/**
	 * APIキー保存リクエストを処理します。
	 * @return void
	 */
	public function handle_save_api_key() {
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => __( 'Permission denied.', 'pixalia-image-assistant' ) ], 403 );
		}

		$api_key = isset( $_POST['api_key'] ) ? sanitize_text_field( wp_unslash($_POST['api_key']) ) : '';

		// ★追加: 設定値の取得と保存
		$style  = isset( $_POST['default_style'] ) ? sanitize_text_field( wp_unslash($_POST['default_style']) ) : 'photorealistic';
		$aspect = isset( $_POST['default_aspect'] ) ? sanitize_text_field( wp_unslash($_POST['default_aspect']) ) : '16:9';

		$this->optionRepository->updateDefaultStyle( $style );
		$this->optionRepository->updateDefaultAspectRatio( $aspect );

		// APIキーの処理（空なら削除、あれば検証）
		if ( empty( $api_key ) ) {
			delete_option( PixaliaConst::OPTION_API_KEY );
			wp_send_json_success( [ 'message' => '設定を保存しました（APIキーは削除されました）。' ] );
		}

		// API検証
		$user_status = $this->client->get_user_status( $api_key );

		if ( is_wp_error( $user_status ) ) {
			// 検証失敗しても、スタイル設定だけは保存しておいてあげるのが親切かも？
			// 今回はエラーとして返します
			wp_send_json_error( [
				'message' => 'APIキーが無効です: ' . $user_status->get_error_message()
			] );
		}

		// 保存
		update_option( PixaliaConst::OPTION_API_KEY, $api_key );

		wp_send_json_success( [
			'message'   => '設定を保存しました。接続成功！',
			'user_data' => [
				'plan_name' => $user_status['plan_name'] ?? 'Unknown',
				'credits'   => $user_status['credits'] ?? 0,
			]
		] );
	}

	/**
	 * 1. 生成開始 (POST /generations)
	 */
	public function handle_generate_image() {
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => '権限がありません。' ] );
		}

		$params = [
			'title'        => isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash($_POST['title']) ?? '' ) : '',
			'content'      => isset( $_POST['content'] ) ? sanitize_textarea_field( wp_unslash($_POST['content']) ?? '' ) : '',
			'style'        => isset( $_POST['style'] ) ? sanitize_text_field( wp_unslash($_POST['style']) ?? PixaliaConst::IMAGE_DEFAULT_STYLE ) : PixaliaConst::IMAGE_DEFAULT_STYLE,
			'aspect_ratio' => isset( $_POST['aspect_ratio'] ) ? sanitize_text_field( wp_unslash($_POST['aspect_ratio']) ?? '1' ) : '1',
			'target_type'  => isset( $_POST['target_type'] ) ? sanitize_text_field( wp_unslash($_POST['target_type']) ?? 'featured' ) : 'featured',
		];

		$result = $this->client->generate_image( $params );

		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [ 'message' => $result->get_error_message() ] );
		}

		// 成功時: { "task_uuid": "uuid...", "status": "pending" }
		wp_send_json_success( $result );
	}

	/**
	 * 2. ステータス確認 (GET /generations/{id})
	 */
	public function handle_check_task_status() {
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => '権限がありません。' ] );
		}

		$task_id = isset( $_POST['task_id'] ) ? sanitize_text_field( wp_unslash($_POST['task_id']) ?? '' ) : '';
		if ( empty( $task_id ) ) {
			wp_send_json_error( [ 'message' => 'Task IDが必要です。' ] );
		}

		$result = $this->client->get_task_status( $task_id );

		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [ 'message' => $result->get_error_message() ] );
		}

		// 成功時: { "job_status": "completed", "result": { "image_url": "..." } }
		wp_send_json_success( $result );
	}

	/**
	 * 3. 画像保存 & 紐付け
	 */
	public function handle_attach_image() {
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => '権限がありません。' ] );
		}

		$post_id     = absint( $_POST['post_id'] ?? 0 );
		$image_url   = isset( $_POST['image_url'] ) ? esc_url_raw( wp_unslash($_POST['image_url']) ?? '' ) : '';
		$is_featured = ( isset( $_POST['is_featured'] ) && sanitize_text_field( wp_unslash($_POST['is_featured']) ) === '1' );

		if ( ! $post_id || ! $image_url ) {
			wp_send_json_error( [ 'message' => 'パラメータが不足しています。' ] );
		}

		// 画像をDLして保存
		$attachment_id = $this->uploader->upload_from_url( $image_url, $post_id, 'Generated by Pixalia' );

		if ( is_wp_error( $attachment_id ) ) {
			wp_send_json_error( [ 'message' => '画像の保存に失敗: ' . $attachment_id->get_error_message() ] );
		}

		// アイキャッチに設定する？ (今回は「アイキャッチタブ」からの呼び出しなら設定する仕様)
		// 必要に応じてフラグを渡してもいいが、一旦強制で設定する例:
		if ( $is_featured ) {
			$this->uploader->set_featured_image( $post_id, $attachment_id );
		}

		// 成功レスポンス
		wp_send_json_success( [
			'attachment_id' => $attachment_id,
			'url'           => wp_get_attachment_url( $attachment_id ),
			'message'       => '画像を保存しました。'
		] );
	}

	/**
	 * OGPデータ取得リクエストを処理します。
	 */
	public function handleGetOgpData(): void {
		// Nonce検証と権限チェック
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => __( 'Permission denied.', 'pixalia-image-assistant' ) ], 403 );
		}

		// 投稿IDの取得と検証
		$postId = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
		if ( ! $postId ) {
			wp_send_json_error( [ 'message' => __( 'Invalid Post ID.', 'pixalia-image-assistant' ) ] );
		}

		// 投稿URLの取得
		$url = get_permalink( $postId );
		if ( empty( $url ) === true ) {
			wp_send_json_error( [ 'message' => __( 'Could not retrieve post URL.', 'pixalia-image-assistant' ) ] );
		}

		$args = [ 'timeout' => 30 ];

		//開発環境の場合の対応
		if ( str_contains( $url, 'http://localhost:8080' ) ) {
			if ( str_starts_with( $url, 'http://localhost:8080' ) ) {
				$url             = str_replace( 'http://localhost:8080', 'http://wordpress', $url );
				$args['headers'] = [
					'Host' => 'localhost:8080'
				];
			}
		}

		//サーバーサイドからURLの内容を取得
		$response = wp_remote_get( $url, $args ); // タイムアウトを15秒に設定

		if ( is_wp_error( $response ) ) {
			// デバッグしやすいように、リクエストしたURLとエラー詳細を返す
			$error_message = sprintf(
				'Failed to fetch URL (%s). Error: %s',
				$url,
				$response->get_error_message()
			);
			wp_send_json_error( [ 'message' => $error_message ] );
		}

		$html = wp_remote_retrieve_body( $response );
		if ( empty( $html ) ) {
			wp_send_json_error( [ 'message' => __( 'Could not retrieve HTML content from the URL.', 'pixalia-image-assistant' ) ] );
		}

		//HTMLからOGPメタタグを抽出
		$ogpData = $this->scrapeOgpData( $html );

		//成功JSONを返す
		wp_send_json_success( $ogpData );
	}

	/**
	 * 未チェックの投稿総数を取得する
	 */
	public function handleGetUncheckedCount(): void {
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => __( 'Permission denied.', 'pixalia-image-assistant' ) ], 403 );
		}
		// リポジトリに総件数を問い合わせる
		$count = $this->postRepository->getUncheckedCount();
		wp_send_json_success( [ 'count' => $count ] );
	}

	/**
	 * 投稿のアイキャッチ画像チェックを一括で行います（50ずつ）
	 */
	public function handleBulkCheckPosts(): void {
		check_ajax_referer( 'wp_rest', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => __( 'Permission denied.', 'pixalia-image-assistant' ) ], 403 );
		}

		// 1バッチあたりの処理件数
		$limit = 50;
		// リポジトリにバッチ取得を依頼
		$posts           = $this->postRepository->getUncheckedPosts( $limit );
		$processed_count = 0;

		foreach ( $posts as $post ) {
			// ImageCheckerにチェックと保存を依頼
			$this->checker->check_and_save_status_on_save( $post->ID, $post, true );
			$processed_count ++;
		}

		// 残りの未チェック件数をリポジトリに再問い合わせ
		$remaining_count = $this->postRepository->getUncheckedCount();

		if ( $remaining_count <= 0 ) {
			$optionRepository = new OptionRepository();
			$optionRepository->updateLastCheckVersion( PixaliaConst::LOGIC_VERSION );
		}

		wp_send_json_success( [
			'processed' => $processed_count,
			'remaining' => $remaining_count,
		] );
	}

	/**
	 * HTML文字列からOGPメタタグを抽出するヘルパーメソッド
	 *
	 * @param string $html HTMLコンテンツ
	 *
	 * @return array OGPデータの連想配列 (例: ['og:title' => '...', 'og:image' => '...'])
	 */
	private function scrapeOgpData( string $html ): array {
		$ogpData = [];
		if ( ! class_exists( 'DOMDocument' ) ) {
			return $ogpData; // DOM拡張がない場合は空を返す
		}

		$doc = new DOMDocument();
		// HTML5のタグを正しく解釈し、文字化けを防ぐおまじない
		libxml_use_internal_errors( true );
		$doc->loadHTML( mb_convert_encoding( $html, 'HTML-ENTITIES', 'UTF-8' ) );
		libxml_clear_errors();

		$metaTags = $doc->getElementsByTagName( 'meta' );

		foreach ( $metaTags as $tag ) {
			$property = $tag->getAttribute( 'property' );
			// property属性が 'og:' で始まるものを抽出
			if ( $property && str_starts_with( $property, 'og:' ) ) {
				$ogpData[ $property ] = $tag->getAttribute( 'content' );
			}
		}

		return $ogpData;
	}
}
