<?php

/**
 * WooReadHandler — WooCommerce read-only actions.
 *
 * Owns: wc_get_products, wc_get_product, wc_get_orders, wc_get_order,
 *       wc_get_customers, wc_get_categories, wc_get_coupons, wc_get_reports
 *
 * @package LolaCore\Actions\Handlers
 * @license GPL-2.0-or-later
 */

declare( strict_types=1 );

namespace LolaCore\Actions\Handlers;

// phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Diagnostic exception messages; escaped at REST/chat presentation layer.

use LolaCore\Actions\Contracts\ActionHandlerInterface;

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

class WooReadHandler implements ActionHandlerInterface {

	public function getSupportedActions(): array {
		return array(
			'wc_get_products', 'wc_get_product',
			'wc_get_orders',   'wc_get_order',
			'wc_get_customers','wc_get_categories',
			'wc_get_coupons',  'wc_get_reports',
		);
	}

	public function handle( string $actionId, array $params, bool $dryRun ): array {
		$this->requireWooCommerce();
		return match ( $actionId ) {
			'wc_get_products'   => $this->getProducts( $params ),
			'wc_get_product'    => $this->getProduct( $params ),
			'wc_get_orders'     => $this->getOrders( $params ),
			'wc_get_order'      => $this->getOrder( $params ),
			'wc_get_customers'  => $this->getCustomers( $params ),
			'wc_get_categories' => $this->getCategories( $params ),
			'wc_get_coupons'    => $this->getCoupons( $params ),
			'wc_get_reports'    => $this->getReports( $params ),
			default             => throw new \Exception( esc_html( "WooReadHandler: unknown action '{$actionId}'." ) ),
		};
	}

	private function requireWooCommerce(): void {
		if ( ! class_exists( 'WooCommerce' ) ) {
			throw new \Exception( __( 'WooCommerce is not installed or activated.', 'lolacore' ) );
		}
	}

	private function getProducts( array $params ): array {
		$status   = sanitize_text_field( $params['status'] ?? 'publish' );
		$per_page = max( 1, min( 100, (int) ( $params['limit'] ?? $params['per_page'] ?? 20 ) ) );
		$page     = max( 1, (int) ( $params['page'] ?? 1 ) );
		$search   = sanitize_text_field( $params['search'] ?? '' );
		$category = sanitize_text_field( $params['category'] ?? '' );
		$orderby  = sanitize_text_field( $params['orderby'] ?? 'date' );
		$order    = strtoupper( $params['order'] ?? 'DESC' ) === 'ASC' ? 'ASC' : 'DESC';

		$args = array( 'status' => $status, 'limit' => $per_page, 'page' => $page, 'orderby' => $orderby, 'order' => $order, 'return' => 'objects' );
		if ( $search )   { $args['s'] = $search; }
		if ( $category ) { $args['category'] = array( $category ); }

		$products = wc_get_products( $args );
		$items    = array();
		foreach ( $products as $p ) {
			$items[] = array( 'id' => $p->get_id(), 'name' => $p->get_name(), 'sku' => $p->get_sku(), 'status' => $p->get_status(), 'type' => $p->get_type(), 'price' => $p->get_price(), 'regular_price' => $p->get_regular_price(), 'sale_price' => $p->get_sale_price(), 'stock_status' => $p->get_stock_status(), 'stock_qty' => $p->get_stock_quantity(), 'permalink' => get_permalink( $p->get_id() ) );
		}
		$count_args            = $args;
		$count_args['limit']   = -1;
		$count_args['return']  = 'ids';
		$total                 = count( wc_get_products( $count_args ) );
		return array( 'products' => $items, 'page' => $page, 'per_page' => $per_page, 'total' => count( $items ), 'total_products' => $total, 'total_pages' => (int) ceil( $total / $per_page ) );
	}

	private function getProduct( array $params ): array {
		$pid = (int) ( $params['product_id'] ?? 0 );
		if ( ! $pid ) { throw new \Exception( __( 'A valid product_id is required.', 'lolacore' ) ); }
		$p = wc_get_product( $pid );
		if ( ! $p ) { throw new \Exception( __( 'Product not found.', 'lolacore' ) ); }

		$categories = array();
		foreach ( $p->get_category_ids() as $cid ) {
			$t = get_term( $cid, 'product_cat' );
			if ( $t && ! is_wp_error( $t ) ) { $categories[] = array( 'id' => $t->term_id, 'name' => $t->name, 'slug' => $t->slug ); }
		}
		$tags = array();
		foreach ( $p->get_tag_ids() as $tid ) {
			$t = get_term( $tid, 'product_tag' );
			if ( $t && ! is_wp_error( $t ) ) { $tags[] = array( 'id' => $t->term_id, 'name' => $t->name, 'slug' => $t->slug ); }
		}
		$attributes = array();
		foreach ( $p->get_attributes() as $key => $attr ) {
			if ( is_string( $attr ) ) {
				$attributes[] = array( 'name' => $key, 'options' => array_map( 'trim', explode( '|', $attr ) ) );
			} else {
				$attributes[] = array( 'name' => $attr->get_name(), 'options' => $attr->get_options() );
			}
		}
		return array( 'id' => $p->get_id(), 'name' => $p->get_name(), 'slug' => $p->get_slug(), 'sku' => $p->get_sku(), 'status' => $p->get_status(), 'type' => $p->get_type(), 'description' => $p->get_description(), 'short_description' => $p->get_short_description(), 'price' => $p->get_price(), 'regular_price' => $p->get_regular_price(), 'sale_price' => $p->get_sale_price(), 'on_sale' => $p->is_on_sale(), 'stock_status' => $p->get_stock_status(), 'stock_qty' => $p->get_stock_quantity(), 'manage_stock' => $p->get_manage_stock(), 'weight' => $p->get_weight(), 'categories' => $categories, 'tags' => $tags, 'attributes' => $attributes, 'permalink' => get_permalink( $p->get_id() ), 'date_created' => $p->get_date_created() ? $p->get_date_created()->date( 'Y-m-d H:i:s' ) : null, 'date_modified' => $p->get_date_modified() ? $p->get_date_modified()->date( 'Y-m-d H:i:s' ) : null );
	}

	private function getOrders( array $params ): array {
		$status   = sanitize_text_field( $params['status'] ?? 'any' );
		$per_page = max( 1, min( 100, (int) ( $params['per_page'] ?? 10 ) ) );
		$page     = max( 1, (int) ( $params['page'] ?? 1 ) );
		$args     = array( 'status' => $status, 'limit' => $per_page, 'paged' => $page, 'return' => 'objects', 'orderby' => 'date', 'order' => 'DESC' );
		if ( isset( $params['customer_id'] ) ) { $args['customer_id'] = (int) $params['customer_id']; }
		if ( isset( $params['date_after'] ) )  { $args['date_after']  = sanitize_text_field( $params['date_after'] ); }
		if ( isset( $params['date_before'] ) ) { $args['date_before'] = sanitize_text_field( $params['date_before'] ); }

		$orders = wc_get_orders( $args );
		$items  = array();
		foreach ( $orders as $o ) {
			$items[] = array( 'id' => $o->get_id(), 'status' => $o->get_status(), 'total' => $o->get_total(), 'currency' => $o->get_currency(), 'customer_id' => $o->get_customer_id(), 'customer_email' => $o->get_billing_email(), 'customer_name' => trim( $o->get_billing_first_name() . ' ' . $o->get_billing_last_name() ), 'items_count' => $o->get_item_count(), 'date_created' => $o->get_date_created() ? $o->get_date_created()->date( 'Y-m-d H:i:s' ) : null, 'payment_method' => $o->get_payment_method_title() );
		}
		return array( 'orders' => $items, 'page' => $page, 'per_page' => $per_page, 'total' => count( $items ) );
	}

	private function getOrder( array $params ): array {
		$oid = (int) ( $params['order_id'] ?? 0 );
		if ( ! $oid ) { throw new \Exception( __( 'A valid order_id is required.', 'lolacore' ) ); }
		$o = wc_get_order( $oid );
		if ( ! $o ) { throw new \Exception( __( 'Order not found.', 'lolacore' ) ); }

		$line_items = array();
		foreach ( $o->get_items() as $iid => $item ) {
			$line_items[] = array( 'item_id' => $iid, 'name' => $item->get_name(), 'product_id' => $item->get_product_id(), 'qty' => $item->get_quantity(), 'total' => $item->get_total() );
		}
		return array( 'id' => $o->get_id(), 'status' => $o->get_status(), 'currency' => $o->get_currency(), 'total' => $o->get_total(), 'subtotal' => $o->get_subtotal(), 'total_tax' => $o->get_total_tax(), 'shipping_total' => $o->get_shipping_total(), 'payment_method' => $o->get_payment_method(), 'payment_title' => $o->get_payment_method_title(), 'customer_id' => $o->get_customer_id(), 'customer_note' => $o->get_customer_note(), 'billing' => array( 'first_name' => $o->get_billing_first_name(), 'last_name' => $o->get_billing_last_name(), 'email' => $o->get_billing_email(), 'phone' => $o->get_billing_phone(), 'address_1' => $o->get_billing_address_1(), 'city' => $o->get_billing_city(), 'state' => $o->get_billing_state(), 'postcode' => $o->get_billing_postcode(), 'country' => $o->get_billing_country() ), 'shipping' => array( 'first_name' => $o->get_shipping_first_name(), 'last_name' => $o->get_shipping_last_name(), 'address_1' => $o->get_shipping_address_1(), 'city' => $o->get_shipping_city(), 'state' => $o->get_shipping_state(), 'postcode' => $o->get_shipping_postcode(), 'country' => $o->get_shipping_country() ), 'line_items' => $line_items, 'date_created' => $o->get_date_created() ? $o->get_date_created()->date( 'Y-m-d H:i:s' ) : null, 'date_modified' => $o->get_date_modified() ? $o->get_date_modified()->date( 'Y-m-d H:i:s' ) : null, 'date_completed' => $o->get_date_completed() ? $o->get_date_completed()->date( 'Y-m-d H:i:s' ) : null );
	}

	private function getCustomers( array $params ): array {
		$per_page = max( 1, min( 100, (int) ( $params['per_page'] ?? 10 ) ) );
		$page     = max( 1, (int) ( $params['page'] ?? 1 ) );
		$search   = sanitize_text_field( $params['search'] ?? '' );
		$orderby  = sanitize_text_field( $params['orderby'] ?? 'registered' );
		$order    = strtoupper( $params['order'] ?? 'DESC' ) === 'ASC' ? 'ASC' : 'DESC';

		$args = array( 'role__in' => array( 'customer', 'subscriber' ), 'number' => $per_page, 'paged' => $page, 'orderby' => $orderby, 'order' => $order );
		if ( $search ) { $args['search'] = '*' . $search . '*'; }

		$q     = new \WP_User_Query( $args );
		$users = $q->get_results();
		$items = array();
		foreach ( $users as $u ) {
			$c       = new \WC_Customer( $u->ID );
			$items[] = array( 'id' => $u->ID, 'username' => $u->user_login, 'email' => $u->user_email, 'first_name' => $c->get_first_name(), 'last_name' => $c->get_last_name(), 'orders_count' => $c->get_order_count(), 'total_spent' => $c->get_total_spent(), 'date_registered' => $u->user_registered, 'billing_city' => $c->get_billing_city(), 'billing_country' => $c->get_billing_country() );
		}
		return array( 'customers' => $items, 'page' => $page, 'per_page' => $per_page, 'total' => $q->get_total() );
	}

	private function getCategories( array $params ): array {
		$args = array( 'taxonomy' => 'product_cat', 'hide_empty' => (bool) ( $params['hide_empty'] ?? false ), 'orderby' => 'name', 'order' => 'ASC' );
		if ( isset( $params['parent'] ) ) { $args['parent'] = (int) $params['parent']; }
		$terms = get_terms( $args );
		if ( is_wp_error( $terms ) ) { throw new \Exception( esc_html( $terms->get_error_message() ) ); }
		$data = array();
		foreach ( $terms as $t ) { $data[] = array( 'id' => $t->term_id, 'name' => $t->name, 'slug' => $t->slug, 'count' => $t->count, 'parent' => $t->parent ); }
		return array( 'categories' => $data, 'total' => count( $data ) );
	}

	private function getCoupons( array $params ): array {
		$limit   = min( (int) ( $params['limit'] ?? 20 ), 50 );
		$status  = sanitize_text_field( $params['status'] ?? 'publish' );
		$coupons = get_posts( array( 'post_type' => 'shop_coupon', 'post_status' => $status, 'posts_per_page' => $limit, 'orderby' => 'date', 'order' => 'DESC' ) );
		$data    = array();
		foreach ( $coupons as $cp ) {
			$c      = new \WC_Coupon( $cp->ID );
			$data[] = array( 'id' => $c->get_id(), 'code' => $c->get_code(), 'discount_type' => $c->get_discount_type(), 'amount' => $c->get_amount(), 'usage_count' => $c->get_usage_count(), 'usage_limit' => $c->get_usage_limit(), 'expiry_date' => $c->get_date_expires() ? $c->get_date_expires()->date( 'Y-m-d' ) : null, 'minimum_amount' => $c->get_minimum_amount(), 'individual_use' => $c->get_individual_use(), 'status' => $cp->post_status );
		}
		return array( 'coupons' => $data, 'total' => count( $data ) );
	}

	private function getReports( array $params ): array {
		$period = $params['period'] ?? '7days';
		$now    = current_time( 'timestamp' );
		$after  = match ( $period ) {
			'today'           => gmdate( 'Y-m-d', $now ),
			'30days', 'month' => gmdate( 'Y-m-d', strtotime( '-30 days', $now ) ),
			'year'            => gmdate( 'Y-01-01', $now ),
			default           => gmdate( 'Y-m-d', strtotime( '-7 days', $now ) ),
		};

		$orders       = wc_get_orders( array( 'status' => array( 'completed', 'processing' ), 'date_after' => $after, 'limit' => -1, 'return' => 'objects' ) );
		$total_sales  = 0.0;
		$total_tax    = 0.0;
		$total_items  = 0;
		$product_sold = array();

		foreach ( $orders as $o ) {
			$total_sales += (float) $o->get_total();
			$total_tax   += (float) $o->get_total_tax();
			foreach ( $o->get_items() as $item ) {
				$total_items   += $item->get_quantity();
				$pid            = $item->get_product_id();
				if ( ! isset( $product_sold[ $pid ] ) ) { $product_sold[ $pid ] = array( 'name' => $item->get_name(), 'qty' => 0, 'revenue' => 0.0 ); }
				$product_sold[ $pid ]['qty']     += $item->get_quantity();
				$product_sold[ $pid ]['revenue'] += (float) $item->get_total();
			}
		}

		uasort( $product_sold, fn( $a, $b ) => $b['qty'] <=> $a['qty'] );
		return array( 'period' => $period, 'date_from' => $after, 'date_to' => gmdate( 'Y-m-d', $now ), 'total_orders' => count( $orders ), 'total_sales' => round( $total_sales, 2 ), 'net_revenue' => round( $total_sales - $total_tax, 2 ), 'total_tax' => round( $total_tax, 2 ), 'items_sold' => $total_items, 'top_products' => array_slice( array_values( $product_sold ), 0, 5 ) );
	}
}

