<?php

declare(strict_types=1);

namespace Australcode\Rewards\Admin;

use Australcode\Rewards\Service\Import\ImportReport;
use Australcode\Rewards\Service\Import\YithImporter;

defined( 'ABSPATH' ) || exit;

/**
 * "Import" page — admin UI for migrating point balances from another loyalty
 * plugin into Australcode Points and Rewards.
 *
 * The YithImporter (balance-only, idempotent, resumable) already existed but was
 * reachable only through WP-CLI (`wp acrwd import yith`) — invisible to the
 * non-technical merchants who most need to migrate (code-vs-UI audit, 2026-06-25).
 * This page wraps it: a Scan (dry-run) that reports what would be imported, then an
 * Import now button that writes it. Core / both builds (Free includes the migration
 * tools). Mirrors the TiersPage admin-post + nonce + flash pattern.
 *
 * On a very large store the synchronous run can hit PHP's max_execution_time — but
 * the import is idempotent and resumable (each user is flagged once written), so
 * re-running simply continues where it stopped. The equivalent WP-CLI command has no
 * such limit for bulk migrations.
 */
final class ImportPage {

	use RendersPageHeader;

	public const SCAN_ACTION = 'acrwd_import_scan';
	public const RUN_ACTION  = 'acrwd_import_run';
	public const NONCE       = 'acrwd_import';

	private const CAPABILITY    = 'manage_woocommerce';
	private const PAGE_SLUG     = 'acrwd-import';
	private const FLASH_PREFIX  = 'acrwd_import_notice_';
	private const REPORT_PREFIX = 'acrwd_import_report_';
	private const REPORT_TTL    = 10 * MINUTE_IN_SECONDS;

	public function __construct( private readonly YithImporter $yith ) {}

	public function register(): void {
		add_action( 'admin_post_' . self::SCAN_ACTION, array( $this, 'handle_scan' ) );
		add_action( 'admin_post_' . self::RUN_ACTION, array( $this, 'handle_run' ) );
		// Core page: registered in AdminMenu's submenu list (no self-register needed —
		// unlike the @fs_premium_only Pro pages). register() only wires the handlers.
	}

	public function handle_scan(): void {
		$this->guard();
		check_admin_referer( self::NONCE );

		$report = $this->yith->run( true );
		$this->store_report( $report );

		if ( $report->candidates > 0 ) {
			$this->flash( 'success', __( 'Scan complete — review the results below.', 'australcode-points-rewards' ) );
		} else {
			$this->flash( 'success', __( 'Scan complete — no YITH points data found in this site.', 'australcode-points-rewards' ) );
		}

		$this->redirect();
	}

	public function handle_run(): void {
		$this->guard();
		check_admin_referer( self::NONCE );

		$report = $this->yith->run( false );
		$this->clear_report();

		$this->flash(
			'success',
			sprintf(
				/* translators: 1: number of customers imported, 2: total points imported. */
				_n(
					'Imported %1$s customer (%2$s points).',
					'Imported %1$s customers (%2$s points).',
					$report->imported,
					'australcode-points-rewards'
				),
				number_format_i18n( $report->imported ),
				number_format_i18n( $report->points )
			)
		);

		$this->redirect();
	}

	public function render(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You are not allowed to access this page.', 'australcode-points-rewards' ) );
		}

		echo '<div class="wrap acds-root acrwd-page"><div class="acds-wrap">';
		$this->render_page_header(
			__( 'Import', 'australcode-points-rewards' ),
			__( 'Migrate existing point balances from another loyalty plugin into Australcode Points and Rewards.', 'australcode-points-rewards' ),
			$this->dashboard_back_action()
		);
		$this->render_flash();

		$this->render_intro();
		$this->render_report();

		echo '</div></div>';
	}

	private function render_intro(): void {
		echo '<div class="acds-surface"><div class="acds-surface__head"><h2 class="acds-surface__title">'
			. esc_html__( 'YITH WooCommerce Points and Rewards', 'australcode-points-rewards' ) . '</h2></div>';
		echo '<div class="acds-surface__body">';
		echo '<p class="acds-muted">' . esc_html__( 'Reads each customer’s current YITH balance and lifetime totals and writes them into your wallet, with one opening ledger entry per customer so the migration is auditable. It is safe to run more than once — customers already imported are skipped. YITH can be deactivated first; the data is read straight from the database.', 'australcode-points-rewards' ) . '</p>';

		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '">';
		echo '<input type="hidden" name="action" value="' . esc_attr( self::SCAN_ACTION ) . '" />';
		wp_nonce_field( self::NONCE );
		submit_button( __( 'Scan for importable data', 'australcode-points-rewards' ), 'secondary', 'submit', false );
		echo '</form>';
		echo '</div></div>';
	}

	private function render_report(): void {
		$report = $this->stored_report();
		if ( ! $report instanceof ImportReport ) {
			return;
		}

		echo '<div class="acds-surface"><div class="acds-surface__head"><h2 class="acds-surface__title">'
			. esc_html__( 'Scan results', 'australcode-points-rewards' ) . '</h2></div>';
		echo '<div class="acds-surface__body">';

		if ( 0 === $report->candidates ) {
			echo '<div class="acds-empty"><p class="acds-empty__title">'
				. esc_html__( 'No importable data found', 'australcode-points-rewards' ) . '</p>';
			echo '<p class="acds-empty__body">' . esc_html__( 'No YITH WooCommerce Points and Rewards balances exist on this site.', 'australcode-points-rewards' ) . '</p></div>';
			echo '</div></div>';
			return;
		}

		echo '<div class="acrwd-kpi-grid acrwd-kpi-grid--secondary">';
		$this->stat( __( 'Customers found', 'australcode-points-rewards' ), $report->candidates );
		$this->stat( __( 'Already imported', 'australcode-points-rewards' ), $report->already_imported );
		$this->stat( __( 'Ready to import', 'australcode-points-rewards' ), $report->eligible );
		$this->stat( __( 'Points to import', 'australcode-points-rewards' ), $report->points );
		echo '</div>';

		if ( $report->eligible > 0 ) {
			$confirm = sprintf(
				/* translators: %s: number of customers. */
				__( 'Import %s customer(s) now? Existing balances for these customers will be overwritten with their YITH totals.', 'australcode-points-rewards' ),
				number_format_i18n( $report->eligible )
			);
			echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" '
				. 'onsubmit="return confirm(' . esc_attr( (string) wp_json_encode( $confirm ) ) . ');">';
			echo '<input type="hidden" name="action" value="' . esc_attr( self::RUN_ACTION ) . '" />';
			wp_nonce_field( self::NONCE );
			submit_button( __( 'Import now', 'australcode-points-rewards' ), 'primary', 'submit', false );
			echo '</form>';
			echo '<p class="description">' . esc_html__( 'Large stores: if the import stops early, just run it again — it resumes from where it left off.', 'australcode-points-rewards' ) . '</p>';
		} else {
			echo '<p class="acds-muted">' . esc_html__( 'Every YITH customer has already been imported. Nothing left to do.', 'australcode-points-rewards' ) . '</p>';
		}

		echo '</div></div>';
	}

	private function stat( string $label, int $value ): void {
		echo '<div class="acds-kpi"><span class="acds-kpi__value">' . esc_html( number_format_i18n( $value ) ) . '</span>';
		echo '<span class="acds-kpi__label">' . esc_html( $label ) . '</span></div>';
	}

	private function store_report( ImportReport $report ): void {
		set_transient(
			self::REPORT_PREFIX . get_current_user_id(),
			array(
				'candidates'       => $report->candidates,
				'already_imported' => $report->already_imported,
				'eligible'         => $report->eligible,
				'points'           => $report->points,
				'imported'         => $report->imported,
			),
			self::REPORT_TTL
		);
	}

	private function stored_report(): ?ImportReport {
		$data = get_transient( self::REPORT_PREFIX . get_current_user_id() );
		if ( ! is_array( $data ) ) {
			return null;
		}

		return new ImportReport(
			(int) ( $data['candidates'] ?? 0 ),
			(int) ( $data['already_imported'] ?? 0 ),
			(int) ( $data['eligible'] ?? 0 ),
			(int) ( $data['points'] ?? 0 ),
			(int) ( $data['imported'] ?? 0 ),
		);
	}

	private function clear_report(): void {
		delete_transient( self::REPORT_PREFIX . get_current_user_id() );
	}

	private function flash( string $type, string $message ): void {
		set_transient(
			self::FLASH_PREFIX . get_current_user_id(),
			array(
				'type'    => $type,
				'message' => $message,
			),
			MINUTE_IN_SECONDS
		);
	}

	private function render_flash(): void {
		$key   = self::FLASH_PREFIX . get_current_user_id();
		$flash = get_transient( $key );
		if ( ! is_array( $flash ) ) {
			return;
		}
		delete_transient( $key );
		$class = 'success' === ( $flash['type'] ?? '' ) ? 'notice-success' : 'notice-error';
		echo '<div class="notice ' . esc_attr( $class ) . ' is-dismissible"><p>'
			. esc_html( (string) ( $flash['message'] ?? '' ) ) . '</p></div>';
	}

	private function guard(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You are not allowed to import Australcode Rewards data.', 'australcode-points-rewards' ) );
		}
	}

	private function redirect(): void {
		wp_safe_redirect( admin_url( 'admin.php?page=' . self::PAGE_SLUG ) );
		exit;
	}
}
