<?php
/**
 * Date Range Trait.
 *
 * Provides methods for calculating date ranges and periods for dashboard queries.
 * Handles various time periods like today, this week, last month, etc.
 *
 * @since   1.0.0
 * @package WC_Affiliate\Traits
 */

namespace WC_Affiliate\Traits;

defined( 'ABSPATH' ) || exit;

/**
 * Date trait class.
 */
trait Date {

	/**
	 * Get date range based on period.
	 *
	 * Calculates the start and end dates for a given period, supporting predefined periods like 'today', 'this_month', or custom ranges.
	 *
	 * @param string $period     The period type (e.g., 'today', 'this_month', 'custom').
	 * @param string $start_date Optional start date for custom period (YYYY-MM-DD).
	 * @param string $end_date   Optional end date for custom period (YYYY-MM-DD).
	 *
	 * @return array Associative array with 'start_date' and 'end_date' keys.
	 */
	public function get_date_range( string $period, string $start_date = '', string $end_date = '' ): array {
		$end   = current_time( 'Y-m-d' );
		$start = $end;

		// Use Cleaner trait to sanitize inputs.
		$period     = sanitize_text_field( $period );
		$start_date = sanitize_text_field( $start_date );
		$end_date   = sanitize_text_field( $end_date );

		$current_timestamp = time();

		switch ( $period ) {
			case 'all_time':
				$start = '';
				$end   = '';
				break;

			case 'today':
				// Start and end are already set to today.
				break;

			case 'this_week':
				// Start from Monday of current week.
				$start = wp_date( 'Y-m-d', strtotime( 'monday this week', $current_timestamp ) );
				break;

			case 'last_7_days':
				$start = wp_date( 'Y-m-d', strtotime( '-6 days', strtotime( $end ) ) );
				break;

			case 'last_14_days':
				$start = wp_date( 'Y-m-d', strtotime( '-13 days', strtotime( $end ) ) );
				break;

			case 'last_30_days':
				$start = wp_date( 'Y-m-d', strtotime( '-29 days', strtotime( $end ) ) );
				break;

			case 'last_90_days':
				$start = wp_date( 'Y-m-d', strtotime( '-89 days', strtotime( $end ) ) );
				break;

			case 'this_month':
				// First day of current month.
				$start = wp_date( 'Y-m-01', $current_timestamp );
				// Last day of current month.
				$end = wp_date( 'Y-m-t', strtotime( 'last day of this month', $current_timestamp ) );
				break;

			case 'last_month':
				// First day of last month.
				$start = wp_date( 'Y-m-01', strtotime( 'first day of last month', $current_timestamp ) );
				// Last day of last month.
				$end = wp_date( 'Y-m-t', strtotime( 'first day of last month', $current_timestamp ) );
				break;

			case 'this_year':
				// First day of current year.
				$start = wp_date( 'Y-01-01', $current_timestamp );
				break;

			case 'last_year':
				// First day of last year.
				$start = wp_date( 'Y-01-01', strtotime( 'first day of january last year', $current_timestamp ) );
				// Last day of last year.
				$end = wp_date( 'Y-12-31', strtotime( 'last day of december last year', $current_timestamp ) );
				break;

			case 'custom':
				if ( $start_date ) {
					$start = $start_date;
				}
				if ( $end_date ) {
					$end = $end_date;
				}
				break;
		}

		$date_range = array(
			'start_date' => $start,
			'end_date'   => $end,
		);

		/**
		 * Filter the calculated date range.
		 *
		 * Allows modification of the date range for dashboard queries.
		 *
		 * @since 1.0.0
		 *
		 * @param array  $date_range Calculated date range.
		 * @param string $period     The period type.
		 */
		return apply_filters( 'wc_affiliate_dashboard_date_range', $date_range, $period );
	}

	/**
	 * Get period in days.
	 *
	 * Converts a period string to the equivalent number of days for leaderboard or top performers queries.
	 *
	 * @param string $period The period type (e.g., 'today', 'last_30_days').
	 *
	 * @return int The number of days in the period.
	 */
	public function get_period_days( string $period ): int {
		// Use Cleaner trait to sanitize input.
		$period = sanitize_text_field( $period );

		$current_timestamp = time();

		switch ( $period ) {
			case 'today':
				return 1;

			case 'this_week':
				// Calculate days from Monday to today.
				$monday = strtotime( 'monday this week', $current_timestamp );

				return (int) ceil( ( $current_timestamp - $monday ) / DAY_IN_SECONDS ) + 1;

			case 'last_7_days':
				return 7;

			case 'last_14_days':
				return 14;

			case 'last_30_days':
				return 30;

			case 'last_90_days':
				return 90;

			case 'this_month':
				// Days from start of month to today.
				$first_day = strtotime( wp_date( 'Y-m-01', $current_timestamp ) );

				return (int) ceil( ( $current_timestamp - $first_day ) / DAY_IN_SECONDS ) + 1;

			case 'last_month':
				// Total days in last month.
				return (int) wp_date( 't', strtotime( 'first day of last month', $current_timestamp ) );

			case 'this_year':
				// Days from start of year to today.
				$first_day = strtotime( wp_date( 'Y-01-01', $current_timestamp ) );

				return (int) ceil( ( $current_timestamp - $first_day ) / DAY_IN_SECONDS ) + 1;

			case 'last_year':
				// Check if last year was a leap year.
				$last_year = (int) wp_date( 'Y', $current_timestamp ) - 1;

				return ( 0 === $last_year % 4 && ( 0 !== $last_year % 100 || 0 === $last_year % 400 ) ) ? 366 : 365;

			default:
				return 0;
		}
	}

	/**
	 * Get PHP date format for period
	 *
	 * @param string $period Period type.
	 *
	 * @return string PHP date format
	 */
	public function get_date_format_for_period( string $period ): string {
		switch ( $period ) {
			case 'daily':
				return 'Y-m-d';
			case 'weekly':
				return 'Y-W';
			case 'monthly':
				return 'Y-m';
			default:
				return 'Y-m-d';
		}
	}
}
