/**
 * Frontierline Forms - マルチステップフォーム + 確認画面
 *
 * @package CF7MasterPro
 */

( function () {
	'use strict';

	class CF7MPMultiStep {
		constructor( form ) {
			this.form = form;
			this.cfg = window.cf7mpFrontend || {};
			this.enableConfirm = !! this.cfg.enableConfirmation;
			this.isAdmin = !! this.cfg.isAdmin;

			this.steps = Array.from( form.querySelectorAll( '.cf7mp-multistep__step' ) );

			// シングルステップ + 確認画面有効 → 仮想ステップ化
			if ( ! this.steps.length && this.enableConfirm ) {
				this.wrapSingleStep();
				this.steps = Array.from( form.querySelectorAll( '.cf7mp-multistep__step' ) );
			}

			this.currentStep = 0;
			this.totalSteps = this.steps.length;
			if ( ! this.totalSteps ) {
				return;
			}

			// 確認画面ステップ追加
			if ( this.enableConfirm ) {
				let existingConfirm = form.querySelector( '.cf7mp-multistep__step[data-role="confirmation"]' );

				// フォールバック: 最終ステップがタイトル「確認」「Confirmation」「Confirm」or 空 で
				// 入力フィールドを含まない場合、確認画面ステップとみなす
				if ( ! existingConfirm ) {
					const last = this.steps[ this.steps.length - 1 ];
					if ( last ) {
						const title = ( last.dataset.title || '' ).trim().toLowerCase();
						const hasInputField = !! last.querySelector( 'input:not([type="hidden"]):not([type="submit"]), textarea, select' );
						const titleMatch = ( '' === title || '確認' === title || 'confirmation' === title || 'confirm' === title );
						if ( titleMatch && ! hasInputField ) {
							last.dataset.role = 'confirmation';
							if ( ! last.dataset.title ) {
								last.dataset.title = '確認';
							}
							existingConfirm = last;
						}
					}
				}

				if ( existingConfirm ) {
					this.ensureConfirmContainer( existingConfirm );
				} else {
					this.buildConfirmStep();
				}
				this.steps = Array.from( form.querySelectorAll( '.cf7mp-multistep__step' ) );
				this.totalSteps = this.steps.length;
			}

			this.init();
		}

		/**
		 * シングルステップフォームを仮想ステップ化
		 * （マルチステップでないフォームにも確認画面を適用するため）
		 */
		wrapSingleStep() {
			const submit = this.form.querySelector( '[type="submit"]' );
			const hidden = this.form.querySelector( '.hidden-fields-container' );
			const stepDiv = document.createElement( 'div' );
			stepDiv.className = 'cf7mp-multistep__step';
			stepDiv.dataset.step = '1';
			stepDiv.dataset.title = '入力';

			// hidden-fields-container の後ろから submit の前までを step1 に移動
			const start = hidden ? hidden.nextSibling : this.form.firstChild;
			let node = start;
			while ( node && node !== submit ) {
				const next = node.nextSibling;
				if ( submit && node.contains && node.contains( submit ) ) {
					break;
				}
				stepDiv.appendChild( node );
				node = next;
			}
			if ( submit && submit.parentNode ) {
				submit.parentNode.insertBefore( stepDiv, submit );
			} else {
				this.form.appendChild( stepDiv );
			}
		}

		/**
		 * 確認画面ステップを最終追加
		 */
		buildConfirmStep() {
			const confirmStep = document.createElement( 'div' );
			confirmStep.className = 'cf7mp-multistep__step cf7mp-confirm';
			confirmStep.dataset.step = String( this.steps.length + 1 );
			confirmStep.dataset.title = '確認';
			confirmStep.dataset.role = 'confirmation';
			confirmStep.innerHTML = '<div class="cf7mp-confirm__intro">入力内容をご確認のうえ、送信してください。</div><dl class="cf7mp-confirm__list" aria-label="入力内容"></dl>';

			const submit = this.form.querySelector( '[type="submit"]' );
			if ( submit && submit.parentNode ) {
				submit.parentNode.insertBefore( confirmStep, submit );
			} else {
				this.form.appendChild( confirmStep );
			}
		}

		/**
		 * 既存confirmation roleステップに表示用コンテナを保証
		 */
		ensureConfirmContainer( stepEl ) {
			stepEl.classList.add( 'cf7mp-confirm' );
			if ( ! stepEl.querySelector( '.cf7mp-confirm__list' ) ) {
				const intro = document.createElement( 'div' );
				intro.className = 'cf7mp-confirm__intro';
				intro.textContent = '入力内容をご確認のうえ、送信してください。';
				const list = document.createElement( 'dl' );
				list.className = 'cf7mp-confirm__list';
				list.setAttribute( 'aria-label', '入力内容' );
				stepEl.appendChild( intro );
				stepEl.appendChild( list );
			}
		}

		/**
		 * 確認画面に入力値を反映
		 */
		fillConfirmStep() {
			const confirmStep = this.form.querySelector( '[data-role="confirmation"] .cf7mp-confirm__list' );
			if ( ! confirmStep ) {
				return;
			}
			confirmStep.innerHTML = '';

			// 入力ステップから値を集約
			const inputSteps = Array.from( this.form.querySelectorAll( '.cf7mp-multistep__step' ) )
				.filter( ( s ) => 'confirmation' !== s.dataset.role );

			inputSteps.forEach( ( step ) => {
				const fields = step.querySelectorAll( 'input, textarea, select' );
				const seen = new Set();
				fields.forEach( ( f ) => {
					if ( ! f.name || 'submit' === f.type || 'hidden' === f.type || 'button' === f.type ) {
						return;
					}
					if ( f.name.indexOf( 'cf7mp_hp_' ) === 0 ) {
						return;
					}
					if ( ( 'checkbox' === f.type || 'radio' === f.type ) && ! f.checked ) {
						return;
					}
					const labelText = this.findLabel( f );
					const value = this.getFieldDisplayValue( f );
					if ( ! value ) {
						return;
					}
					const dedupeKey = f.name + '||' + ( 'checkbox' === f.type || 'radio' === f.type ? '' : value );
					if ( seen.has( dedupeKey ) ) {
						return;
					}
					seen.add( dedupeKey );

					const dt = document.createElement( 'dt' );
					dt.className = 'cf7mp-confirm__label';
					dt.textContent = labelText;
					const dd = document.createElement( 'dd' );
					dd.className = 'cf7mp-confirm__value';
					dd.textContent = value;
					confirmStep.appendChild( dt );
					confirmStep.appendChild( dd );
				} );
			} );
		}

		/**
		 * フィールドのラベル文字列推定
		 */
		findLabel( field ) {
			const wrap = field.closest( 'label' );
			if ( wrap ) {
				const clone = wrap.cloneNode( true );
				clone.querySelectorAll( 'input, textarea, select, .wpcf7-form-control-wrap, br, span[style*="color:red"]' ).forEach( ( n ) => n.remove() );
				const t = clone.textContent.replace( /[\s\*]+$/g, '' ).trim();
				if ( t ) {
					return t;
				}
			}
			return field.name;
		}

		/**
		 * 表示用の値文字列
		 */
		getFieldDisplayValue( field ) {
			if ( 'checkbox' === field.type || 'radio' === field.type ) {
				return field.value;
			}
			if ( 'SELECT' === field.tagName ) {
				return Array.from( field.selectedOptions ).map( ( o ) => o.textContent.trim() ).join( ', ' );
			}
			return ( field.value || '' ).trim();
		}

		init() {
			this.buildProgress();
			this.buildNav();
			this.showStep( 0 );
			this.bindEvents();
			this.bindAutoClear();
			// 管理者は下書き読み込まない（テスト時の邪魔回避）
			if ( ! this.isAdmin ) {
				this.loadDraft();
			} else {
				this.buildResetButton();
			}
		}

		/**
		 * CF7送信成功イベント→下書き自動クリア
		 */
		bindAutoClear() {
			const handler = ( e ) => {
				// 全フォーム共通イベントなので、自フォームか確認
				const targetForm = e.target && e.target.closest ? e.target.closest( '.wpcf7-form' ) : null;
				if ( targetForm && targetForm !== this.form ) {
					return;
				}
				this.clearDraft();

				// 完了後リダイレクト（指定時はサンクスページへ＝CV計測）
				const url = ( this.cfg.redirectUrl || '' ).trim();
				if ( /^https?:\/\//i.test( url ) ) {
					window.location.href = url;
					return;
				}
				// 完了画面表示
				this.showComplete();
			};
			document.addEventListener( 'wpcf7mailsent', handler );
			this.form.addEventListener( 'wpcf7mailsent', handler );
		}

		/**
		 * 送信完了画面（フォームを完了パネルに差し替え）
		 */
		showComplete() {
			const def = '送信が完了しました。\nお問い合わせありがとうございます。\n担当者より追ってご連絡いたします。';
			const msg = ( this.cfg.completeMessage || '' ).trim() || def;
			this.form.classList.add( 'cf7mp-completed' );

			// フォーム要素を隠す
			[ '.cf7mp-multistep__nav', '.wpcf7-response-output' ].forEach( ( sel ) => {
				const el = this.form.querySelector( sel );
				if ( el ) { el.style.display = 'none'; }
			} );

			// ステッパー: 全入力ステップ完了＋「完了」ドット点灯（入力→確認→完了）
			if ( this.progress ) {
				const dots = this.progress.querySelectorAll( '.cf7mp-progress__step' );
				dots.forEach( ( d, i ) => {
					d.classList.remove( 'cf7mp-progress__step--active' );
					d.classList.add( 'cf7mp-progress__step--completed' );
					if ( i === dots.length - 1 ) {
						d.classList.add( 'cf7mp-progress__step--active' );
					}
				} );
				if ( this.progressFill ) { this.progressFill.style.width = '100%'; }
			}
			this.steps.forEach( ( s ) => { s.style.display = 'none'; } );
			const submit = this.form.querySelector( '[type="submit"]' );
			if ( submit ) { submit.style.display = 'none'; }
			const reset = this.form.querySelector( '.cf7mp-multistep__reset' );
			if ( reset ) { reset.style.display = 'none'; }

			let panel = this.form.querySelector( '.cf7mp-multistep__complete' );
			if ( ! panel ) {
				panel = document.createElement( 'div' );
				panel.className = 'cf7mp-multistep__complete';
				panel.setAttribute( 'role', 'status' );
				panel.innerHTML = '<div class="cf7mp-multistep__complete-icon" aria-hidden="true">✓</div><div class="cf7mp-multistep__complete-text"></div>';
				const wrap = this.form.querySelector( '.cf7mp-multistep' ) || this.form;
				wrap.appendChild( panel );
			}
			panel.querySelector( '.cf7mp-multistep__complete-text' ).textContent = msg;
			panel.style.display = 'block';
			try { panel.scrollIntoView( { behavior: 'smooth', block: 'center' } ); } catch ( err ) {}
		}

		/**
		 * 下書きリセットボタン（管理者表示時のみ）
		 */
		buildResetButton() {
			const btn = document.createElement( 'button' );
			btn.type = 'button';
			btn.className = 'cf7mp-multistep__reset';
			btn.innerHTML = '<span class="cf7mp-size-badge__admin">管理者</span> 下書きリセット';
			btn.addEventListener( 'click', () => {
				this.clearDraft();
				this.form.reset();
				this.currentStep = 0;
				this.showStep( 0 );
			} );
			this.form.appendChild( btn );
		}

		clearDraft() {
			try {
				localStorage.removeItem( this.getStorageKey() );
			} catch ( e ) {}
		}

		buildProgress() {
			const wrapper = document.createElement( 'div' );
			const style = this.cfg.progressStyle || 'step';
			wrapper.className = 'cf7mp-progress cf7mp-progress--style-' + style;

			if ( 'bar' === style ) {
				const fill = document.createElement( 'span' );
				fill.className = 'cf7mp-progress__fill';
				fill.style.width = ( 100 / Math.max( 1, this.steps.length ) ) + '%';
				wrapper.appendChild( fill );
				this.progressFill = fill;
			} else {
				this.steps.forEach( ( step, idx ) => {
					const stepEl = document.createElement( 'div' );
					stepEl.className = 'cf7mp-progress__step';
					stepEl.dataset.step = idx;
					stepEl.innerHTML = '<div class="cf7mp-progress__step-circle">' + ( idx + 1 ) + '</div><div class="cf7mp-progress__step-label">' + ( step.dataset.title || '' ) + '</div>';
					wrapper.appendChild( stepEl );
				} );

				// 表示専用「完了」ドット（入力→確認→完了の標準3ステップ表示／非ナビゲート）
				if ( false !== this.cfg.showCompleteStep ) {
					const doneEl = document.createElement( 'div' );
					doneEl.className = 'cf7mp-progress__step cf7mp-progress__step--final';
					doneEl.dataset.step = 'done';
					doneEl.innerHTML = '<div class="cf7mp-progress__step-circle">' + ( this.steps.length + 1 ) + '</div><div class="cf7mp-progress__step-label">' + ( ( this.cfg.completeLabel || '完了' ) ) + '</div>';
					wrapper.appendChild( doneEl );
					this.hasFinalDot = true;
				}
			}

			this.form.insertBefore( wrapper, this.form.firstChild );
			this.progress = wrapper;
		}

		buildNav() {
			const nav = document.createElement( 'div' );
			nav.className = 'cf7mp-multistep__nav';
			nav.innerHTML = '<button type="button" class="cf7mp-multistep__btn cf7mp-multistep__btn--prev" data-action="prev">戻る</button><button type="button" class="cf7mp-multistep__btn cf7mp-multistep__btn--next" data-action="next">次へ</button>';
			const submit = this.form.querySelector( '[type="submit"]' );
			if ( submit ) {
				submit.style.display = 'none';
				nav.querySelector( '[data-action="next"]' ).insertAdjacentElement( 'afterend', submit );
			}
			this.form.appendChild( nav );
			this.nav = nav;
		}

		bindEvents() {
			this.nav.addEventListener( 'click', ( e ) => {
				const action = e.target.dataset.action;
				if ( 'next' === action ) {
					this.next();
				} else if ( 'prev' === action ) {
					this.prev();
				}
			} );

			// 自動保存
			this.form.addEventListener( 'input', this.debounce( () => this.saveDraft(), 500 ) );
		}

		showStep( idx ) {
			try { document.dispatchEvent( new CustomEvent( 'cf7mp:step', { detail: { step: idx + 1 } } ) ); } catch ( e ) {}
			this.steps.forEach( ( s, i ) => {
				s.classList.toggle( 'cf7mp-multistep__step--active', i === idx );
			} );

			// 確認画面表示直前に値を反映
			const active = this.steps[ idx ];
			if ( active && 'confirmation' === active.dataset.role ) {
				this.fillConfirmStep();
			}

			this.progress.querySelectorAll( '.cf7mp-progress__step' ).forEach( ( s, i ) => {
				if ( s.classList.contains( 'cf7mp-progress__step--final' ) ) {
					return; // 完了ドットは送信後に点灯
				}
				s.classList.remove( 'cf7mp-progress__step--active', 'cf7mp-progress__step--completed' );
				if ( i < idx ) {
					s.classList.add( 'cf7mp-progress__step--completed' );
				} else if ( i === idx ) {
					s.classList.add( 'cf7mp-progress__step--active' );
				}
			} );

			// bar style: fill width 更新
			if ( this.progressFill ) {
				this.progressFill.style.width = ( ( idx + 1 ) / Math.max( 1, this.totalSteps ) * 100 ) + '%';
			}

			const prevBtn = this.nav.querySelector( '[data-action="prev"]' );
			const nextBtn = this.nav.querySelector( '[data-action="next"]' );
			const submit = this.form.querySelector( '[type="submit"]' );

			prevBtn.disabled = 0 === idx;
			if ( idx === this.totalSteps - 1 ) {
				nextBtn.style.display = 'none';
				if ( submit ) {
					submit.style.display = 'inline-flex';
				}
			} else {
				nextBtn.style.display = 'inline-flex';
				if ( submit ) {
					submit.style.display = 'none';
				}
			}
		}

		next() {
			if ( ! this.validateStep( this.currentStep ) ) {
				return;
			}
			if ( this.currentStep < this.totalSteps - 1 ) {
				this.currentStep++;
				this.showStep( this.currentStep );
			}
		}

		prev() {
			if ( this.currentStep > 0 ) {
				this.currentStep--;
				this.showStep( this.currentStep );
			}
		}

		validateStep( idx ) {
			const step = this.steps[ idx ];
			if ( 'confirmation' === step.dataset.role ) {
				return true;
			}
			const requiredFields = step.querySelectorAll( '[aria-required="true"], [required]' );
			let valid = true;
			requiredFields.forEach( ( field ) => {
				if ( ! field.value.trim() ) {
					field.classList.add( 'cf7mp-error' );
					valid = false;
				} else {
					field.classList.remove( 'cf7mp-error' );
				}
			} );
			return valid;
		}

		saveDraft() {
			// 管理者は保存しない（テスト時の蓄積防止）
			if ( this.isAdmin ) {
				return;
			}
			const data = new FormData( this.form );
			const obj = {};
			data.forEach( ( v, k ) => {
				obj[ k ] = v;
			} );
			try {
				localStorage.setItem( this.getStorageKey(), JSON.stringify( obj ) );
			} catch ( e ) {}
		}

		loadDraft() {
			try {
				const raw = localStorage.getItem( this.getStorageKey() );
				if ( ! raw ) {
					return;
				}
				const obj = JSON.parse( raw );
				Object.keys( obj ).forEach( ( k ) => {
					const field = this.form.querySelector( '[name="' + k + '"]' );
					if ( field ) {
						field.value = obj[ k ];
					}
				} );
			} catch ( e ) {}
		}

		getStorageKey() {
			// .cf7mp-multistep の data-form-id か _wpcf7 hidden value を使用
			const multistep = this.form.querySelector( '.cf7mp-multistep' );
			const cf7Input = this.form.querySelector( 'input[name="_wpcf7"]' );
			const formId = ( multistep && multistep.dataset.formId ) || ( cf7Input && cf7Input.value ) || '0';
			return 'cf7mp_draft_' + formId;
		}

		debounce( fn, wait ) {
			let timer;
			return ( ...args ) => {
				clearTimeout( timer );
				timer = setTimeout( () => fn.apply( this, args ), wait );
			};
		}
	}

	document.addEventListener( 'DOMContentLoaded', () => {
		const cfg = window.cf7mpFrontend || {};
		document.querySelectorAll( '.wpcf7-form' ).forEach( ( form ) => {
			const hasMultistep = !! form.querySelector( '.cf7mp-multistep__step' );
			if ( hasMultistep || cfg.enableConfirmation ) {
				new CF7MPMultiStep( form );
			}
		} );
	} );
} )();
