<?php
/**
 * WooCommerce integration mode.
 *
 * @package Lucrativeit_Subscription_Recurring_Billing
 */

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

/**
 * When the subscription engine is set to "WooCommerce", this class bridges
 * plugin plans to WooCommerce products and lets WooCommerce / WooCommerce
 * Subscriptions handle checkout, payment and recurring billing.
 */
class LUCRSURE_WooCommerce {

	/**
	 * Singleton.
	 *
	 * @var LUCRSURE_WooCommerce|null
	 */
	private static $instance = null;

	/**
	 * Get the singleton.
	 *
	 * @return LUCRSURE_WooCommerce
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Whether WooCommerce is active.
	 *
	 * @return bool
	 */
	public static function is_active() {
		return class_exists( 'WooCommerce' );
	}

	/**
	 * Whether WooCommerce Subscriptions is active.
	 *
	 * @return bool
	 */
	public static function subscriptions_active() {
		return class_exists( 'WC_Subscriptions' );
	}

	/**
	 * Hook into WooCommerce.
	 */
	public function init() {
		if ( ! self::is_active() ) {
			add_action( 'admin_notices', array( $this, 'missing_wc_notice' ) );
			return;
		}

		// Keep WooCommerce products in sync when plans change.
		add_action( 'lucrsure_plan_saved', array( $this, 'sync_plan_to_product' ), 10, 2 );

		// Mirror completed WooCommerce orders into the subscription/invoice tables.
		add_action( 'woocommerce_order_status_completed', array( $this, 'handle_order_completed' ) );
		add_action( 'woocommerce_payment_complete', array( $this, 'handle_order_completed' ) );
	}

	/**
	 * Admin notice when WooCommerce mode is selected but WooCommerce is missing.
	 */
	public function missing_wc_notice() {
		$screen = get_current_screen();
		if ( $screen && false === strpos( $screen->id, 'lucrsure' ) && false === strpos( $screen->id, 'lucrativeit' ) ) {
			return;
		}
		echo '<div class="notice notice-warning"><p>';
		echo esc_html(
			sprintf(
				/* translators: %s: plugin name */
				__( '%s is set to WooCommerce mode, but WooCommerce is not active. Install and activate WooCommerce, or switch to the Custom engine in Settings.', 'lucrativeit-subscription-recurring-billing' ),
				lucrsure_plugin_name()
			)
		);
		echo '</p></div>';
	}

	/**
	 * Create or update a WooCommerce product for a plan.
	 *
	 * @param int   $plan_id Plan ID.
	 * @param array $plan    Plan data.
	 */
	public function sync_plan_to_product( $plan_id, $plan ) {
		if ( ! self::is_active() || ! function_exists( 'wc_get_product' ) ) {
			return;
		}

		$product_id = isset( $plan['wc_product_id'] ) ? (int) $plan['wc_product_id'] : 0;

		// Prefer a subscription product type when WooCommerce Subscriptions exists.
		if ( self::subscriptions_active() && class_exists( 'WC_Product_Subscription' ) ) {
			$product = $product_id ? wc_get_product( $product_id ) : null;
			if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
				$product = new WC_Product_Subscription();
			}
			$effective_price = lucrsure_plan_effective_price( $plan );
			$product->update_meta_data( '_subscription_price', $effective_price );
			$product->update_meta_data( '_subscription_period', $plan['billing_interval'] );
			$product->update_meta_data( '_subscription_period_interval', (int) $plan['interval_count'] );
			if ( (int) $plan['trial_days'] > 0 ) {
				$product->update_meta_data( '_subscription_trial_length', (int) $plan['trial_days'] );
				$product->update_meta_data( '_subscription_trial_period', 'day' );
			}
		} else {
			$product = $product_id ? wc_get_product( $product_id ) : null;
			if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
				$product = new WC_Product_Simple();
			}
		}

		$product->set_name( $plan['name'] );
		$product->set_description( isset( $plan['description'] ) ? $plan['description'] : '' );
		$product->set_regular_price( (string) $plan['price'] );
		if ( lucrsure_plan_has_special_price( $plan ) ) {
			$product->set_sale_price( (string) lucrsure_plan_effective_price( $plan ) );
		} else {
			$product->set_sale_price( '' );
		}
		$product->set_catalog_visibility( 'visible' );
		$product->set_status( ! empty( $plan['is_active'] ) ? 'publish' : 'draft' );

		$new_product_id = $product->save();

		if ( $new_product_id && $new_product_id !== $product_id ) {
			$plans = new LUCRSURE_Plan_Repository();
			$plans->update( $plan_id, array( 'wc_product_id' => (int) $new_product_id ) );
		}
	}

	/**
	 * Mirror a completed WooCommerce order into customers/subscriptions/invoices.
	 *
	 * @param int $order_id Order ID.
	 */
	public function handle_order_completed( $order_id ) {
		if ( ! function_exists( 'wc_get_order' ) ) {
			return;
		}

		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			return;
		}

		$customers = new LUCRSURE_Customer_Repository();
		$plans     = new LUCRSURE_Plan_Repository();
		$subs      = new LUCRSURE_Subscription_Repository();
		$invoices  = new LUCRSURE_Invoice_Repository();

		$email = $order->get_billing_email();
		$name  = trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() );
		$billing = lucrsure_sanitize_billing_address(
			array(
				'billing_address_1' => $order->get_billing_address_1(),
				'billing_address_2' => $order->get_billing_address_2(),
				'billing_city'      => $order->get_billing_city(),
				'billing_state'     => $order->get_billing_state(),
				'billing_postcode'  => $order->get_billing_postcode(),
				'billing_country'   => $order->get_billing_country(),
			)
		);

		$customer = $customers->find_by_email( $email );
		if ( ! $customer ) {
			$customer_id = $customers->insert(
				array_merge(
					array(
						'user_id' => (int) $order->get_user_id(),
						'name'    => $name ? $name : $email,
						'email'   => $email,
						'phone'   => $order->get_billing_phone(),
						'company' => $order->get_billing_company(),
						'status'  => 'active',
					),
					$billing
				)
			);
		} else {
			$customer_id = (int) $customer['id'];
			$customers->update(
				$customer_id,
				array_merge(
					array(
						'name'    => $name ? $name : $customer['name'],
						'phone'   => $order->get_billing_phone(),
						'company' => $order->get_billing_company(),
					),
					$billing
				)
			);
		}

		foreach ( $order->get_items() as $item ) {
			$product_id = $item->get_product_id();

			global $wpdb;
			$plan = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery,PluginCheck.Security.DirectDB.UnescapedDBParameter
				$wpdb->prepare( 'SELECT * FROM %i WHERE wc_product_id = %d', lucrsure_table( 'plans' ), $product_id ),
				ARRAY_A
			);

			if ( ! $plan ) {
				continue;
			}

			$sub_id = $subs->insert(
				array(
					'customer_id'          => $customer_id,
					'plan_id'              => (int) $plan['id'],
					'status'               => 'active',
					'quantity'             => (int) $item->get_quantity(),
					'mrr'                  => lucrsure_plan_effective_price( $plan ),
					'start_date'           => current_time( 'mysql' ),
					'current_period_start' => current_time( 'mysql' ),
					'current_period_end'   => lucrsure_next_period_end( $plan['billing_interval'], (int) $plan['interval_count'] ),
					'gateway'              => 'woocommerce',
					'auto_renew'           => 1,
				)
			);

			$invoices->insert(
				array_merge(
					array(
						'invoice_number'     => $invoices->next_number(),
						'customer_id'        => $customer_id,
						'subscription_id'    => $sub_id,
						'amount'             => (float) $item->get_total(),
						'currency'           => $order->get_currency(),
						'status'             => 'paid',
						'paid_at'            => current_time( 'mysql' ),
						'gateway'            => 'woocommerce',
						'gateway_payment_id' => (string) $order_id,
					),
					$billing
				)
			);
		}
	}
}
