<?php

declare( strict_types=1 );

namespace Brightfern\Admin;

use Brightfern\Inbound\WebhookController;
use Brightfern\Settings;
use Brightfern\Transmission\ProviderFactory;

/**
 * Brightfern settings screen (WooCommerce submenu). Captures seller identity,
 * provider credentials, the trigger status, country/format, and the inbound
 * webhook secret + polling toggle. Inputs are validated/sanitized before save;
 * transmission is refused elsewhere if the seller identity is incomplete.
 */
final class SettingsPage {

	public const PAGE = 'brightfern-settings';

	public function register(): void {
		add_action( 'admin_menu', array( $this, 'addMenu' ) );
		add_action( 'admin_post_brightfern_save_settings', array( $this, 'save' ) );
	}

	public function addMenu(): void {
		add_submenu_page(
			'woocommerce',
			__( 'Brightfern E-Invoicing', 'brightfern-e-invoicing-for-woocommerce' ),
			__( 'E-Invoicing', 'brightfern-e-invoicing-for-woocommerce' ),
			'manage_woocommerce',
			self::PAGE,
			array( $this, 'render' )
		);
	}

	public function render(): void {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}

		$saved = isset( $_GET['updated'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		echo '<div class="wrap"><h1>' . esc_html__( 'Brightfern E-Invoicing for WooCommerce', 'brightfern-e-invoicing-for-woocommerce' ) . '</h1>';
		if ( $saved ) {
			echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Settings saved.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p></div>';
		}
		if ( ! Settings::sellerIdentityComplete() ) {
			echo '<div class="notice notice-warning"><p>' . esc_html__( 'Seller identity is incomplete — Brightfern will not transmit until name, VAT/company id, address, and Peppol electronic address are set.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p></div>';
		}
		if ( ! brightfern_is_pro() ) {
			echo '<div class="notice notice-info"><p>' . esc_html__( 'Free plan: generate, validate, download, and receive inbound e-invoices. Upgrade to Pro to transmit over Peppol.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p></div>';
		}

		echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '">';
		echo '<input type="hidden" name="action" value="brightfern_save_settings" />';
		wp_nonce_field( 'brightfern_save_settings' );

		$this->sectionSeller();
		$this->sectionProvider();
		$this->sectionFlow();
		$this->sectionInbound();

		echo '<p class="submit"><button type="submit" class="button button-primary">' . esc_html__( 'Save settings', 'brightfern-e-invoicing-for-woocommerce' ) . '</button></p>';
		echo '</form></div>';
	}

	private function sectionSeller(): void {
		echo '<h2>' . esc_html__( 'Seller identity', 'brightfern-e-invoicing-for-woocommerce' ) . '</h2><table class="form-table"><tbody>';
		$this->text( 'seller_name', __( 'Legal name (BT-27)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_trading_name', __( 'Trading name (BT-28)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_vat', __( 'VAT number (BT-31), e.g. BE0123456789', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_company_id', __( 'Company registration id (BT-30)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_company_id_scheme', __( 'Company id scheme (e.g. 0208)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_endpoint_scheme', __( 'Peppol electronic address scheme (BT-34), e.g. 0208', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_endpoint_id', __( 'Peppol electronic address (BT-34)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_line1', __( 'Address line 1', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_line2', __( 'Address line 2', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_city', __( 'City', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_postal_zone', __( 'Post code', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_country_subentity', __( 'Region / state', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_country', __( 'Country code (ISO, e.g. BE)', 'brightfern-e-invoicing-for-woocommerce' ), 'BE' );
		$this->text( 'seller_contact_name', __( 'Contact name', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_contact_email', __( 'Contact email', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'seller_contact_phone', __( 'Contact phone', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'payee_iban', __( 'IBAN (BT-84)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'payee_bic', __( 'BIC (BT-86)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->select(
			'payment_means_code',
			__( 'Payment means (BT-81)', 'brightfern-e-invoicing-for-woocommerce' ),
			array(
				'30' => __( 'Credit transfer', 'brightfern-e-invoicing-for-woocommerce' ),
				'58' => __( 'SEPA credit transfer', 'brightfern-e-invoicing-for-woocommerce' ),
			),
			'30'
		);
		$this->text( 'payment_terms', __( 'Payment terms (BT-20)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->checkbox( 'exempt_small_business', __( 'VAT-exempt small business (e.g. franchise en base / Kleinunternehmer)', 'brightfern-e-invoicing-for-woocommerce' ) );
		echo '</tbody></table>';
	}

	private function sectionProvider(): void {
		echo '<h2>' . esc_html__( 'Access Point provider', 'brightfern-e-invoicing-for-woocommerce' ) . '</h2>';
		echo '<p>' . esc_html__( 'Bring your own Access Point — Brightfern is provider-agnostic. Credentials are stored in your database; never share them.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p>';
		echo '<p>' . esc_html__( 'The Poland KSeF (direct) provider files invoices straight to the Ministry of Finance with no intermediary. It only sends — it does not receive inbound e-invoices — and filing itself requires Brightfern Pro.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p>';
		echo '<table class="form-table"><tbody>';
		$this->select( 'provider', __( 'Provider', 'brightfern-e-invoicing-for-woocommerce' ), ProviderFactory::choices() );
		$this->text( 'storecove_api_key', __( 'Storecove API key', 'brightfern-e-invoicing-for-woocommerce' ), '', 'password' );
		$this->text( 'storecove_legal_entity_id', __( 'Storecove legal entity id', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'storecove_base_url', __( 'Storecove base URL', 'brightfern-e-invoicing-for-woocommerce' ), 'https://api.storecove.com/api/v2' );
		$this->checkbox( 'use_test_network', __( 'Use the Peppol TEST network for recipient lookups', 'brightfern-e-invoicing-for-woocommerce' ) );
		echo '<tr><th>' . esc_html__( 'KSeF authorization token', 'brightfern-e-invoicing-for-woocommerce' ) . '</th><td>';
		echo '<input type="password" class="regular-text" id="brightfern_ksef_token" name="brightfern[ksef_token]" value="' . esc_attr( (string) Settings::get( 'ksef_token' ) ) . '" autocomplete="off" />';
		echo '<p class="description">' . esc_html__( 'Only used with the Poland KSeF (direct) provider. Generate this once in the KSeF Taxpayer Application (ksef.podatki.gov.pl) — Brightfern cannot create it for you, and it is not the same as a Storecove key.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p>';
		echo '</td></tr>';
		$this->text( 'ksef_base_url', __( 'KSeF base URL', 'brightfern-e-invoicing-for-woocommerce' ), 'https://api-test.ksef.mf.gov.pl/api/v2' );
		echo '</tbody></table>';
	}

	private function sectionFlow(): void {
		echo '<h2>' . esc_html__( 'Invoicing flow', 'brightfern-e-invoicing-for-woocommerce' ) . '</h2><table class="form-table"><tbody>';

		$statuses = array();
		if ( function_exists( 'wc_get_order_statuses' ) ) {
			foreach ( wc_get_order_statuses() as $key => $label ) {
				$statuses[ preg_replace( '/^wc-/', '', (string) $key ) ] = (string) $label;
			}
		} else {
			$statuses = array( 'completed' => 'Completed', 'processing' => 'Processing' );
		}
		$this->select( 'trigger_status', __( 'Generate on order status', 'brightfern-e-invoicing-for-woocommerce' ), $statuses, 'completed' );
		$this->select( 'format', __( 'Format', 'brightfern-e-invoicing-for-woocommerce' ), array( 'ubl' => 'Peppol BIS UBL', 'xrechnung' => 'XRechnung (Germany)', 'facturx' => 'Factur-X (France)', 'ksef' => 'KSeF FA(3) (Poland)' ), 'ubl' );
		$this->text( 'due_days', __( 'Payment due in (days)', 'brightfern-e-invoicing-for-woocommerce' ), '30' );
		$this->checkbox( 'mark_prepaid', __( 'Treat paid orders as prepaid (sets BT-113)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->checkbox( 'require_recipient_reachable', __( 'Block sending if the recipient is not registered on Peppol', 'brightfern-e-invoicing-for-woocommerce' ), true );
		echo '</tbody></table>';
	}

	private function sectionInbound(): void {
		echo '<h2>' . esc_html__( 'Inbound (receiving)', 'brightfern-e-invoicing-for-woocommerce' ) . '</h2>';
		echo '<table class="form-table"><tbody>';
		$this->checkbox( 'polling_enabled', __( 'Poll the provider for inbound documents every 15 minutes (fallback if webhooks are unavailable)', 'brightfern-e-invoicing-for-woocommerce' ) );
		$this->text( 'webhook_secret', __( 'Webhook shared secret', 'brightfern-e-invoicing-for-woocommerce' ), '', 'password' );
		echo '<tr><th>' . esc_html__( 'Webhook URL', 'brightfern-e-invoicing-for-woocommerce' ) . '</th><td><code>' . esc_html( WebhookController::webhookUrl() ) . '</code><p class="description">' . esc_html__( 'Paste this into your provider so it notifies Brightfern of received documents. Set a secret first, and configure the secret as a request header named X-Brightfern-Secret if your provider supports custom headers — that keeps it out of server and proxy logs.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p></td></tr>';
		echo '<tr><th>' . esc_html__( 'Webhook URL (with secret, for providers without custom headers)', 'brightfern-e-invoicing-for-woocommerce' ) . '</th><td><code>' . esc_html( WebhookController::webhookUrlWithSecretQueryArg() ) . '</code><p class="description">' . esc_html__( 'Only use this if your provider genuinely cannot send a custom header — the secret in this URL can end up in server/proxy access logs.', 'brightfern-e-invoicing-for-woocommerce' ) . '</p></td></tr>';
		echo '</tbody></table>';
	}

	/* ----- field helpers ----- */

	private function text( string $key, string $label, string $default = '', string $type = 'text' ): void {
		$value = (string) Settings::get( $key, $default );
		echo '<tr><th><label for="brightfern_' . esc_attr( $key ) . '">' . esc_html( $label ) . '</label></th><td>';
		echo '<input type="' . esc_attr( $type ) . '" class="regular-text" id="brightfern_' . esc_attr( $key ) . '" name="brightfern[' . esc_attr( $key ) . ']" value="' . esc_attr( $value ) . '" autocomplete="off" />';
		echo '</td></tr>';
	}

	/** @param array<string,string> $options */
	private function select( string $key, string $label, array $options, string $default = '' ): void {
		$value = (string) Settings::get( $key, $default );
		echo '<tr><th><label for="brightfern_' . esc_attr( $key ) . '">' . esc_html( $label ) . '</label></th><td>';
		echo '<select id="brightfern_' . esc_attr( $key ) . '" name="brightfern[' . esc_attr( $key ) . ']">';
		foreach ( $options as $optValue => $optLabel ) {
			echo '<option value="' . esc_attr( (string) $optValue ) . '" ' . selected( $value, (string) $optValue, false ) . '>' . esc_html( $optLabel ) . '</option>';
		}
		echo '</select></td></tr>';
	}

	private function checkbox( string $key, string $label, bool $default = false ): void {
		$value = (bool) Settings::get( $key, $default );
		echo '<tr><th>' . esc_html( $label ) . '</th><td>';
		echo '<label><input type="checkbox" name="brightfern[' . esc_attr( $key ) . ']" value="1" ' . checked( $value, true, false ) . ' /> ' . esc_html__( 'Enabled', 'brightfern-e-invoicing-for-woocommerce' ) . '</label>';
		echo '</td></tr>';
	}

	/* ----- save ----- */

	public function save(): void {
		check_admin_referer( 'brightfern_save_settings' );
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'Insufficient permissions.', 'brightfern-e-invoicing-for-woocommerce' ) );
		}

		// The array key here must match the field helpers' name="brightfern[...]"
		// exactly — a mismatch makes every save silently wipe the stored settings.
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized field-by-field in sanitize() below.
		$raw = isset( $_POST['brightfern'] ) && is_array( $_POST['brightfern'] ) ? wp_unslash( $_POST['brightfern'] ) : array();
		$clean = $this->sanitize( (array) $raw );
		Settings::update( $clean );

		wp_safe_redirect( add_query_arg( array( 'page' => self::PAGE, 'updated' => '1' ), admin_url( 'admin.php' ) ) );
		exit;
	}

	/**
	 * @param array<string,mixed> $raw
	 * @return array<string,mixed>
	 */
	private function sanitize( array $raw ): array {
		$textKeys = array(
			'seller_name', 'seller_trading_name', 'seller_vat', 'seller_company_id', 'seller_company_id_scheme',
			'seller_endpoint_scheme', 'seller_endpoint_id', 'seller_line1', 'seller_line2', 'seller_city',
			'seller_postal_zone', 'seller_country_subentity', 'seller_country', 'seller_contact_name',
			'seller_contact_phone', 'payee_iban', 'payee_bic', 'payment_terms', 'provider',
			'storecove_legal_entity_id', 'trigger_status', 'format', 'due_days', 'webhook_secret',
			'storecove_api_key', 'ksef_token',
		);
		$checkboxKeys = array( 'exempt_small_business', 'use_test_network', 'mark_prepaid', 'require_recipient_reachable', 'polling_enabled' );

		$clean = array();
		foreach ( $textKeys as $key ) {
			// is_scalar() guard, not a bare (string) cast: a crafted POST field
			// (e.g. brightfern[seller_name][]=x) makes $raw[$key] an array, and
			// casting an array to string raises a PHP warning and silently
			// stores the literal text "Array". Requires manage_woocommerce
			// already, so not a security issue — just noise in the log.
			$value         = $raw[ $key ] ?? '';
			$clean[ $key ] = sanitize_text_field( is_scalar( $value ) ? (string) $value : '' );
		}
		$clean['seller_country']  = strtoupper( substr( $clean['seller_country'], 0, 2 ) );
		$clean['seller_contact_email'] = sanitize_email( (string) ( $raw['seller_contact_email'] ?? '' ) );
		$clean['storecove_base_url']   = $this->httpsUrl( $raw['storecove_base_url'] ?? '', 'https://api.storecove.com/api/v2' );
		$clean['ksef_base_url']        = $this->httpsUrl( $raw['ksef_base_url'] ?? '', 'https://api-test.ksef.mf.gov.pl/api/v2' );
		$clean['due_days']        = (string) max( 0, (int) ( $raw['due_days'] ?? 30 ) );
		// UNCL4461: only the two credit-transfer codes the serializer supports.
		$means                        = (string) ( $raw['payment_means_code'] ?? '30' );
		$clean['payment_means_code']  = in_array( $means, array( '30', '58' ), true ) ? $means : '30';

		foreach ( $checkboxKeys as $key ) {
			$clean[ $key ] = ! empty( $raw[ $key ] );
		}

		return $clean;
	}

	/**
	 * An API base URL, forced to https.
	 *
	 * Both provider base URLs carry credentials to their endpoint — Storecove's
	 * a bearer API key, KSeF's the RSA-encrypted authorization token plus the
	 * certificate response that key is encrypted *to*. Plain esc_url_raw()
	 * allows every scheme in wp_allowed_protocols() (http included) and even
	 * prepends http:// to a scheme-less entry, so a typo silently downgrades
	 * the transport with no feedback. There is no legitimate reason to point
	 * either at http://, so anything that isn't https falls back to the
	 * documented default rather than being saved.
	 *
	 * @param mixed  $value   Raw submitted value.
	 * @param string $default Fallback used when the value is empty or not https.
	 */
	private function httpsUrl( mixed $value, string $default ): string {
		$url = esc_url_raw( is_scalar( $value ) ? (string) $value : '', array( 'https' ) );
		return '' !== $url ? $url : $default;
	}
}
