<?php
declare(strict_types=1);
namespace ConfManager\Members;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use ConfManager\Registration\RegistrationManager;

/**
 * 会員種別（料金区分）の表示名に学会の略称を前置する
 *
 * 共催の催しで、**本会の非会員が「正会員」として参加登録してしまう**ケースが多発した。
 * 画面の選択肢が「正会員」としか出ないので、他学会の正会員が自分のことだと読む。
 * 設定（`conf_manager_society_short_name`）に略称を入れると
 * `日本○○学会_正会員` のように出る。
 *
 * 🔴 **設計の要点（外すと壊れる）**
 *
 * 1. **元のラベル定義は 1 文字も変えない。表示の直前にだけ装飾を通す。**
 *    `registrations.fee_type_label` は**申込時のラベルを DB に焼き付ける**列なので、
 *    ここに前置きを混ぜると、設定前の申込（前置なし）と設定後の申込（前置あり）が
 *    **同じ CSV に並び、同じ区分が 2 通りに見える**。
 * 2. **既定は「付けない」。** 「空欄ならサイト名」にすると、
 *    **更新した瞬間に全サイトの表示が変わる**。入力の手間は
 *    初期設定の「サイト名を入れる」ボタンで補う。
 * 3. **前置してよいのは標準 5 区分だけ。判定はキーで行う。**
 *    ラベル文字列で判定すると、催しの独自区分の名前がたまたま「正会員」のときに
 *    巻き込むうえ、**描画のたびに前置が伸びる**。
 * 4. **会員 CSV の書き出しには出さない。** 書き出し → 編集 → 取り込みで往復する
 *    形式なので、表示名を混ぜると**取り込みが全滅する**。
 *
 * @since 1.5.2
 */
class MemberTypeLabel {

	/**
	 * 略称を保存する wp_options のキー
	 */
	public const OPTION = 'conf_manager_society_short_name';

	/**
	 * 略称と区分名のあいだに入れる文字
	 *
	 * ⚠️ 表示専用。DB に焼き付く値には入らない。
	 */
	public const SEPARATOR = '_';

	/**
	 * 設定されている学会の略称を返す（未設定なら空文字）
	 */
	public static function society_short_name(): string {
		return trim( (string) get_option( self::OPTION, '' ) );
	}

	/**
	 * 標準 5 区分のキーかどうか
	 *
	 * 🔴 ラベル文字列ではなく**キー**で判定する。
	 */
	public static function is_standard_key( string $key ): bool {
		return array_key_exists( $key, RegistrationManager::base_labels() );
	}

	/**
	 * 表示名に略称を前置する
	 *
	 * @param string $key   区分キー（regular / student / …。独自区分もありうる）
	 * @param string $label 元の表示名。**この文字列は変更せず、前置した新しい文字列を返す**
	 * @return string 装飾後の表示名。設定が空、または標準 5 区分でなければ $label のまま
	 */
	public static function decorate( string $key, string $label ): string {
		$short = self::society_short_name();

		if ( '' === $short || '' === $label || ! self::is_standard_key( $key ) ) {
			return $label;
		}

		return $short . self::SEPARATOR . $label;
	}

	/**
	 * キー => 表示名 の配列をまとめて装飾する
	 *
	 * @param array<string, string> $labels
	 * @return array<string, string>
	 */
	public static function decorate_map( array $labels ): array {
		$out = [];
		foreach ( $labels as $key => $label ) {
			$out[ (string) $key ] = self::decorate( (string) $key, (string) $label );
		}
		return $out;
	}

	/**
	 * 申込 1 件の焼き付けラベルを、表示用に装飾して返す
	 *
	 * 🔴 **DB の `fee_type_label` は書き換えない。** 表示の直前にだけ通すこと。
	 * 設定より前に作られた申込も、キーが標準 5 区分ならこれで同じ表記になる。
	 *
	 * @param string $fee_type       区分キー（`registrations.fee_type`）
	 * @param string $fee_type_label 焼き付けラベル（`registrations.fee_type_label`）
	 */
	public static function decorate_registration( string $fee_type, string $fee_type_label ): string {
		return self::decorate( $fee_type, $fee_type_label );
	}

	/**
	 * JS へ渡す設定（wp_localize_script 用）
	 *
	 * 🔴 REST（`/admin/system-status`）から取らせないこと。あの経路は
	 * `conf_manager_manage_settings` を要求するが、**「学会編集者」は会員を編集できるのに
	 * 設定権限を持たない**ので、画面は開けるのに前置だけ出なくなる。
	 *
	 * @return array{short_name: string, separator: string, standard_keys: array<int, string>}
	 */
	public static function script_data(): array {
		return [
			'short_name'    => self::society_short_name(),
			'separator'     => self::SEPARATOR,
			'standard_keys' => array_keys( RegistrationManager::base_labels() ),
		];
	}
}
