<?php
defined( 'ABSPATH' ) || exit;

/**
 * Creates and removes dummy demo data for the analytics dashboard.
 * Used by both the WP-CLI seed script and the admin settings page.
 */
class WAD_Seeder {

	// ─── Public API ───────────────────────────────────────────────────────────

	/**
	 * Seed all demo data. Returns counts of created items.
	 *
	 * @return array{ products: int, customers: int, orders: int }
	 */
	public static function seed(): array {
		set_time_limit( 0 );
		ignore_user_abort( true );

		self::suppress_emails();

		$cat_ids      = self::create_categories();
		$product_ids  = self::create_products( $cat_ids );
		$customer_ids = self::create_customers();
		$order_count  = self::create_orders( $product_ids, $customer_ids );

		self::bust_cache();

		return [
			'products'  => count( $product_ids ),
			'customers' => count( $customer_ids ),
			'orders'    => $order_count,
		];
	}

	/**
	 * Remove all seeded demo data. Returns counts of removed items.
	 *
	 * @return array{ products: int, customers: int, orders: int }
	 */
	public static function clean(): array {
		set_time_limit( 0 );

		// Orders (supports both HPOS and legacy post table)
		$order_ids = wc_get_orders( [
			'limit'      => -1,
			'meta_key'   => '_wad_seeded',
			'meta_value' => '1',
			'return'     => 'ids',
		] );
		foreach ( $order_ids as $id ) {
			$order = wc_get_order( $id );
			if ( $order ) {
				$order->delete( true );
			}
		}

		// Products
		$product_ids = get_posts( [
			'post_type'   => 'product',
			'numberposts' => -1,
			'post_status' => 'any',
			'fields'      => 'ids',
			'meta_key'    => '_wad_seeded',
			'meta_value'  => '1',
		] );
		foreach ( $product_ids as $id ) {
			wp_delete_post( $id, true );
		}

		// Customers
		$customer_ids = get_users( [
			'meta_key'   => '_wad_seeded',
			'meta_value' => '1',
			'fields'     => 'ID',
		] );
		foreach ( $customer_ids as $id ) {
			wp_delete_user( $id );
		}

		// Categories (only if empty after product removal)
		$cat_ids = get_terms( [
			'taxonomy'   => 'product_cat',
			'hide_empty' => false,
			'fields'     => 'ids',
			'meta_query' => [ [ 'key' => '_wad_seeded', 'value' => '1' ] ],
		] );
		foreach ( $cat_ids as $id ) {
			wp_delete_term( $id, 'product_cat' );
		}

		self::bust_cache();

		return [
			'products'  => count( $product_ids ),
			'customers' => count( $customer_ids ),
			'orders'    => count( $order_ids ),
		];
	}

	/** Returns true if any seeded data currently exists. */
	public static function has_seeded_data(): bool {
		$products = get_posts( [
			'post_type'   => 'product',
			'numberposts' => 1,
			'post_status' => 'any',
			'fields'      => 'ids',
			'meta_key'    => '_wad_seeded',
			'meta_value'  => '1',
		] );
		return ! empty( $products );
	}

	// ─── Email suppression ────────────────────────────────────────────────────

	public static function suppress_emails(): void {
		foreach ( [
			'woocommerce_email_enabled_new_order',
			'woocommerce_email_enabled_cancelled_order',
			'woocommerce_email_enabled_failed_order',
			'woocommerce_email_enabled_customer_on_hold_order',
			'woocommerce_email_enabled_customer_processing_order',
			'woocommerce_email_enabled_customer_completed_order',
			'woocommerce_email_enabled_customer_refunded_order',
			'woocommerce_email_enabled_customer_invoice',
			'woocommerce_email_enabled_new_customer',
		] as $filter ) {
			add_filter( $filter, '__return_false' );
		}

		remove_action( 'register_new_user',      'wp_send_new_user_notifications' );
		remove_action( 'edit_user_created_user', 'wp_send_new_user_notifications' );
	}

	// ─── Private helpers ──────────────────────────────────────────────────────

	private static function rand_date( int $days_ago_min, int $days_ago_max ): string {
		$ts = time() - rand( $days_ago_min * DAY_IN_SECONDS, $days_ago_max * DAY_IN_SECONDS );
		return gmdate( 'Y-m-d H:i:s', $ts );
	}

	private static function rand_price( float $min, float $max ): float {
		return round( $min + mt_rand() / mt_getrandmax() * ( $max - $min ), 2 );
	}

	private static function bust_cache(): void {
		foreach ( [ '7d', '1m', '3m', '6m', '1y' ] as $range ) {
			delete_transient( 'wad_overview_' . $range );
			delete_transient( 'wad_revenue_chart_' . $range );
		}
		foreach ( [ 6, 10, 20 ] as $limit ) {
			delete_transient( 'wad_recent_orders_' . $limit );
		}
		delete_transient( 'wad_ai_store_context' );
	}

	// ─── Categories ───────────────────────────────────────────────────────────

	private static function create_categories(): array {
		$definitions = [
			'Dresses'     => 'dress',
			'Tops'        => 'top',
			'Trousers'    => 'trouser',
			'Jackets'     => 'jacket',
			'Shoes'       => 'shoes',
			'Bags'        => 'bag',
			'Accessories' => 'accessory',
		];

		$cat_ids = [];
		foreach ( $definitions as $name => $slug ) {
			$existing = get_term_by( 'slug', 'seed-' . $slug, 'product_cat' );
			if ( $existing ) {
				$cat_ids[ $name ] = $existing->term_id;
				continue;
			}
			$term = wp_insert_term( $name, 'product_cat', [ 'slug' => 'seed-' . $slug ] );
			if ( ! is_wp_error( $term ) ) {
				$cat_ids[ $name ] = $term['term_id'];
				update_term_meta( $term['term_id'], '_wad_seeded', '1' );
			}
		}

		return $cat_ids;
	}

	// ─── Products ─────────────────────────────────────────────────────────────

	private static function create_products( array $cat_ids ): array {
		$definitions = [
			[ 'name' => 'Silk Slip Dress',             'cat' => 'Dresses',     'price' => [ 89, 149 ],  'stock' => [ 5, 40 ] ],
			[ 'name' => 'Floral Wrap Dress',           'cat' => 'Dresses',     'price' => [ 65, 110 ],  'stock' => [ 8, 50 ] ],
			[ 'name' => 'Linen Midi Dress',            'cat' => 'Dresses',     'price' => [ 75, 130 ],  'stock' => [ 3, 30 ] ],
			[ 'name' => 'Velvet Evening Gown',         'cat' => 'Dresses',     'price' => [ 145, 220 ], 'stock' => [ 2, 15 ] ],
			[ 'name' => 'Broderie Anglaise Sundress',  'cat' => 'Dresses',     'price' => [ 55, 90 ],   'stock' => [ 10, 60 ] ],
			[ 'name' => 'Ribbed Knit Mini Dress',      'cat' => 'Dresses',     'price' => [ 49, 79 ],   'stock' => [ 6, 45 ] ],
			[ 'name' => 'Satin Bias-Cut Dress',        'cat' => 'Dresses',     'price' => [ 95, 165 ],  'stock' => [ 4, 25 ] ],
			[ 'name' => 'Classic Stripe Breton',       'cat' => 'Tops',        'price' => [ 35, 60 ],   'stock' => [ 15, 80 ] ],
			[ 'name' => 'Silk Cami Top',               'cat' => 'Tops',        'price' => [ 42, 75 ],   'stock' => [ 10, 55 ] ],
			[ 'name' => 'Oversized Linen Shirt',       'cat' => 'Tops',        'price' => [ 55, 90 ],   'stock' => [ 8, 50 ] ],
			[ 'name' => 'Ruched Bandeau Top',          'cat' => 'Tops',        'price' => [ 28, 50 ],   'stock' => [ 12, 70 ] ],
			[ 'name' => 'Puff Sleeve Blouse',          'cat' => 'Tops',        'price' => [ 48, 85 ],   'stock' => [ 5, 35 ] ],
			[ 'name' => 'Ribbed Crop Jumper',          'cat' => 'Tops',        'price' => [ 38, 65 ],   'stock' => [ 9, 60 ] ],
			[ 'name' => 'Off-Shoulder Bodysuit',       'cat' => 'Tops',        'price' => [ 32, 55 ],   'stock' => [ 7, 40 ] ],
			[ 'name' => 'Wide-Leg Tailored Trousers',  'cat' => 'Trousers',    'price' => [ 70, 120 ],  'stock' => [ 6, 40 ] ],
			[ 'name' => 'High-Rise Skinny Jeans',      'cat' => 'Trousers',    'price' => [ 60, 95 ],   'stock' => [ 10, 65 ] ],
			[ 'name' => 'Linen Palazzo Pants',         'cat' => 'Trousers',    'price' => [ 65, 100 ],  'stock' => [ 5, 35 ] ],
			[ 'name' => 'Leather-Look Trousers',       'cat' => 'Trousers',    'price' => [ 75, 130 ],  'stock' => [ 4, 25 ] ],
			[ 'name' => 'Cropped Straight Jeans',      'cat' => 'Trousers',    'price' => [ 55, 85 ],   'stock' => [ 8, 50 ] ],
			[ 'name' => 'Classic Trench Coat',         'cat' => 'Jackets',     'price' => [ 165, 280 ], 'stock' => [ 3, 20 ] ],
			[ 'name' => 'Oversized Blazer',            'cat' => 'Jackets',     'price' => [ 110, 190 ], 'stock' => [ 4, 25 ] ],
			[ 'name' => 'Quilted Puffer Jacket',       'cat' => 'Jackets',     'price' => [ 120, 200 ], 'stock' => [ 5, 30 ] ],
			[ 'name' => 'Faux-Leather Biker Jacket',   'cat' => 'Jackets',     'price' => [ 95, 165 ],  'stock' => [ 3, 18 ] ],
			[ 'name' => 'Denim Jacket',                'cat' => 'Jackets',     'price' => [ 75, 125 ],  'stock' => [ 6, 40 ] ],
			[ 'name' => 'Block Heel Mules',            'cat' => 'Shoes',       'price' => [ 65, 110 ],  'stock' => [ 4, 30 ] ],
			[ 'name' => 'Strappy Heeled Sandals',      'cat' => 'Shoes',       'price' => [ 75, 130 ],  'stock' => [ 5, 35 ] ],
			[ 'name' => 'Leather Chelsea Boots',       'cat' => 'Shoes',       'price' => [ 120, 210 ], 'stock' => [ 3, 20 ] ],
			[ 'name' => 'Pointed-Toe Flats',           'cat' => 'Shoes',       'price' => [ 55, 90 ],   'stock' => [ 6, 40 ] ],
			[ 'name' => 'Platform Trainers',           'cat' => 'Shoes',       'price' => [ 85, 145 ],  'stock' => [ 4, 28 ] ],
			[ 'name' => 'Kitten Heel Slingbacks',      'cat' => 'Shoes',       'price' => [ 70, 120 ],  'stock' => [ 5, 32 ] ],
			[ 'name' => 'Mini Crossbody Bag',          'cat' => 'Bags',        'price' => [ 45, 80 ],   'stock' => [ 8, 50 ] ],
			[ 'name' => 'Structured Tote Bag',         'cat' => 'Bags',        'price' => [ 95, 160 ],  'stock' => [ 4, 25 ] ],
			[ 'name' => 'Quilted Chain Bag',           'cat' => 'Bags',        'price' => [ 110, 190 ], 'stock' => [ 3, 18 ] ],
			[ 'name' => 'Woven Raffia Basket',         'cat' => 'Bags',        'price' => [ 55, 90 ],   'stock' => [ 6, 35 ] ],
			[ 'name' => 'Leather Clutch',              'cat' => 'Bags',        'price' => [ 65, 115 ],  'stock' => [ 5, 30 ] ],
			[ 'name' => 'Silk Square Scarf',           'cat' => 'Accessories', 'price' => [ 28, 55 ],   'stock' => [ 10, 80 ] ],
			[ 'name' => 'Oversized Sunglasses',        'cat' => 'Accessories', 'price' => [ 35, 70 ],   'stock' => [ 8, 60 ] ],
			[ 'name' => 'Wide-Brim Sun Hat',           'cat' => 'Accessories', 'price' => [ 40, 75 ],   'stock' => [ 6, 45 ] ],
			[ 'name' => 'Delicate Gold Necklace',      'cat' => 'Accessories', 'price' => [ 32, 65 ],   'stock' => [ 12, 90 ] ],
			[ 'name' => 'Leather Belt',                'cat' => 'Accessories', 'price' => [ 35, 65 ],   'stock' => [ 9, 55 ] ],
			[ 'name' => 'Hoop Earring Set',            'cat' => 'Accessories', 'price' => [ 22, 45 ],   'stock' => [ 15, 100 ] ],
			[ 'name' => 'Cashmere Beanie',             'cat' => 'Accessories', 'price' => [ 38, 70 ],   'stock' => [ 7, 50 ] ],
		];

		$product_ids = [];
		$sku_counter = 1000;

		foreach ( $definitions as $p ) {
			$sku   = 'ME-' . $sku_counter++;
			$price = self::rand_price( $p['price'][0], $p['price'][1] );
			$stock = rand( $p['stock'][0], $p['stock'][1] );

			$product = new WC_Product_Simple();
			$product->set_name( $p['name'] );
			$product->set_status( 'publish' );
			$product->set_sku( $sku );
			$product->set_regular_price( $price );
			$product->set_price( $price );
			$product->set_manage_stock( true );
			$product->set_stock_quantity( $stock );
			$product->set_stock_status( $stock > 0 ? 'instock' : 'outofstock' );
			$product->set_category_ids( isset( $cat_ids[ $p['cat'] ] ) ? [ $cat_ids[ $p['cat'] ] ] : [] );
			$product->set_short_description( 'A premium ' . strtolower( $p['name'] ) . ' from the ModaExpress collection.' );

			$pid = $product->save();
			update_post_meta( $pid, '_wad_seeded', '1' );
			$product_ids[] = [ 'id' => $pid, 'price' => $price, 'name' => $p['name'] ];
		}

		return $product_ids;
	}

	// ─── Customers ────────────────────────────────────────────────────────────

	private static function create_customers(): array {
		$definitions = [
			[ 'first' => 'Sophie',    'last' => 'Harrison',  'city' => 'London' ],
			[ 'first' => 'Emma',      'last' => 'Clarke',    'city' => 'Manchester' ],
			[ 'first' => 'Olivia',    'last' => 'Bennett',   'city' => 'Bristol' ],
			[ 'first' => 'Charlotte', 'last' => 'Williams',  'city' => 'Edinburgh' ],
			[ 'first' => 'Amelia',    'last' => 'Johnson',   'city' => 'Leeds' ],
			[ 'first' => 'Isabella',  'last' => 'Davis',     'city' => 'Liverpool' ],
			[ 'first' => 'Mia',       'last' => 'Taylor',    'city' => 'Brighton' ],
			[ 'first' => 'Grace',     'last' => 'Anderson',  'city' => 'Oxford' ],
			[ 'first' => 'Lucy',      'last' => 'Martin',    'city' => 'Cambridge' ],
			[ 'first' => 'Hannah',    'last' => 'Thompson',  'city' => 'Birmingham' ],
			[ 'first' => 'Lily',      'last' => 'White',     'city' => 'Glasgow' ],
			[ 'first' => 'Poppy',     'last' => 'Wilson',    'city' => 'Cardiff' ],
			[ 'first' => 'Freya',     'last' => 'Moore',     'city' => 'Bath' ],
			[ 'first' => 'Jessica',   'last' => 'Brown',     'city' => 'Sheffield' ],
			[ 'first' => 'Chloe',     'last' => 'Jackson',   'city' => 'Newcastle' ],
			[ 'first' => 'Evie',      'last' => 'Harris',    'city' => 'Nottingham' ],
			[ 'first' => 'Alice',     'last' => 'Lewis',     'city' => 'Southampton' ],
			[ 'first' => 'Daisy',     'last' => 'Walker',    'city' => 'Portsmouth' ],
			[ 'first' => 'Ruby',      'last' => 'Hall',      'city' => 'Leicester' ],
			[ 'first' => 'Scarlett',  'last' => 'Allen',     'city' => 'Coventry' ],
			[ 'first' => 'Maya',      'last' => 'Young',     'city' => 'Norwich' ],
			[ 'first' => 'Ellie',     'last' => 'King',      'city' => 'Reading' ],
			[ 'first' => 'Isla',      'last' => 'Wright',    'city' => 'York' ],
			[ 'first' => 'Zoe',       'last' => 'Scott',     'city' => 'Exeter' ],
			[ 'first' => 'Naomi',     'last' => 'Green',     'city' => 'Canterbury' ],
		];

		$postcodes    = [ 'SW1A 1AA', 'M1 1AE', 'BS1 4DJ', 'EH1 1YZ', 'LS1 1BA', 'L1 8JQ', 'BN1 1AF', 'OX1 1BP', 'CB2 1TN', 'B1 1BB' ];
		$customer_ids = [];

		foreach ( $definitions as $c ) {
			$suffix   = rand( 10, 99 );
			$email    = strtolower( $c['first'] . '.' . $c['last'] . $suffix . '@example.com' );
			$username = strtolower( $c['first'] . $c['last'] . $suffix );

			if ( email_exists( $email ) ) {
				$user           = get_user_by( 'email', $email );
				$customer_ids[] = $user->ID;
				continue;
			}

			$uid = wp_insert_user( [
				'user_login'   => $username,
				'user_email'   => $email,
				'user_pass'    => wp_generate_password(),
				'first_name'   => $c['first'],
				'last_name'    => $c['last'],
				'role'         => 'customer',
				'display_name' => $c['first'] . ' ' . $c['last'],
			] );

			if ( is_wp_error( $uid ) ) continue;

			$postcode = $postcodes[ array_rand( $postcodes ) ];
			$address  = rand( 1, 99 ) . ' ' . $c['last'] . ' Street';

			foreach ( [ 'billing', 'shipping' ] as $type ) {
				update_user_meta( $uid, "{$type}_first_name", $c['first'] );
				update_user_meta( $uid, "{$type}_last_name",  $c['last'] );
				update_user_meta( $uid, "{$type}_address_1",  $address );
				update_user_meta( $uid, "{$type}_city",       $c['city'] );
				update_user_meta( $uid, "{$type}_postcode",   $postcode );
				update_user_meta( $uid, "{$type}_country",    'GB' );
			}
			update_user_meta( $uid, 'billing_email', $email );
			update_user_meta( $uid, '_wad_seeded',   '1' );

			$customer_ids[] = $uid;
		}

		return $customer_ids;
	}

	// ─── Orders ───────────────────────────────────────────────────────────────

	private static function create_orders( array $product_ids, array $customer_ids ): int {
		// [ min_days_ago, max_days_ago, count, completed_probability ]
		$batches = [
			[ 1,   7,   18,  0.60 ],
			[ 8,   30,  30,  0.65 ],
			[ 31,  90,  45,  0.70 ],
			[ 91,  180, 55,  0.75 ],
			[ 181, 365, 55,  0.80 ],
		];

		$order_count = 0;

		foreach ( $batches as [ $min_days, $max_days, $count, $completed_weight ] ) {
			for ( $i = 0; $i < $count; $i++ ) {
				$customer_id = $customer_ids[ array_rand( $customer_ids ) ];
				$customer    = new WC_Customer( $customer_id );

				$num_items    = rand( 1, 4 );
				$item_indices = (array) array_rand( $product_ids, min( $num_items, count( $product_ids ) ) );

				$rv = mt_rand() / mt_getrandmax();
				if ( $rv < $completed_weight )              $status = 'wc-completed';
				elseif ( $rv < $completed_weight + 0.15 )  $status = 'wc-processing';
				elseif ( $rv < $completed_weight + 0.22 )  $status = 'wc-on-hold';
				elseif ( $rv < $completed_weight + 0.27 )  $status = 'wc-refunded';
				else                                        $status = 'wc-cancelled';

				$order_date = self::rand_date( $min_days, $max_days );

				$order = wc_create_order( [
					'customer_id' => $customer_id,
					'created_via' => 'seed',
					'status'      => $status,
				] );

				if ( is_wp_error( $order ) ) continue;

				foreach ( $item_indices as $idx ) {
					$product = wc_get_product( $product_ids[ $idx ]['id'] );
					if ( $product ) {
						$order->add_product( $product, rand( 1, 3 ) );
					}
				}

				$bf = $customer->get_billing_first_name();
				$bl = $customer->get_billing_last_name();
				$order->set_billing_first_name( $bf );
				$order->set_billing_last_name( $bl );
				$order->set_billing_email( $customer->get_billing_email() ?: $customer->get_email() );
				$order->set_billing_address_1( $customer->get_billing_address_1() );
				$order->set_billing_city( $customer->get_billing_city() );
				$order->set_billing_postcode( $customer->get_billing_postcode() );
				$order->set_billing_country( $customer->get_billing_country() ?: 'GB' );
				$order->set_shipping_first_name( $customer->get_shipping_first_name() ?: $bf );
				$order->set_shipping_last_name( $customer->get_shipping_last_name() ?: $bl );
				$order->set_shipping_address_1( $customer->get_shipping_address_1() ?: $customer->get_billing_address_1() );
				$order->set_shipping_city( $customer->get_shipping_city() ?: $customer->get_billing_city() );
				$order->set_shipping_postcode( $customer->get_shipping_postcode() ?: $customer->get_billing_postcode() );
				$order->set_shipping_country( $customer->get_shipping_country() ?: 'GB' );
				$order->set_payment_method( 'bacs' );
				$order->set_payment_method_title( 'Bank Transfer' );

				$order->calculate_totals();
				$order->save();

				// Back-date the order
				wp_update_post( [
					'ID'            => $order->get_id(),
					'post_date'     => $order_date,
					'post_date_gmt' => get_gmt_from_date( $order_date ),
				] );
				$order->set_date_created( $order_date );
				$order->save();

				update_post_meta( $order->get_id(), '_wad_seeded', '1' );
				$order_count++;
			}
		}

		return $order_count;
	}
}
