<?php

namespace HulkPlugins\Woo\AccountPages\Admin\Controllers;

use HulkPlugins\Woo\AccountPages\Admin\Services\AccountPagesService;
use HulkPlugins\Woo\AccountPages\Core\BaseController;
use HulkPlugins\Woo\AccountPages\Core\SingletonTrait;
use WP_Error;
use function HulkPlugins\Woo\AccountPages\hulk_woo_ap_fs;
use function HulkPlugins\Woo\AccountPages\hulk_woo_ap_fs_notice;

defined( 'ABSPATH' ) || exit;

class AccountPageLimitNotice extends BaseController {

	use SingletonTrait;

	protected AccountPagesService $service;

	public function init_hooks(): void {
		$this->service = AccountPagesService::getInstance();

		// Validate before insert/update (classic editor, admin, etc.)
		add_filter( 'wp_insert_post_data', [ $this, 'limit_cpt_posts' ], 10, 2 );

		// Validate for REST API
        add_filter( "rest_pre_insert_{$this->service->post_type}", [ $this, 'rest_limit_cpt_posts' ] );
	}

	/**
	 * Restrict CPT posts (classic/admin)
	 */
	public function limit_cpt_posts( $data, $postarr ) {
		$post_type = ($data['post_type'] ?? '');

		// Apply only to your CPT
		if ( $post_type !== $this->service->post_type ) {
			return $data;
		}

		// Exit early if using premium code
		if ( hulk_woo_ap_fs()->can_use_premium_code() ) {
			return $data;
		}

		$post_id     = isset( $postarr['ID'] ) ? (int) $postarr['ID'] : 0;
		$post_status = $data['post_status'] ?? '';

		$error = $this->restrict_pages( $post_id, $post_status );

		if ( is_wp_error( $error ) ) {
			wp_die(
				wp_kses_post( $error->get_error_message() ),
				esc_attr__( 'Limit reached:', 'hulk-account-pages-for-woocommerce' ),
				[ 'back_link' => true ]
			);
		}

		return $data;
	}

	/**
	 * Restrict CPT posts (REST API)
	 * @return object|WP_Error
	 */
	public function rest_limit_cpt_posts( $prepared_post ) {
		$post_type = $prepared_post->post_type ?? '';

		// Apply only to your CPT
		if ( $post_type !== $this->service->post_type ) {
			return $prepared_post;
		}

		// Exit early if using premium code
		if ( hulk_woo_ap_fs()->can_use_premium_code() ) {
			return $prepared_post;
		}

		$post_id     = isset( $prepared_post->ID ) ? (int) $prepared_post->ID : 0;
		$post_status = $prepared_post->post_status ?? '';

		$error = $this->restrict_pages( $post_id, $post_status );

		if ( is_wp_error( $error ) ) {
			return new WP_Error(
				'forbidden',
				esc_html( wp_strip_all_tags( $error->get_error_message() ) ),
				[ 'status' => 403 ]
			);
		}

		return $prepared_post;
	}

	/**
	 * Core restriction logic
	 */
	public function restrict_pages( int $post_id, string $post_status ): ?WP_Error {
		// Make limit filterable
		$limit = (int) apply_filters( 'hulk_woo_ap_account_pages_limit', 2 );

		$is_new = empty( $post_id );

		// Get previous status (if updating)
		$old_status = $post_id ? get_post_status( $post_id ) : '';

		// Only block when:
		// - creating a new published post
		// - OR transitioning from non-publish → publish
		$is_new_publish = $is_new && $post_status === 'publish';
		$is_transition_to_publish = ($post_status === 'publish' && $old_status !== 'publish');

		if ( ! ($is_new_publish || $is_transition_to_publish) ) {
			return null;
		}

		// Count published posts
		$published_count = (int) wp_count_posts( $this->service->post_type )->publish;

		// Exclude current post if already published (editing case)
		if ( ! $is_new && $old_status === 'publish' ) {
			--$published_count;
		}

		if ( $published_count >= $limit ) {

			$message  = sprintf(
			/** @lang text */                '<p><strong>%s</strong> %s</p>',
				esc_attr__( 'Limit reached:', 'hulk-account-pages-for-woocommerce' ),
				esc_attr__( 'You can only publish 2 pages.', 'hulk-account-pages-for-woocommerce' )
			);
			$message .= sprintf(
			/** @lang text */                '<p> %s</p>',
				esc_attr__( 'If you want unlimited pages, upgrade to Pro.', 'hulk-account-pages-for-woocommerce' )
			);

			// Freemius notice
			$message .= sprintf( /** @lang text */ '<p> %s</p>', hulk_woo_ap_fs_notice() );

			return new WP_Error(
				'account_pages_limit_reached',
				wp_kses_post( $message ),
				[ 'status' => 403 ]
			);
		}

		return null;
	}
}
