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

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

/**
 * GMT 保存の日時を「このサイトの時間」で見せる／絞り込むための変換。
 *
 * このプラグインは日時を GMT で保存する（`current_time( 'mysql', true )`）。
 * 保存が GMT なのは正しいが、**画面・CSV にそのまま出すと日本では 9 時間ずれる**。
 * 深夜 0 時から朝 9 時までに確認した入金が「前日」として表示されていた。
 *
 * ⚠️ 「利用国の時間」は **WordPress の 設定 → 一般 → タイムゾーンだけ**を根拠にする。
 * プラグイン側に別のタイムゾーン設定を持たせない。2 つ持つと、片方だけ直された環境で
 * 帳票と画面の日付が割れる。
 *
 * ⚠️ 絞り込みは逆向きの変換が要る。利用者が指定するのは現地日付で、比較先の列は GMT。
 * 現地の 1 日の境界を GMT に直してから比較しないと、日本では 00:00〜09:00 が漏れる。
 *
 * ⚠️ **Pro 線にも同名のクラスがある**（`ConfManager\Support\LocalTime`）。
 * 由来は同じ（handoff `notes/2026-08-21-pro-to-free-4.md`）だが**別実装**で、
 * 使われ方も 1 点違う: **Free は API の `paid_at` / `created_at` を GMT のまま返し、
 * 表示用に `paid_at_local` / `created_at_local` を別キーで添える**
 * （Pro は一覧 API で `paid_at` をその場で置き換える）。
 * Core を突き合わせるときは同じものとして扱わないこと。
 *
 * @since 1.3.0
 */
final class LocalTime {

	/** 画面・CSV の既定の書式（秒は落とす） */
	public const DEFAULT_FORMAT = 'Y-m-d H:i';

	/**
	 * GMT の MySQL 日時をサイトのタイムゾーンに直す。
	 *
	 * @param string|null $gmt_datetime 'Y-m-d H:i:s'（GMT）。空・null・'0000-00-00 00:00:00' は '' を返す。
	 * @param string      $format       出力書式。
	 * @return string 変換後の文字列（変換できないときは ''）。
	 */
	public static function from_gmt( ?string $gmt_datetime, string $format = self::DEFAULT_FORMAT ): string {
		$gmt = trim( (string) $gmt_datetime );
		if ( '' === $gmt || str_starts_with( $gmt, '0000-00-00' ) ) {
			return '';
		}
		return get_date_from_gmt( $gmt, $format );
	}

	/**
	 * GMT の MySQL 日時を、サイトのタイムゾーンでの日付（Y-m-d）に直す。
	 *
	 * @param string|null $gmt_datetime
	 * @return string
	 */
	public static function date_from_gmt( ?string $gmt_datetime ): string {
		return self::from_gmt( $gmt_datetime, 'Y-m-d' );
	}

	/**
	 * 現地日付の「その日の始まり」を GMT の MySQL 日時にする。
	 *
	 * @param string $local_date 'Y-m-d'。時刻付き（'Y-m-d H:i:s'）もそのまま受け付ける。
	 * @return string 'Y-m-d H:i:s'（GMT）。解釈できない入力は '' を返す（＝呼び出し側で条件に足さない）。
	 */
	public static function day_start_to_gmt( string $local_date ): string {
		return self::local_to_gmt( $local_date, '00:00:00' );
	}

	/**
	 * 現地日付の「その日の終わり」を GMT の MySQL 日時にする。
	 *
	 * @param string $local_date 'Y-m-d'。時刻付きもそのまま受け付ける。
	 * @return string 'Y-m-d H:i:s'（GMT）。解釈できない入力は ''。
	 */
	public static function day_end_to_gmt( string $local_date ): string {
		return self::local_to_gmt( $local_date, '23:59:59' );
	}

	/**
	 * 現地日時を GMT の MySQL 日時にする。
	 *
	 * @param string $local        'Y-m-d' または 'Y-m-d H:i(:s)'
	 * @param string $default_time 日付だけのときに補う時刻。
	 * @return string
	 */
	private static function local_to_gmt( string $local, string $default_time ): string {
		$value = trim( $local );

		if ( 1 === preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ) {
			$value .= ' ' . $default_time;
		} elseif ( 1 !== preg_match( '/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2})?$/', $value ) ) {
			// 想定外の書式は条件に混ぜない（'' を返し、呼び出し側で絞り込みを付けない）。
			return '';
		}

		return get_gmt_from_date( str_replace( 'T', ' ', $value ), 'Y-m-d H:i:s' );
	}
}
