<?php
/**
 * Template Library — predefined query templates.
 */

namespace RawTypeOE\Free;

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Manages predefined query templates for common export scenarios.
 */
class Template_Library {

	/**
	 * Get all available templates.
	 *
	 * @return array Array of template definitions.
	 */
	public function get_templates() {
		$templates = $this->get_default_templates();

		/**
		 * Filter the predefined query templates.
		 *
		 * Allows Pro and other plugins to add, modify or remove templates.
		 *
		 * @param array $templates Array of templates. Each template:
		 *     @type string $id          Unique ID (slug).
		 *     @type string $name        Display name.
		 *     @type string $description Short description.
		 *     @type string $icon        Dashicon name.
		 *     @type string $entity      'orders'|'products'|'customers'.
		 *     @type string $category    Category for grouping.
		 *     @type array  $filters     Pre-applied filter configuration.
		 *     @type array  $columns     Column IDs to select.
		 *     @type array  $options     Additional options.
		 */
		$templates = apply_filters( 'rawtype_oe_templates', $templates );

		return $this->sanitize_templates( $templates );
	}

	/**
	 * Get a single template by ID.
	 *
	 * @param string $template_id Template ID.
	 * @return array|null Template definition or null.
	 */
	public function get_template( $template_id ) {
		$templates = $this->get_templates();

		foreach ( $templates as $template ) {
			if ( isset( $template['id'] ) && $template['id'] === $template_id ) {
				return $template;
			}
		}

		return null;
	}

	/**
	 * Get templates filtered by entity.
	 *
	 * @param string $entity Entity to filter by.
	 * @return array Matching templates.
	 */
	public function get_templates_by_entity( $entity ) {
		return array_values(
			array_filter(
				$this->get_templates(),
				function ( $template ) use ( $entity ) {
					return isset( $template['entity'] ) && $template['entity'] === $entity;
				}
			)
		);
	}

	/**
	 * Sanitize template definitions and remove presets that the builder cannot use.
	 *
	 * Templates must target a supported entity, expose at least one valid column,
	 * and include at least one effective filter unless they explicitly opt in to
	 * unfiltered exports with `allow_empty_filters`.
	 *
	 * @param array $templates Raw templates.
	 * @return array
	 */
	private function sanitize_templates( $templates ) {
		if ( ! is_array( $templates ) ) {
			return array();
		}

		$column_registry = new Column_Registry();
		$valid_entities  = Query_Builder::ENTITIES;
		$sanitized       = array();

		foreach ( $templates as $template ) {
			$template = $this->sanitize_template(
				$template,
				$valid_entities,
				$column_registry
			);

			if ( is_array( $template ) ) {
				$sanitized[] = $template;
			}
		}

		return $sanitized;
	}

	/**
	 * Sanitize a single template definition.
	 *
	 * @param array           $template        Raw template.
	 * @param array           $valid_entities  Supported entities.
	 * @param Column_Registry $column_registry Column registry.
	 * @return array|null
	 */
	private function sanitize_template( $template, $valid_entities, Column_Registry $column_registry ) {
		if ( ! is_array( $template ) ) {
			return null;
		}

		$id     = isset( $template['id'] ) ? sanitize_key( $template['id'] ) : '';
		$entity = isset( $template['entity'] ) ? sanitize_key( $template['entity'] ) : '';

		if ( '' === $id || ! in_array( $entity, $valid_entities, true ) ) {
			return null;
		}

		$name        = isset( $template['name'] ) ? (string) $template['name'] : '';
		$description = isset( $template['description'] ) ? (string) $template['description'] : '';
		$icon        = isset( $template['icon'] ) ? sanitize_key( $template['icon'] ) : 'admin-generic';
		$category    = isset( $template['category'] ) ? (string) $template['category'] : '';
		$options     = isset( $template['options'] ) && is_array( $template['options'] ) ? $template['options'] : array();

		if ( '' === $name || '' === $description ) {
			return null;
		}

		$available_columns = array_flip(
			array_map(
				'sanitize_key',
				array_column( $column_registry->get_columns( $entity ), 'key' )
			)
		);
		$columns           = array();

		if ( isset( $template['columns'] ) && is_array( $template['columns'] ) ) {
			foreach ( $template['columns'] as $column_key ) {
				$column_key = sanitize_key( $column_key );
				if ( '' !== $column_key && isset( $available_columns[ $column_key ] ) ) {
					$columns[] = $column_key;
				}
			}
		}

		$columns = array_values( array_unique( $columns ) );

		if ( empty( $columns ) ) {
			return null;
		}

		$filters = array();
		if ( isset( $template['filters'] ) && is_array( $template['filters'] ) ) {
			foreach ( $template['filters'] as $filter ) {
				$filter = $this->sanitize_template_filter( $filter );
				if ( is_array( $filter ) ) {
					$filters[] = $filter;
				}
			}
		}

		if ( empty( $filters ) && empty( $template['allow_empty_filters'] ) ) {
			return null;
		}

		$template['id']          = $id;
		$template['name']        = $name;
		$template['description'] = $description;
		$template['icon']        = $icon;
		$template['entity']      = $entity;
		$template['category']    = $category;
		$template['filters']     = $filters;
		$template['columns']     = $columns;
		$template['options']     = $options;

		return $template;
	}

	/**
	 * Sanitize a template filter while keeping compatibility with extensibility.
	 *
	 * Unknown filter types are preserved as-is so Pro can keep adding custom
	 * filter types, but empty/invalid filters are removed from the library.
	 *
	 * @param array $filter Raw filter definition.
	 * @return array|null
	 */
	private function sanitize_template_filter( $filter ) {
		if ( ! is_array( $filter ) ) {
			return null;
		}

		$type = isset( $filter['type'] ) ? sanitize_key( $filter['type'] ) : '';
		if ( '' === $type ) {
			return null;
		}

		$value = isset( $filter['value'] ) ? $filter['value'] : null;
		if ( is_array( $value ) && empty( $value ) ) {
			return null;
		}

		if ( ! is_array( $value ) && ( '' === $value || null === $value ) ) {
			return null;
		}

		if ( isset( $filter['field'] ) ) {
			$filter['field'] = sanitize_key( $filter['field'] );
		}

		if ( isset( $filter['operator'] ) ) {
			$filter['operator'] = sanitize_text_field( $filter['operator'] );
		}

		if ( isset( $filter['mode'] ) ) {
			$filter['mode'] = sanitize_key( $filter['mode'] );
		}

		$known_types = array( 'status', 'date', 'category', 'tag', 'product', 'sku', 'numeric' );
		if ( ! in_array( $type, $known_types, true ) ) {
			wc_get_logger()->notice(
				sprintf( 'Unknown filter type "%s" in template definition.', $type ),
				array( 'source' => 'rawtype-order-exporter-woocommerce' )
			);
		}

		$filter['type'] = $type;

		return $filter;
	}

	/**
	 * Default templates included in Free.
	 *
	 * @return array Array of template definitions.
	 */
	private function get_default_templates() {
		return array(

			// === ORDERS ===

			array(
				'id'          => 'orders-last-30-days',
				'name'        => __( 'Orders from the last 30 days', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'All orders created in the last 30 days with billing details.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'calendar-alt',
				'entity'      => 'orders',
				'category'    => __( 'Recent', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'date',
						'field'    => 'date_created',
						'operator' => 'after',
						'value'    => '-30 days',
					),
				),
				'columns'     => array(
					'order_id',
					'order_number',
					'status',
					'date_created',
					'total',
					'currency',
					'payment_method',
					'billing_first_name',
					'billing_last_name',
					'billing_email',
					'billing_city',
					'billing_country',
					'line_items',
					'line_items_total',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'orders-completed-quarter',
				'name'        => __( 'Completed orders this quarter', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Orders with "completed" status from the current quarter. Ideal for quarterly reports and accounting.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'yes-alt',
				'entity'      => 'orders',
				'category'    => __( 'Accounting', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'status',
						'field'    => 'status',
						'operator' => 'is',
						'value'    => 'completed',
					),
					array(
						'type'     => 'date',
						'field'    => 'date_created',
						'operator' => 'after',
						'value'    => 'this_quarter',
					),
				),
				'columns'     => array(
					'order_id',
					'order_number',
					'date_created',
					'total',
					'currency',
					'payment_method',
					'billing_first_name',
					'billing_last_name',
					'billing_email',
					'billing_phone',
					'billing_city',
					'billing_country',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'orders-refunded',
				'name'        => __( 'Refunded orders', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Orders with "refunded" status. Useful for tracking returns and analyzing refund patterns.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'undo',
				'entity'      => 'orders',
				'category'    => __( 'Analysis', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'status',
						'field'    => 'status',
						'operator' => 'is',
						'value'    => 'refunded',
					),
				),
				'columns'     => array(
					'order_id',
					'order_number',
					'status',
					'date_created',
					'total',
					'payment_method',
					'billing_first_name',
					'billing_last_name',
					'billing_email',
					'billing_phone',
					'refund_total',
					'refund_reason',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'orders-pending-shipping',
				'name'        => __( 'Orders pending shipping', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Processing orders with full shipping address. Ready for fulfillment.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'car',
				'entity'      => 'orders',
				'category'    => __( 'Fulfillment', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'status',
						'field'    => 'status',
						'operator' => 'is',
						'value'    => 'processing',
					),
				),
				'columns'     => array(
					'order_id',
					'order_number',
					'date_created',
					'total',
					'billing_phone',
					'shipping_first_name',
					'shipping_last_name',
					'shipping_address_1',
					'shipping_city',
					'shipping_state',
					'shipping_postcode',
					'shipping_country',
				),
				'options'     => array(),
			),

			// === PRODUCTS ===

			array(
				'id'          => 'products-published-catalog',
				'name'        => __( 'Published product catalog', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'All published products with pricing and stock info.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'star-filled',
				'entity'      => 'products',
				'category'    => __( 'Catalog', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'status',
						'field'    => 'status',
						'operator' => 'is',
						'value'    => 'publish',
					),
				),
				'columns'     => array(
					'product_id',
					'name',
					'sku',
					'type',
					'price',
					'regular_price',
					'sale_price',
					'stock_quantity',
					'stock_status',
					'categories',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'products-out-of-stock',
				'name'        => __( 'Out of stock products', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Products that are out of stock. Take immediate action to restock.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'warning',
				'entity'      => 'products',
				'category'    => __( 'Inventory', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'status',
						'field'    => 'stock_status',
						'operator' => 'is',
						'value'    => 'outofstock',
					),
				),
				'columns'     => array(
					'product_id',
					'name',
					'sku',
					'type',
					'price',
					'stock_quantity',
					'stock_status',
					'categories',
					'tags',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'products-on-sale',
				'name'        => __( 'Products currently on sale', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Published products with an active sale price. Compare regular vs sale prices.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'tag',
				'entity'      => 'products',
				'category'    => __( 'Pricing', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'status',
						'field'    => 'on_sale',
						'operator' => 'is',
						'value'    => 'true',
					),
					array(
						'type'     => 'status',
						'field'    => 'status',
						'operator' => 'is',
						'value'    => 'publish',
					),
				),
				'columns'     => array(
					'product_id',
					'name',
					'sku',
					'type',
					'regular_price',
					'sale_price',
					'price',
					'stock_status',
					'categories',
				),
				'options'     => array(),
			),

			// === CUSTOMERS ===

			array(
				'id'          => 'customers-paying',
				'name'        => __( 'Customers with orders', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Customers with at least one paid order. Useful for CRM syncs and revenue reporting.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'businessperson',
				'entity'      => 'customers',
				'category'    => __( 'Revenue', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'customer_total_spend',
						'field'    => 'total_spent',
						'operator' => '>',
						'value'    => 0,
					),
				),
				'columns'     => array(
					'customer_id',
					'first_name',
					'last_name',
					'email',
					'orders_count',
					'total_spent',
					'billing_city',
					'billing_country',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'customers-new-last-month',
				'name'        => __( 'New customers last month', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Customers who registered in the last 30 days. Useful for measuring acquisition and welcome campaigns.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'groups',
				'entity'      => 'customers',
				'category'    => __( 'Recent', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'date',
						'field'    => 'date_registered',
						'operator' => 'after',
						'value'    => '-30 days',
					),
				),
				'columns'     => array(
					'customer_id',
					'first_name',
					'last_name',
					'email',
					'username',
					'date_registered',
					'orders_count',
					'total_spent',
					'billing_city',
					'billing_country',
					'billing_phone',
				),
				'options'     => array(),
			),

			array(
				'id'          => 'customers-inactive-90-days',
				'name'        => __( 'Inactive customers >90 days', 'rawtype-order-exporter-woocommerce' ),
				'description' => __( 'Customers whose last order was over 90 days ago. Candidates for reactivation campaigns.', 'rawtype-order-exporter-woocommerce' ),
				'icon'        => 'clock',
				'entity'      => 'customers',
				'category'    => __( 'Analysis', 'rawtype-order-exporter-woocommerce' ),
				'filters'     => array(
					array(
						'type'     => 'date',
						'field'    => 'last_order_date',
						'operator' => 'before',
						'value'    => '-90 days',
					),
				),
				'columns'     => array(
					'customer_id',
					'first_name',
					'last_name',
					'email',
					'orders_count',
					'total_spent',
					'billing_city',
					'billing_country',
				),
				'options'     => array(),
			),

		);
	}
}
