<?php
/**
 * Filter context for Insights snapshot requests.
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class LinkCentral_Insights_Filters {

	/** @var string */
	public $preset = '7';

	/** @var string|null */
	public $start_date = null;

	/** @var string|null */
	public $end_date = null;

	/** @var bool */
	public $since_start = false;

	/** @var int|null */
	public $link_id = null;

	/** @var int|null */
	public $category_id = null;

	/** @var string|null Browser drill-down label. */
	public $browser = null;

	/** @var string|null Device drill-down label. */
	public $device = null;

	/** @var string|null Operating system drill-down label. */
	public $operating_system = null;

	/** @var string|null Geo drill-down: country, region, or city. */
	public $geo_type = null;

	/** @var string|null Country code (e.g. NL) or XX for unknown. */
	public $geo_country = null;

	/** @var string|null Region name when geo_type is region or city. */
	public $geo_region = null;

	/** @var string|null City name when geo_type is city. */
	public $geo_city = null;

	/** @var string|null Display label for geo filter chip (not used in SQL). */
	public $geo_label = null;

	/** @var string|null Channel drill-down (Direct, Internal, Referral). */
	public $channel = null;

	/** @var string|null Referrer domain drill-down (display label). */
	public $referrer = null;

	/**
	 * Build filters from an AJAX request payload.
	 *
	 * @param array $post Raw $_POST or decoded filters array.
	 * @return self
	 */
	public static function from_request( $post ) {
		$raw = isset( $post['filters'] ) && is_array( $post['filters'] )
			? $post['filters']
			: $post;

		$filters = new self();

		$filters->preset      = isset( $raw['preset'] ) ? sanitize_text_field( wp_unslash( $raw['preset'] ) ) : '7';
		$filters->since_start = self::parse_boolean( $raw['since_start'] ?? false );

		if ( isset( $raw['start_date'] ) && $raw['start_date'] !== '' && $raw['start_date'] !== null ) {
			$filters->start_date = gmdate( 'Y-m-d', strtotime( sanitize_text_field( wp_unslash( $raw['start_date'] ) ) ) );
		}

		if ( isset( $raw['end_date'] ) && $raw['end_date'] !== '' && $raw['end_date'] !== null ) {
			$filters->end_date = gmdate( 'Y-m-d', strtotime( sanitize_text_field( wp_unslash( $raw['end_date'] ) ) ) );
		}

		if ( class_exists( 'LinkCentral_Insights_Link_Scope' ) ) {
			LinkCentral_Insights_Link_Scope::parse_from_request( $filters, $raw );
		}

		if ( class_exists( 'LinkCentral_Insights_Drilldown' ) ) {
			LinkCentral_Insights_Drilldown::parse_from_request( $filters, $raw );
		}

		$filters->normalize();

		return $filters;
	}

	/**
	 * Validate and normalize base filter values.
	 */
	public function normalize() {
		$allowed_presets = array( '1', '7', '30', '365', 'since_start', 'custom' );

		if ( $this->since_start ) {
			$this->preset     = 'since_start';
			$this->start_date = null;
			$this->end_date   = null;
		} elseif ( in_array( $this->preset, array( '1', '7', '30', '365' ), true ) ) {
			$this->since_start = false;
		} elseif ( $this->start_date && $this->end_date ) {
			$this->preset      = 'custom';
			$this->since_start = false;
		} elseif ( ! in_array( $this->preset, $allowed_presets, true ) ) {
			$this->preset      = '7';
			$this->since_start = false;
		}
	}

	/**
	 * Public representation for API responses.
	 *
	 * @return array
	 */
	public function to_public_array() {
		$public = array(
			'preset'      => $this->preset,
			'start_date'  => $this->start_date,
			'end_date'    => $this->end_date,
			'since_start' => $this->since_start,
		);

		if ( class_exists( 'LinkCentral_Insights_Link_Scope' ) ) {
			$public = array_merge( $public, LinkCentral_Insights_Link_Scope::to_public_array( $this ) );
		}

		if ( class_exists( 'LinkCentral_Insights_Drilldown' ) ) {
			$public = array_merge( $public, LinkCentral_Insights_Drilldown::to_public_array( $this ) );
		}

		return $public;
	}

	/**
	 * Parse request booleans (jQuery sends false as the string "false", which !empty() treats as true).
	 *
	 * @param mixed $value Raw value.
	 * @return bool
	 */
	private static function parse_boolean( $value ) {
		if ( is_bool( $value ) ) {
			return $value;
		}

		if ( is_int( $value ) ) {
			return 1 === $value;
		}

		$value = strtolower( trim( (string) $value ) );

		return in_array( $value, array( '1', 'true', 'yes', 'on' ), true );
	}

	/**
	 * Preset value for legacy code paths that expect a day count string.
	 *
	 * @return string
	 */
	public function get_timeframe_preset() {
		if ( $this->since_start || $this->preset === 'since_start' ) {
			return 'since_start';
		}
		if ( $this->start_date && $this->end_date ) {
			return $this->preset;
		}
		return $this->preset;
	}
}
