<?php
/**
 * Kreator onboardingu 1-klik: token → test połączenia → pierwsza faktura.
 *
 * Cel: nowy użytkownik łączy konto KSeF i wystawia pierwszą fakturę w kilka minut,
 * bez błądzenia po ustawieniach. Reużywa istniejących AJAX-ów (ksef_test_connection)
 * oraz bulletproof wysyłki (Invoice_Sender::send_data).
 *
 * @package KSEF\WordPress\Admin
 */

declare(strict_types=1);

namespace KSEF\WordPress\Admin;

// phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders, WordPress.DB.SlowDBQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Wlasne tabele gksef_*: wartosci przez $wpdb->prepare()/esc_like(), nazwy tabel z $wpdb->prefix, paginacja rzutowana (int); nonce weryfikowany w handlerze (check_ajax_referer/check_admin_referer).

use KSEF\WordPress\Crypto;
use KSEF\WordPress\V2\Bootstrap as V2_Bootstrap;

class Onboarding_Page {

	const TABLE = 'gksef_credentials';

	public static function register_ajax(): void {
		add_action( 'wp_ajax_ksef_onboard_create', [ self::class, 'ajax_create' ] );
		add_action( 'wp_ajax_ksef_onboard_test_invoice', [ self::class, 'ajax_test_invoice' ] );
		// Notice „rozpocznij” gdy brak kredencjałów.
		add_action( 'admin_notices', [ self::class, 'maybe_render_start_notice' ] );
	}

	/** Czy są już jakieś kredencjały KSeF? */
	public static function has_credentials(): bool {
		global $wpdb;
		return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}" . self::TABLE ) > 0; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- nazwy tabel z $wpdb->prefix, wartosci przez $wpdb->prepare().
	}

	/** Banner zachęcający do kreatora, gdy konto nie jest jeszcze połączone. */
	public static function maybe_render_start_notice(): void {
		if ( ! current_user_can( 'ksef_view_settings' ) ) {
			return;
		}
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		// Pokaż tylko na stronach KSeF (nie zaśmiecaj całego admina) i gdy brak konta.
		if ( $screen && false === strpos( (string) $screen->id, 'ksef' ) ) {
			return;
		}
		if ( self::has_credentials() ) {
			return;
		}
		$url = admin_url( 'admin.php?page=ksef-onboarding' );
		echo '<div class="notice notice-info" style="border-left-color:#d9531e;padding:14px 16px;">'
			. '<p style="font-size:14px;margin:0 0 8px;"><strong>' . esc_html__( 'Zacznij od połączenia konta KSeF', 'prostafaktura-ksef' ) . '</strong> — '
			. esc_html__( 'token → test → pierwsza faktura w 3 krokach.', 'prostafaktura-ksef' ) . '</p>'
			. '<a href="' . esc_url( $url ) . '" class="button button-primary">' . esc_html__( 'Otwórz kreator', 'prostafaktura-ksef' ) . '</a>'
			. '</div>';
	}

	/** AJAX: zapisz kredencjał z kreatora (token). */
	public static function ajax_create(): void {
		if ( ! current_user_can( 'ksef_view_settings' ) ) {
			wp_send_json_error( [ 'message' => 'Brak uprawnień.' ], 403 );
		}
		check_ajax_referer( 'ksef_onboard', 'nonce' );
		global $wpdb;
		$table = $wpdb->prefix . self::TABLE;

		$nip = preg_replace( '/\D/', '', (string) sanitize_text_field( wp_unslash( $_POST['nip'] ?? '' ) ) );
		if ( strlen( $nip ) !== 10 ) {
			wp_send_json_error( [ 'message' => 'NIP musi mieć dokładnie 10 cyfr.' ], 400 );
		}
		$token = trim( sanitize_text_field( wp_unslash( $_POST['token'] ?? '' ) ) );
		if ( '' === $token ) {
			wp_send_json_error( [ 'message' => 'Wklej token KSeF wygenerowany w aplikacji podatnika.' ], 400 );
		}
		$env  = in_array( sanitize_text_field( wp_unslash( $_POST['ksef_environment'] ?? '' ) ), [ 'test', 'demo', 'prod' ], true ) ? sanitize_text_field( wp_unslash( $_POST['ksef_environment'] ?? '' ) ) : 'test';
		$name = sanitize_text_field( wp_unslash( $_POST['seller_name'] ?? '' ) );

		$data = [
			'nip'              => $nip,
			'name'             => '' !== $name ? $name : ( 'NIP ' . $nip ),
			'ksef_environment' => $env,
			'is_production'    => ( 'prod' === $env ) ? 1 : 0,
			'auth_method'      => 'token',
			'token_encrypted'  => Crypto::encrypt_token( $token ),
			'seller_name'      => $name,
			'seller_email'     => sanitize_email( wp_unslash( $_POST['seller_email'] ?? '' ) ),
			'seller_street'    => sanitize_text_field( wp_unslash( $_POST['seller_street'] ?? '' ) ),
			'seller_building'  => sanitize_text_field( wp_unslash( $_POST['seller_building'] ?? '' ) ),
			'seller_postal'    => sanitize_text_field( wp_unslash( $_POST['seller_postal'] ?? '' ) ),
			'seller_city'      => sanitize_text_field( wp_unslash( $_POST['seller_city'] ?? '' ) ),
			'seller_country'   => strtoupper( substr( sanitize_text_field( wp_unslash( $_POST['seller_country'] ?? 'PL' ) ), 0, 2 ) ) ?: 'PL',
			'sync_incoming'    => 1,
			'sync_outgoing'    => 1,
		];

		// Ten sam NIP+środowisko → aktualizuj istniejący zamiast tworzyć duplikat.
		$existing = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$table} WHERE nip = %s AND ksef_environment = %s LIMIT 1", $nip, $env ) );
		if ( $existing ) {
			$wpdb->update( $table, $data, [ 'id' => (int) $existing ] );
			$id = (int) $existing;
		} else {
			$wpdb->insert( $table, $data );
			$id = (int) $wpdb->insert_id;
		}
		if ( ! get_option( 'ksef_default_credential_id' ) ) {
			update_option( 'ksef_default_credential_id', $id, false );
		}

		wp_send_json_success( [
			'credential_id' => $id,
			'environment'   => $env,
			'test_nonce'    => wp_create_nonce( 'ksef_test_connection' ),
		] );
	}

	/** AJAX: wyślij fakturę testową do piaskownicy (tylko env=test). */
	public static function ajax_test_invoice(): void {
		if ( ! current_user_can( 'ksef_create_invoice' ) ) {
			wp_send_json_error( [ 'message' => 'Brak uprawnień.' ], 403 );
		}
		check_ajax_referer( 'ksef_onboard', 'nonce' );
		global $wpdb;
		$id   = intval( wp_unslash( $_POST['credential_id'] ?? 0 ) );
		$cred = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}gksef_credentials WHERE id = %d", $id ), ARRAY_A );
		if ( ! $cred ) {
			wp_send_json_error( [ 'message' => 'Kredencjał nie istnieje.' ], 404 );
		}
		// Bezpieczeństwo: fakturę testową wysyłamy WYŁĄCZNIE na środowisko testowe.
		if ( 'test' !== (string) ( $cred['ksef_environment'] ?? '' ) ) {
			wp_send_json_error( [ 'message' => 'Faktura testowa działa tylko na środowisku testowym (piaskownica MF). Dla produkcji wystaw prawdziwą fakturę.' ], 400 );
		}
		$payload = self::sample_payload( $cred );
		$res = V2_Bootstrap::invoice_sender_for_credential( $cred )->send_data( $payload, $cred, null );
		if ( is_wp_error( $res ) ) {
			$fr = \KSEF\WordPress\V2\Ksef_Client::friendly_error( (string) $res->get_error_code(), (string) $res->get_error_message() );
			wp_send_json_error( [ 'message' => $fr['title'], 'hint' => $fr['hint'] ], 200 );
		}
		wp_send_json_success( [
			'status'      => (string) ( $res['status'] ?? 'sent' ),
			'ksef_number' => (string) ( $res['ksef_number'] ?? '' ),
			'invoice_id'  => (int) ( $res['invoice_id'] ?? 0 ),
		] );
	}

	/** Minimalna, poprawna faktura testowa zbudowana z danych sprzedawcy z kredencjału. */
	private static function sample_payload( array $cred ): array {
		$seller = [
			'nip'     => (string) $cred['nip'],
			'name'    => (string) ( $cred['seller_name'] ?: $cred['name'] ),
			'email'   => (string) ( $cred['seller_email'] ?? '' ),
			'address' => [
				'country'       => (string) ( $cred['seller_country'] ?: 'PL' ),
				'street'        => (string) ( $cred['seller_street'] ?: 'Testowa' ),
				'street_number' => (string) ( $cred['seller_building'] ?: '1' ),
				'city'          => (string) ( $cred['seller_city'] ?: 'Warszawa' ),
				'postal_code'   => (string) ( $cred['seller_postal'] ?: '00-001' ),
			],
		];
		return [
			'seller'         => $seller,
			'buyer'          => [
				'nip'     => '1234563218',
				'name'    => 'Nabywca Testowy Sp. z o.o.',
				'address' => [ 'country' => 'PL', 'street' => 'Przykładowa', 'street_number' => '2', 'city' => 'Kraków', 'postal_code' => '30-001' ],
			],
			'items'          => [ [ 'description' => 'Usługa testowa KSeF', 'unit' => 'szt.', 'quantity' => 1, 'unit_price_net' => 100.00, 'vat_rate' => 23, 'line_net' => 100.00, 'line_gross' => 123.00 ] ],
			'vat_summary'    => [ [ 'rate' => 23, 'base_net' => 100.00, 'vat_amount' => 23.00 ] ],
			'total_net'      => 100.00,
			'total_vat'      => 23.00,
			'total_gross'    => 123.00,
			'currency'       => 'PLN',
			'invoice_number' => 'TEST/' . gmdate( 'YmdHis' ),
			'issue_date'     => gmdate( 'Y-m-d' ),
			'sale_date'      => gmdate( 'Y-m-d' ),
			'rodzaj_faktury' => 'VAT',
			'adnotacje'      => [ 'P_16' => '2', 'P_17' => '2', 'P_18' => '2', 'P_18A' => '2', 'P_19N' => '1', 'P_22N' => '1', 'P_23' => '2' ],
			'payment'        => [ 'form' => '6', 'paid' => 0, 'due_date' => gmdate( 'Y-m-d', strtotime( '+14 days' ) ) ],
			'is_b2c'         => false,
		];
	}

	public function render_page(): void {
		$nonce      = wp_create_nonce( 'ksef_onboard' );
		$ajax       = admin_url( 'admin-ajax.php' );
		$invoice_url = admin_url( 'admin.php?page=ksef-manual-invoice' );
		?>
		<div class="ksob-wrap">
			<div class="ksob-head">
				<h1><?php esc_html_e( 'Połącz KSeF w 3 krokach', 'prostafaktura-ksef' ); ?></h1>
				<p><?php esc_html_e( 'Token → test połączenia → pierwsza faktura. Zajmie kilka minut.', 'prostafaktura-ksef' ); ?></p>
			</div>

			<div class="ksob-steps">
				<div class="ksob-step is-active" data-step="1"><span>1</span> <?php esc_html_e( 'Połącz', 'prostafaktura-ksef' ); ?></div>
				<div class="ksob-step" data-step="2"><span>2</span> <?php esc_html_e( 'Test', 'prostafaktura-ksef' ); ?></div>
				<div class="ksob-step" data-step="3"><span>3</span> <?php esc_html_e( 'Faktura', 'prostafaktura-ksef' ); ?></div>
			</div>

			<!-- KROK 1 -->
			<div class="ksob-panel is-active" id="ksob-p1">
				<div class="ksob-card">
					<label class="ksob-lbl"><?php esc_html_e( 'Środowisko', 'prostafaktura-ksef' ); ?></label>
					<div class="ksob-seg">
						<label class="ksob-seg-item is-on"><input type="radio" name="ob_env" value="test" checked> <?php esc_html_e( 'Testowe (piaskownica)', 'prostafaktura-ksef' ); ?></label>
						<label class="ksob-seg-item"><input type="radio" name="ob_env" value="prod"> <?php esc_html_e( 'Produkcyjne', 'prostafaktura-ksef' ); ?></label>
					</div>
					<p class="ksob-hint"><?php esc_html_e( 'Zacznij od testowego, aby bezpiecznie wystawić próbną fakturę. Produkcję włącz, gdy wszystko działa.', 'prostafaktura-ksef' ); ?></p>

					<div class="ksob-grid2">
						<div><label class="ksob-lbl"><?php esc_html_e( 'NIP firmy', 'prostafaktura-ksef' ); ?> *</label><input type="text" id="ob_nip" placeholder="np. 5272772475" maxlength="13"></div>
						<div><label class="ksob-lbl"><?php esc_html_e( 'Nazwa firmy', 'prostafaktura-ksef' ); ?></label><input type="text" id="ob_name" placeholder="np. Moja Firma Sp. z o.o."></div>
					</div>

					<label class="ksob-lbl"><?php esc_html_e( 'Token KSeF', 'prostafaktura-ksef' ); ?> *</label>
					<textarea id="ob_token" rows="3" placeholder="<?php esc_attr_e( 'Wklej token wygenerowany w aplikacji podatnika KSeF', 'prostafaktura-ksef' ); ?>"></textarea>
					<p class="ksob-hint"><?php esc_html_e( 'Token wygenerujesz w aplikacji podatnika KSeF: Ustawienia → Tokeny → Wygeneruj (uprawnienia do wystawiania i przeglądania).', 'prostafaktura-ksef' ); ?></p>

					<details class="ksob-more">
						<summary><?php esc_html_e( 'Dane sprzedawcy na fakturze (zalecane)', 'prostafaktura-ksef' ); ?></summary>
						<div class="ksob-grid2">
							<div><label class="ksob-lbl"><?php esc_html_e( 'Ulica', 'prostafaktura-ksef' ); ?></label><input type="text" id="ob_street"></div>
							<div><label class="ksob-lbl"><?php esc_html_e( 'Nr', 'prostafaktura-ksef' ); ?></label><input type="text" id="ob_building"></div>
							<div><label class="ksob-lbl"><?php esc_html_e( 'Kod pocztowy', 'prostafaktura-ksef' ); ?></label><input type="text" id="ob_postal" placeholder="00-000"></div>
							<div><label class="ksob-lbl"><?php esc_html_e( 'Miasto', 'prostafaktura-ksef' ); ?></label><input type="text" id="ob_city"></div>
							<div><label class="ksob-lbl"><?php esc_html_e( 'E-mail', 'prostafaktura-ksef' ); ?></label><input type="email" id="ob_email"></div>
						</div>
					</details>

					<div class="ksob-actions">
						<button type="button" class="ksob-btn ksob-btn-primary" id="ob-save"><?php esc_html_e( 'Zapisz i testuj połączenie →', 'prostafaktura-ksef' ); ?></button>
						<span id="ob-save-msg" class="ksob-msg"></span>
					</div>
				</div>
			</div>

			<!-- KROK 2 -->
			<div class="ksob-panel" id="ksob-p2">
				<div class="ksob-card ksob-center">
					<div id="ob-test-spinner" class="ksob-spinner"></div>
					<div id="ob-test-result"></div>
					<div class="ksob-actions" style="justify-content:center;margin-top:16px;">
						<button type="button" class="ksob-btn" id="ob-back-1"><?php esc_html_e( '← Popraw dane', 'prostafaktura-ksef' ); ?></button>
						<button type="button" class="ksob-btn ksob-btn-primary" id="ob-retry-test"><?php esc_html_e( 'Testuj ponownie', 'prostafaktura-ksef' ); ?></button>
						<button type="button" class="ksob-btn ksob-btn-primary" id="ob-to-3" style="display:none;"><?php esc_html_e( 'Dalej →', 'prostafaktura-ksef' ); ?></button>
					</div>
				</div>
			</div>

			<!-- KROK 3 -->
			<div class="ksob-panel" id="ksob-p3">
				<div class="ksob-card ksob-center">
					<div class="ksob-done">✓</div>
					<h2><?php esc_html_e( 'Konto KSeF połączone!', 'prostafaktura-ksef' ); ?></h2>
					<p class="ksob-hint"><?php esc_html_e( 'Możesz już wystawiać faktury. Zacznij od pierwszej.', 'prostafaktura-ksef' ); ?></p>
					<div class="ksob-actions" style="justify-content:center;flex-wrap:wrap;">
						<a class="ksob-btn ksob-btn-primary" href="<?php echo esc_url( $invoice_url ); ?>"><?php esc_html_e( 'Wystaw pierwszą fakturę', 'prostafaktura-ksef' ); ?></a>
						<button type="button" class="ksob-btn" id="ob-test-invoice" style="display:none;"><?php esc_html_e( 'Wyślij fakturę testową do piaskownicy', 'prostafaktura-ksef' ); ?></button>
					</div>
					<div id="ob-ti-result" style="margin-top:14px;"></div>
				</div>
			</div>
		</div>

		<?php ob_start(); ?>
		.ksob-wrap{max-width:760px;margin:24px auto;font-family:-apple-system,"Segoe UI",Roboto,sans-serif;color:#1a1d21;}
		.ksob-head h1{font-size:26px;font-weight:800;margin:0 0 4px;}
		.ksob-head p{color:#6b7280;margin:0 0 18px;font-size:14px;}
		.ksob-steps{display:flex;gap:8px;margin-bottom:18px;}
		.ksob-step{flex:1;display:flex;align-items:center;gap:8px;background:#f3f4f6;border-radius:10px;padding:10px 14px;font-size:13px;font-weight:600;color:#9ca3af;}
		.ksob-step span{width:24px;height:24px;border-radius:50%;background:#d1d5db;color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;}
		.ksob-step.is-active{background:#fff2eb;color:#d9531e;}
		.ksob-step.is-active span{background:#d9531e;}
		.ksob-step.is-done span{background:#16a34a;}
		.ksob-panel{display:none;}
		.ksob-panel.is-active{display:block;}
		.ksob-card{background:#fff;border:1px solid #e7eaee;border-radius:14px;padding:22px 24px;}
		.ksob-center{text-align:center;}
		.ksob-lbl{display:block;font-size:12px;color:#6b7280;margin:12px 0 5px;font-weight:600;}
		.ksob-card input[type=text],.ksob-card input[type=email],.ksob-card textarea{width:100%;padding:10px 12px;border:1px solid #d1d5db;border-radius:8px;font-size:14px;box-sizing:border-box;}
		.ksob-card textarea{font-family:'SF Mono',Menlo,monospace;font-size:12px;}
		.ksob-grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
		.ksob-hint{font-size:12px;color:#6b7280;margin:6px 0 0;}
		.ksob-seg{display:inline-flex;gap:6px;}
		.ksob-seg-item{border:1px solid #d1d5db;border-radius:8px;padding:8px 14px;font-size:13px;cursor:pointer;}
		.ksob-seg-item.is-on{border-color:#d9531e;background:#fff2eb;color:#d9531e;font-weight:600;}
		.ksob-more{margin-top:10px;}
		.ksob-more summary{cursor:pointer;color:#5B5BD6;font-size:13px;font-weight:600;}
		.ksob-actions{display:flex;gap:10px;align-items:center;margin-top:18px;}
		.ksob-btn{border:1px solid #d1d5db;background:#fff;border-radius:9px;padding:11px 18px;font-size:14px;font-weight:600;cursor:pointer;color:#374151;text-decoration:none;display:inline-flex;align-items:center;}
		.ksob-btn-primary{background:#d9531e;border-color:#d9531e;color:#fff;}
		.ksob-btn-primary:hover{opacity:.92;color:#fff;}
		.ksob-btn[disabled]{opacity:.5;cursor:not-allowed;}
		.ksob-msg{font-size:13px;}
		.ksob-spinner{width:34px;height:34px;border:3px solid #eee;border-top-color:#d9531e;border-radius:50%;animation:ksobspin .8s linear infinite;margin:6px auto 14px;}
		@keyframes ksobspin{to{transform:rotate(360deg);}}
		.ksob-done{width:56px;height:56px;border-radius:50%;background:#dcfce7;color:#16a34a;font-size:30px;display:flex;align-items:center;justify-content:center;margin:0 auto 10px;}
		.ksob-ok{color:#15803d;font-weight:700;font-size:16px;}
		.ksob-err{color:#b91c1c;font-weight:700;font-size:15px;}
		@media(max-width:640px){.ksob-grid2{grid-template-columns:1fr;}}
		<?php Modern_Shell::inline_style( 'ksef-onboarding', ob_get_clean() ); ob_start(); ?>
		(function(){
			const AJAX=<?php echo wp_json_encode( $ajax ); ?>, NONCE=<?php echo wp_json_encode( $nonce ); ?>;
			let credId=0, env='test', testNonce='';
			function esc(s){return String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}
			function go(step){
				document.querySelectorAll('.ksob-panel').forEach(p=>p.classList.remove('is-active'));
				document.getElementById('ksob-p'+step).classList.add('is-active');
				document.querySelectorAll('.ksob-step').forEach(s=>{
					const n=+s.dataset.step; s.classList.toggle('is-active',n===step); s.classList.toggle('is-done',n<step);
				});
				window.scrollTo({top:0,behavior:'smooth'});
			}
			// segment env
			document.querySelectorAll('input[name=ob_env]').forEach(r=>r.addEventListener('change',()=>{
				document.querySelectorAll('.ksob-seg-item').forEach(i=>i.classList.toggle('is-on',i.querySelector('input').checked));
				env=document.querySelector('input[name=ob_env]:checked').value;
			}));
			// Krok 1 → zapisz
			document.getElementById('ob-save').addEventListener('click',async function(){
				const msg=document.getElementById('ob-save-msg'); msg.textContent=''; msg.className='ksob-msg';
				const nip=(document.getElementById('ob_nip').value||'').replace(/\D/g,'');
				if(nip.length!==10){ msg.textContent='NIP musi mieć 10 cyfr.'; msg.className='ksob-msg ksob-err'; return; }
				if(!(document.getElementById('ob_token').value||'').trim()){ msg.textContent='Wklej token KSeF.'; msg.className='ksob-msg ksob-err'; return; }
				this.disabled=true; this.textContent='Zapisuję…';
				try{
					const fd=new FormData();
					fd.append('action','ksef_onboard_create'); fd.append('nonce',NONCE);
					fd.append('nip',nip); fd.append('seller_name',document.getElementById('ob_name').value);
					fd.append('ksef_environment',env); fd.append('token',document.getElementById('ob_token').value);
					fd.append('seller_street',document.getElementById('ob_street').value);
					fd.append('seller_building',document.getElementById('ob_building').value);
					fd.append('seller_postal',document.getElementById('ob_postal').value);
					fd.append('seller_city',document.getElementById('ob_city').value);
					fd.append('seller_email',document.getElementById('ob_email').value);
					const r=await fetch(AJAX,{method:'POST',body:fd,credentials:'same-origin'});
					const j=await r.json();
					if(!j.success){ msg.textContent=(j.data&&j.data.message)||'Błąd zapisu.'; msg.className='ksob-msg ksob-err'; return; }
					credId=j.data.credential_id; env=j.data.environment; testNonce=j.data.test_nonce;
					go(2); runTest();
				}catch(e){ msg.textContent='Błąd sieci.'; msg.className='ksob-msg ksob-err'; }
				finally{ this.disabled=false; this.textContent='Zapisz i testuj połączenie →'; }
			});
			// Krok 2 → test połączenia (reużywa ksef_test_connection)
			async function runTest(){
				const sp=document.getElementById('ob-test-spinner'), res=document.getElementById('ob-test-result');
				const to3=document.getElementById('ob-to-3'), retry=document.getElementById('ob-retry-test');
				sp.style.display='block'; res.innerHTML=''; to3.style.display='none'; retry.style.display='none';
				try{
					const fd=new FormData();
					fd.append('action','ksef_test_connection'); fd.append('nonce',testNonce); fd.append('credential_id',credId);
					const r=await fetch(AJAX,{method:'POST',body:fd,credentials:'same-origin'});
					const j=await r.json();
					sp.style.display='none';
					if(j.success){
						res.innerHTML='<div class="ksob-ok">✓ Połączenie z KSeF działa</div><p class="ksob-hint">NIP '+esc(j.data.nip||'')+' · środowisko '+esc(j.data.environment||'')+'</p>';
						to3.style.display='inline-flex';
					}else{
						const d=j.data||{};
						res.innerHTML='<div class="ksob-err">✗ '+esc(d.message||'Nie udało się połączyć')+'</div>'+(d.is_network?'<p class="ksob-hint">To problem sieci/MF, nie tokenu — spróbuj ponownie za chwilę.</p>':'<p class="ksob-hint">Sprawdź token i środowisko, potem testuj ponownie.</p>');
						retry.style.display='inline-flex';
					}
				}catch(e){ sp.style.display='none'; res.innerHTML='<div class="ksob-err">✗ Błąd sieci</div>'; retry.style.display='inline-flex'; }
			}
			document.getElementById('ob-retry-test').addEventListener('click',runTest);
			document.getElementById('ob-back-1').addEventListener('click',()=>go(1));
			document.getElementById('ob-to-3').addEventListener('click',()=>{
				go(3);
				if(env==='test'){ document.getElementById('ob-test-invoice').style.display='inline-flex'; }
			});
			// Krok 3 → faktura testowa (tylko test)
			document.getElementById('ob-test-invoice').addEventListener('click',async function(){
				const out=document.getElementById('ob-ti-result');
				this.disabled=true; const old=this.textContent; this.textContent='Wysyłam…'; out.innerHTML='';
				try{
					const fd=new FormData();
					fd.append('action','ksef_onboard_test_invoice'); fd.append('nonce',NONCE); fd.append('credential_id',credId);
					const r=await fetch(AJAX,{method:'POST',body:fd,credentials:'same-origin'});
					const j=await r.json();
					if(j.success){
						if(j.data.status==='confirmed'){
							out.innerHTML='<div class="ksob-ok">✓ Faktura testowa zaakceptowana przez KSeF</div><p class="ksob-hint">Numer KSeF: <code>'+esc(j.data.ksef_number||'—')+'</code></p>';
						}else{
							out.innerHTML='<div class="ksob-ok">✓ Faktura testowa wysłana</div><p class="ksob-hint">Status: '+esc(j.data.status)+' — potwierdzenie pojawi się za chwilę.</p>';
						}
					}else{
						const d=j.data||{};
						out.innerHTML='<div class="ksob-err">✗ '+esc(d.message||'Błąd')+'</div>'+(d.hint?'<p class="ksob-hint">'+esc(d.hint)+'</p>':'');
					}
				}catch(e){ out.innerHTML='<div class="ksob-err">✗ Błąd sieci</div>'; }
				finally{ this.disabled=false; this.textContent=old; }
			});
		})();
		<?php Modern_Shell::inline_script( 'ksef-onboarding', ob_get_clean() ); ?>
		<?php
	}
}
