<?php

defined( 'ABSPATH' ) || exit;

/**
 * Established Year module.
 *
 * Stores a single "company established" date and exposes two shortcodes for
 * use in body copy:
 *
 *   [bw_dev_year_number]   →  45
 *   [bw_dev_year_word]     →  forty-five
 *
 * Plus backwards-compat aliases `[bw_year_number]` and `[bw_year_word]` that
 * only register when the legacy `established-year` plugin is NOT already
 * registering them (detected via `shortcode_exists()`). Keeps both plugins
 * usable side-by-side during a migration.
 *
 * Year count uses `DateTime::diff` for precision — a company founded
 * 1980-12-31 doesn't tick over to "45" until 2025-12-31, not 2025-01-01.
 *
 * Ported from `/srv/apps/newcap/wp-content/plugins/established-year`. The
 * original `bw_established_date` option is auto-migrated by
 * BW_Dev_Migration::on_activation.
 *
 * @package BW_Dev
 */

class BW_Dev_Module_Established_Year implements BW_Dev_Module_Interface {

	const LEGACY_OPTION = 'bw_established_date';

	public function slug(): string {
		return 'established_year';
	}

	public function label(): string {
		return __( 'Established Year', 'bw-dev' );
	}

	public function group(): string {
		return 'editor_admin';
	}

	public function default_settings(): array {
		return array( 'date' => '' );
	}

	public function sanitize( array $data ): array {
		$raw = isset( $data['date'] ) ? trim( (string) wp_unslash( $data['date'] ) ) : '';
		if ( '' === $raw ) {
			return array( 'date' => '' );
		}
		// Strict YYYY-MM-DD shape.
		if ( ! preg_match( '/^(\d{4})-(\d{2})-(\d{2})$/', $raw, $m ) ) {
			return array( 'date' => '' );
		}
		// Real-calendar check (so "2025-02-30" is rejected).
		if ( ! checkdate( (int) $m[2], (int) $m[3], (int) $m[1] ) ) {
			return array( 'date' => '' );
		}
		return array( 'date' => $raw );
	}

	public function register(): void {
		add_action( 'init', array( $this, 'register_shortcodes' ) );
	}

	public function register_shortcodes(): void {
		add_shortcode( 'bw_dev_year_number', array( $this, 'shortcode_year_number' ) );
		add_shortcode( 'bw_dev_year_word',   array( $this, 'shortcode_year_word' ) );

		// Backwards-compat aliases for the standalone `established-year` plugin.
		// Skipped while it's active so we never collide on the same shortcode.
		if ( ! shortcode_exists( 'bw_year_number' ) ) {
			add_shortcode( 'bw_year_number', array( $this, 'shortcode_year_number' ) );
		}
		if ( ! shortcode_exists( 'bw_year_word' ) ) {
			add_shortcode( 'bw_year_word', array( $this, 'shortcode_year_word' ) );
		}
	}

	public function shortcode_year_number( $atts = array() ): string {
		unset( $atts );
		return (string) self::years_since();
	}

	public function shortcode_year_word( $atts = array() ): string {
		unset( $atts );
		return self::number_to_words( self::years_since() );
	}

	/* ---------------------------------------------------------------------
	 * Calculation helpers — static so render callbacks / external code can
	 * use them without instantiating the module.
	 * ------------------------------------------------------------------- */

	/**
	 * Precise number of full years since the configured establishment date.
	 * Returns 0 when the date is unset or unparseable.
	 */
	public static function years_since(): int {
		$date_str = (string) bw_dev()->settings()->get( 'established_year', 'date', '' );
		if ( '' === $date_str ) {
			return 0;
		}
		try {
			$start    = new DateTime( $date_str );
			$now      = new DateTime();
			$interval = $now->diff( $start );
			return (int) $interval->y;
		} catch ( Exception $e ) {
			return 0;
		}
	}

	/**
	 * Convert a non-negative integer 0-999 into English words.
	 * Returns the numeric string for anything outside that range so callers
	 * always get back something they can render. (Realistic business ages
	 * never approach 1000 — capped behaviour matches the source plugin.)
	 */
	public static function number_to_words( int $number ): string {
		if ( $number < 0 ) {
			return 'negative ' . self::number_to_words( -$number );
		}
		if ( $number >= 1000 ) {
			return (string) $number;
		}

		$dictionary = array(
			0  => 'zero',  1  => 'one',  2  => 'two',  3  => 'three',  4  => 'four',
			5  => 'five',  6  => 'six',  7  => 'seven', 8  => 'eight', 9  => 'nine',
			10 => 'ten',   11 => 'eleven', 12 => 'twelve', 13 => 'thirteen',
			14 => 'fourteen', 15 => 'fifteen', 16 => 'sixteen', 17 => 'seventeen',
			18 => 'eighteen', 19 => 'nineteen',
			20 => 'twenty', 30 => 'thirty', 40 => 'forty', 50 => 'fifty',
			60 => 'sixty',  70 => 'seventy', 80 => 'eighty', 90 => 'ninety',
		);

		if ( $number < 21 ) {
			return $dictionary[ $number ];
		}
		if ( $number < 100 ) {
			$tens  = ( (int) ( $number / 10 ) ) * 10;
			$units = $number % 10;
			return $units ? $dictionary[ $tens ] . '-' . $dictionary[ $units ] : $dictionary[ $tens ];
		}
		// 100-999.
		$hundreds  = (int) ( $number / 100 );
		$remainder = $number % 100;
		$out       = $dictionary[ $hundreds ] . ' hundred';
		if ( $remainder ) {
			$out .= ' and ' . self::number_to_words( $remainder );
		}
		return $out;
	}

	/* ---------------------------------------------------------------------
	 * Settings tab
	 * ------------------------------------------------------------------- */

	public function render_tab(): void {
		$date     = (string) bw_dev()->settings()->get( $this->slug(), 'date', '' );
		$name     = BW_Dev_Settings::OPTION . '[' . $this->slug() . '][date]';
		$years    = self::years_since();
		$words    = self::number_to_words( $years );
		$has_date = '' !== $date;
		?>
		<p class="description">
			<?php esc_html_e( 'Set the date your company was established. Two shortcodes are available so you can drop the years-since-founding into any page or post copy without manually updating it each year.', 'bw-dev' ); ?>
		</p>

		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row">
						<label for="bw-dev-est-date"><?php esc_html_e( 'Date of establishment', 'bw-dev' ); ?></label>
					</th>
					<td>
						<input type="date" id="bw-dev-est-date" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $date ); ?>" />
						<p class="description"><?php esc_html_e( 'Use the precise date — the year ticks over only after the anniversary, not on January 1st.', 'bw-dev' ); ?></p>
					</td>
				</tr>
			</tbody>
		</table>

		<?php if ( $has_date ) : ?>
			<div style="background:#fff;border-left:4px solid #00a32a;padding:12px 16px;margin:14px 0;max-width:720px;">
				<strong><?php esc_html_e( 'Right now this resolves to', 'bw-dev' ); ?></strong>
				<p style="margin:6px 0 0;">
					<code>[bw_dev_year_number]</code> &rarr; <strong><?php echo esc_html( (string) $years ); ?></strong><br />
					<code>[bw_dev_year_word]</code> &rarr; <strong><?php echo esc_html( $words ); ?></strong>
				</p>
			</div>
		<?php endif; ?>

		<h3><?php esc_html_e( 'Shortcodes', 'bw-dev' ); ?></h3>
		<table class="widefat striped" style="max-width:720px;">
			<thead>
				<tr>
					<th><?php esc_html_e( 'Shortcode', 'bw-dev' ); ?></th>
					<th><?php esc_html_e( 'Output', 'bw-dev' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td><code>[bw_dev_year_number]</code></td>
					<td><?php esc_html_e( 'Numeric — e.g. "45"', 'bw-dev' ); ?></td>
				</tr>
				<tr>
					<td><code>[bw_dev_year_word]</code></td>
					<td><?php esc_html_e( 'English words — e.g. "forty-five"', 'bw-dev' ); ?></td>
				</tr>
				<tr>
					<td><code>[bw_year_number]</code> / <code>[bw_year_word]</code></td>
					<td><?php esc_html_e( 'Backwards-compat aliases (only active when the standalone Established Year plugin is NOT installed).', 'bw-dev' ); ?></td>
				</tr>
			</tbody>
		</table>

		<p class="description" style="margin-top:14px;">
			<?php esc_html_e( 'Example copy: "Trusted for [bw_dev_year_word] years" or "Established [bw_dev_year_number] years ago".', 'bw-dev' ); ?>
		</p>

		<h3><?php esc_html_e( 'Use in PHP', 'bw-dev' ); ?></h3>
		<pre style="background:#f6f7f7;padding:10px 14px;max-width:720px;border-left:4px solid #2271b1;font-size:12px;"><code>$years = BW_Dev_Module_Established_Year::years_since();
$words = BW_Dev_Module_Established_Year::number_to_words( $years );</code></pre>
		<?php
	}

	public function uninstall(): void {
		// Settings live under bw_dev_settings — root option drop covers them.
	}
}
