/**
 * 団体申込フォーム（代表者オプション + スタッフ追加）
 *
 * @param {Object}   props
 * @param {Object}   props.selectedEvent    選択済みイベント
 * @param {Object}   props.member           代表者の会員情報
 * @param {Array}    props.sessions         セッション一覧
 * @param {Function} props.onSubmit         送信コールバック(data)
 * @param {Function} props.onBack           戻るコールバック
 */
import { useState, useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { decorateMemberTypeLabels } from '../../common/member-type-label';

const MEMBER_TYPE_LABELS_BASE = {
	regular: __( 'Regular Member', 'conferencemanager' ),
	student: __( 'Student Member', 'conferencemanager' ),
	associate: __( 'Associate Member', 'conferencemanager' ),
	honorary: __( 'Honorary Member', 'conferencemanager' ),
	general: __( 'Non-member', 'conferencemanager' ),
};

// 🔴 表示名の装飾はここ 1 箇所だけ。**元の定義（上）は 1 文字も変えない。**
// 学会の略称（初期設定）が入っていれば標準 5 区分にだけ前置する。
// ⚠️ サーバから来る値（`fee_type_label` など）は**サーバ側でだけ**装飾している。
//    ここで二重に通さないこと。
const MEMBER_TYPE_LABELS = decorateMemberTypeLabels( MEMBER_TYPE_LABELS_BASE );

const MEMBER_TYPES_ORDER = [ 'regular', 'student', 'associate', 'honorary', 'general' ];

const EMPTY_STAFF = { name: '', email: '', participation_type: 'onsite', fee_type: '', session_options: [] };

export default function GroupRegistrationForm( { selectedEvent, member, sessions, onSubmit, onBack } ) {
	// fee_rules に member_type が存在しなければ最初の有効キーにフォールバック
	const getInitialFeeType = () => {
		const rules = selectedEvent?.fee_rules || {};
		if ( rules[ member.member_type ] ) return member.member_type;
		// 固定種別から探す
		for ( const key of MEMBER_TYPES_ORDER ) {
			if ( rules[ key ] ) return key;
		}
		// カスタム種別から探す
		const labels = rules._labels || {};
		const customKeys = Object.keys( labels );
		if ( customKeys.length > 0 && rules[ customKeys[ 0 ] ] ) return customKeys[ 0 ];
		return 'regular';
	};
	const [ feeType, setFeeType ] = useState( getInitialFeeType );

	/**
	 * 料金が設定されている参加形態だけを返す
	 *
	 * 📌 画面側の出し分けでしかない。サーバー側（RegistrationManager::create() /
	 *    GroupRegistration::add_staff()）が同じ判定で断る。
	 *    料金表が空、またはその区分の行が無い場合は従来どおり両方出す。
	 */
	const availableParticipationTypes = ( typeKey ) => {
		const all = [ 'onsite', 'online' ];
		const rules = selectedEvent?.current_fee_rules || selectedEvent?.fee_rules || {};
		const { _labels: ignored, ...typeRules } = rules;
		if ( Object.keys( typeRules ).length === 0 ) return all;

		const row = typeRules[ typeKey ];
		if ( ! row || typeof row !== 'object' ) return all;

		const offered = all.filter( ( pt ) => Object.prototype.hasOwnProperty.call( row, pt ) );
		return offered.length > 0 ? offered : all;
	};
	const [ participationType, setParticipationType ] = useState( 'onsite' );
	const [ selectedSessions, setSelectedSessions ] = useState( [] );
	const [ paymentMethod, setPaymentMethod ] = useState( 'bank' );
	const [ transferNote, setTransferNote ] = useState( '' );
	const [ staffList, setStaffList ] = useState( [ { ...EMPTY_STAFF } ] );
	const [ loading, setLoading ] = useState( false );
	const [ error, setError ] = useState( null );

	// イベントの料金種別オプションを生成（前売/当日の解決済み料金を使用）
	const getFeeTypeOptions = () => {
		if ( ! selectedEvent ) return [];
		const rules = selectedEvent.current_fee_rules || selectedEvent.fee_rules || {};
		const labels = rules._labels || {};
		const options = [];
		MEMBER_TYPES_ORDER.forEach( ( key ) => {
			if ( rules[ key ] ) {
				options.push( { value: key, label: MEMBER_TYPE_LABELS[ key ] || key } );
			}
		} );
		Object.keys( labels ).forEach( ( key ) => {
			if ( rules[ key ] ) {
				options.push( { value: key, label: labels[ key ] || key } );
			}
		} );
		return options;
	};

	const toggleSession = ( id ) => {
		setSelectedSessions( ( prev ) =>
			prev.includes( id ) ? prev.filter( ( s ) => s !== id ) : [ ...prev, id ]
		);
	};

	const addStaff = () => {
		setStaffList( ( prev ) => [ ...prev, { ...EMPTY_STAFF } ] );
	};

	const removeStaff = ( index ) => {
		setStaffList( ( prev ) => prev.filter( ( _, i ) => i !== index ) );
	};

	const updateStaff = ( index, field, value ) => {
		setStaffList( ( prev ) => prev.map( ( s, i ) =>
			i === index ? { ...s, [ field ]: value } : s
		) );
	};

	const toggleStaffSession = ( index, sessionId ) => {
		setStaffList( ( prev ) => prev.map( ( s, i ) => {
			if ( i !== index ) return s;
			const opts = s.session_options || [];
			return {
				...s,
				session_options: opts.includes( sessionId )
					? opts.filter( ( id ) => id !== sessionId )
					: [ ...opts, sessionId ],
			};
		} ) );
	};

	// 料金プレビュー計算（前売/当日の解決済み料金を使用）
	const getBaseFee = useCallback( ( type, pType ) => {
		const rules = selectedEvent?.current_fee_rules || selectedEvent?.fee_rules;
		if ( ! rules ) return 0;
		return rules[ type ]?.[ pType ] || 0;
	}, [ selectedEvent ] );

	const representativeFee = getBaseFee( feeType, participationType );
	const sessionFee = selectedSessions.reduce( ( sum, sid ) => {
		const s = sessions.find( ( sess ) => sess.id === sid );
		return sum + ( s ? s.fee : 0 );
	}, 0 );
	const getStaffSessionFee = ( staff ) => {
		return ( staff.session_options || [] ).reduce( ( sum, sid ) => {
			const s = sessions.find( ( sess ) => sess.id === sid );
			return sum + ( s ? s.fee : 0 );
		}, 0 );
	};
	const staffTotalFee = staffList.reduce( ( sum, s ) => {
		return sum + getBaseFee( s.fee_type || feeType, s.participation_type || 'onsite' ) + getStaffSessionFee( s );
	}, 0 );
	const totalAmount = representativeFee + sessionFee + staffTotalFee;
	const taxRate = selectedEvent?.tax_rate || 10;
	const taxAmount = taxRate > 0 ? Math.floor( totalAmount * taxRate / 100 ) : 0;

	const handleSubmit = async () => {
		// バリデーション: 各スタッフの氏名・メール入力チェック
		const incomplete = [];
		staffList.forEach( ( s, i ) => {
			if ( s.name && ! s.email ) {
				incomplete.push( ( i + 1 ) + __( 'th staff: email address is missing', 'conferencemanager' ) );
			} else if ( ! s.name && s.email ) {
				incomplete.push( ( i + 1 ) + __( 'th staff: name is missing', 'conferencemanager' ) );
			}
		} );
		if ( incomplete.length > 0 ) {
			setError( incomplete.join( '\n' ) );
			return;
		}

		const validStaff = staffList.filter( ( s ) => s.name && s.email );
		if ( validStaff.length === 0 ) {
			setError( __( 'Please add at least one staff member with name and email address.', 'conferencemanager' ) );
			return;
		}

		// メールアドレスの重複チェック
		const emails = validStaff.map( ( s ) => s.email.toLowerCase().trim() );
		const duplicates = emails.filter( ( e, i ) => emails.indexOf( e ) !== i );
		if ( duplicates.length > 0 ) {
			setError( __( 'The same email address is used for multiple staff members.', 'conferencemanager' ) );
			return;
		}

		setLoading( true );
		setError( null );
		try {
			const data = await apiFetch( {
				path: '/conf-manager/v1/public/group-registrations',
				method: 'POST',
				data: {
					event_id: selectedEvent.id,
					representative: {
						member_id: member.id,
						email_hash: member.email_hash,
						participation_type: participationType,
						payment_method: paymentMethod,
						transfer_note: paymentMethod === 'bank' ? transferNote : '',
						fee_type: feeType,
						session_options: selectedSessions,
					},
					staff: validStaff.map( ( s ) => ( {
						name: s.name,
						email: s.email,
						participation_type: s.participation_type,
						fee_type: s.fee_type || feeType,
						session_options: s.session_options || [],
					} ) ),
				},
			} );
			onSubmit( data );
		} catch ( err ) {
			setError( err.message );
		} finally {
			setLoading( false );
		}
	};

	const feeTypeLabel = MEMBER_TYPE_LABELS[ feeType ] || selectedEvent?.fee_rules?._labels?.[ feeType ] || feeType;

	return (
		<div>
			<h3>{ __( 'Group Registration', 'conferencemanager' ) }</h3>

			{ error && <div className="conf-manager-form__error">{ error }</div> }

			{ selectedEvent?.advance_fee_deadline && (
				<div className={ `conf-manager-form__fee-notice ${ selectedEvent.is_advance_period ? 'is-advance' : 'is-day' }` }>
					{ selectedEvent.is_advance_period
						? __( 'Advance pricing applied', 'conferencemanager' ) + `（${ selectedEvent.advance_fee_deadline.substring( 0, 10 ) } ${ __( 'until', 'conferencemanager' ) }）`
						: __( 'On-site pricing applies.', 'conferencemanager' )
					}
					{ selectedEvent.advance_fee_notice && (
						<p style={ { margin: '4px 0 0', fontSize: '13px' } }>{ selectedEvent.advance_fee_notice }</p>
					) }
				</div>
			) }

			{ /* 代表者情報 */ }
			<div className="conf-manager-form__group-section">
				<h4>{ __( 'Representative', 'conferencemanager' ) }</h4>
				<p className="conf-manager-form__member-info" style={ { margin: '0 0 12px' } }>
					{ member.name_sei } { member.name_mei } ({ MEMBER_TYPE_LABELS[ member.member_type ] || member.member_type })
				</p>

				{ getFeeTypeOptions().length > 1 && (
					<div className="conf-manager-form__field">
						<label>{ __( 'Participation Type (Fee Category)', 'conferencemanager' ) }</label>
						<select value={ feeType } onChange={ ( e ) => setFeeType( e.target.value ) }>
							{ getFeeTypeOptions().map( ( opt ) => (
								<option key={ opt.value } value={ opt.value }>{ opt.label }</option>
							) ) }
						</select>
					</div>
				) }

				<div className="conf-manager-form__field">
					<label>{ __( 'Participation Type', 'conferencemanager' ) }</label>
					<select value={ participationType } onChange={ ( e ) => setParticipationType( e.target.value ) }>
						{ availableParticipationTypes( feeType ).map( ( pt ) => (
							<option key={ pt } value={ pt }>
								{ pt === 'online'
									? __( 'Online Participation', 'conferencemanager' )
									: __( 'On-site', 'conferencemanager' ) }
							</option>
						) ) }
					</select>
				</div>

				{ sessions.filter( ( s ) => s.fee > 0 ).length > 0 && (
					<div className="conf-manager-form__field">
						<label>{ __( 'Additional Sessions (paid)', 'conferencemanager' ) }</label>
						{ sessions.filter( ( s ) => s.fee > 0 ).map( ( s ) => (
							<label key={ s.id } className="conf-manager-form__checkbox">
								<input type="checkbox" checked={ selectedSessions.includes( s.id ) } onChange={ () => toggleSession( s.id ) } />
								{ s.title } (&yen;{ s.fee.toLocaleString() })
							</label>
						) ) }
					</div>
				) }

				<div className="conf-manager-form__field">
					<label>{ __( 'Payment Method', 'conferencemanager' ) }</label>
					<select value={ paymentMethod } onChange={ ( e ) => setPaymentMethod( e.target.value ) }>
						<option value="bank">{ __( 'Bank Transfer', 'conferencemanager' ) }</option>
					</select>
				</div>

				{ paymentMethod === 'bank' && (
					<div className="conf-manager-form__field">
						<label>{ __( 'Transfer Account Name Note', 'conferencemanager' ) }</label>
						<input
							type="text"
							maxLength={ 255 }
							value={ transferNote }
							onChange={ ( e ) => setTransferNote( e.target.value ) }
						/>
						<p className="conf-manager-form__hint">{ __( 'If the bank transfer will be made under a name different from the participant, please note it here. Leave blank if it is the same as the participant name.', 'conferencemanager' ) }</p>
					</div>
				) }
			</div>

			{ /* スタッフ一覧 */ }
			<div className="conf-manager-form__group-section">
				<h4>{ __( 'Staff', 'conferencemanager' ) }</h4>
				{ staffList.map( ( staff, idx ) => (
					<div key={ idx } className="conf-manager-form__staff-row">
						<div className="conf-manager-form__staff-header">
							<span className="conf-manager-form__staff-num">{ idx + 1 }</span>
							<input
								type="text"
								value={ staff.name }
								onChange={ ( e ) => updateStaff( idx, 'name', e.target.value ) }
								placeholder={ __( 'Name', 'conferencemanager' ) }
								className="conf-manager-form__staff-name"
							/>
							<input
								type="email"
								value={ staff.email }
								onChange={ ( e ) => updateStaff( idx, 'email', e.target.value ) }
								placeholder={ __( 'Email Address', 'conferencemanager' ) }
								className="conf-manager-form__staff-email"
							/>
							{ staffList.length > 1 && (
								<button
									type="button"
									onClick={ () => removeStaff( idx ) }
									className="conf-manager-form__staff-remove"
									title={ __( 'Delete', 'conferencemanager' ) }
								>&times;</button>
							) }
						</div>
						<div className="conf-manager-form__staff-options">
							<select
								value={ staff.fee_type || feeType }
								onChange={ ( e ) => updateStaff( idx, 'fee_type', e.target.value ) }
								className="conf-manager-form__staff-select"
							>
								{ getFeeTypeOptions().map( ( opt ) => (
									<option key={ opt.value } value={ opt.value }>
										{ opt.label } (&yen;{ getBaseFee( opt.value, staff.participation_type || 'onsite' ).toLocaleString() })
									</option>
								) ) }
							</select>
							<select
								value={ staff.participation_type }
								onChange={ ( e ) => updateStaff( idx, 'participation_type', e.target.value ) }
								className="conf-manager-form__staff-select"
							>
								{ availableParticipationTypes( staff.fee_type || feeType ).map( ( pt ) => (
									<option key={ pt } value={ pt }>
										{ pt === 'online'
											? __( 'Online', 'conferencemanager' )
											: __( 'On-site', 'conferencemanager' ) }
									</option>
								) ) }
							</select>
							{ sessions.filter( ( s ) => s.fee > 0 ).map( ( s ) => (
								<label key={ s.id } className="conf-manager-form__staff-session">
									<input
										type="checkbox"
										checked={ ( staff.session_options || [] ).includes( s.id ) }
										onChange={ () => toggleStaffSession( idx, s.id ) }
									/>
									{ s.title } (&yen;{ s.fee.toLocaleString() })
								</label>
							) ) }
						</div>
					</div>
				) ) }
				<button type="button" onClick={ addStaff } className="conf-manager-form__next" style={ { marginTop: '8px' } }>
					{ __( '+ Add Staff', 'conferencemanager' ) }
				</button>
			</div>

			{ /* 料金プレビュー */ }
			<div className="conf-manager-form__group-section">
				<h4>{ __( 'Fee (excl. tax)', 'conferencemanager' ) }</h4>
				<dl className="conf-manager-form__confirm-list">
					<dt>{ __( 'Representative', 'conferencemanager' ) } ({ feeTypeLabel })</dt>
					<dd>&yen;{ representativeFee.toLocaleString() }</dd>
					{ sessionFee > 0 && (
						<>
							<dt>{ __( 'Additional Sessions', 'conferencemanager' ) }</dt>
							<dd>&yen;{ sessionFee.toLocaleString() }</dd>
						</>
					) }
					<dt>{ __( 'Staff', 'conferencemanager' ) } ({ staffList.length }{ __( 'First Name', 'conferencemanager' ) })</dt>
					<dd>&yen;{ staffTotalFee.toLocaleString() }</dd>
					<dt><strong>{ taxAmount > 0 ? __( 'Subtotal (excl. tax)', 'conferencemanager' ) : __( 'Total', 'conferencemanager' ) }</strong></dt>
					<dd><strong>&yen;{ totalAmount.toLocaleString() }</strong></dd>
					{ taxAmount > 0 && (
						<>
							<dt>{ __( 'Tax', 'conferencemanager' ) }</dt>
							<dd>&yen;{ taxAmount.toLocaleString() }</dd>
							<dt><strong>{ __( 'Total', 'conferencemanager' ) }</strong></dt>
							<dd><strong>&yen;{ ( totalAmount + taxAmount ).toLocaleString() }</strong></dd>
						</>
					) }
				</dl>
			</div>

			<div className="conf-manager-form__actions">
				<button onClick={ onBack } className="conf-manager-form__back">{ __( 'Back', 'conferencemanager' ) }</button>
				<button onClick={ handleSubmit } disabled={ loading } className="conf-manager-form__submit">
					{ loading ? __( 'Submitting...', 'conferencemanager' ) : __( 'Submit Group Registration', 'conferencemanager' ) }
				</button>
			</div>
		</div>
	);
}
