<?php

namespace WC_Affiliate\Models;

use WP_Error;

defined( 'ABSPATH' ) || exit;

/**
 * Class DataExporter
 *
 * Handles data export operations for various data types.
 */
class DataExporter {

	/**
	 * Export data for a specific type.
	 *
	 * @param string $type         Data type to export.
	 * @param int    $affiliate_id Optional affiliate ID filter.
	 *
	 * @return array|WP_Error Export data or error.
	 */
	public static function export_data( string $type, int $affiliate_id = 0 ) {
		/**
		 * Filter to allow preventing export operations.
		 *
		 * @param bool   $can_export   Whether the export can proceed.
		 * @param string $type         Export type.
		 * @param int    $affiliate_id Affiliate ID filter.
		 */
		$can_export = apply_filters( 'wc_affiliate_can_export_data', true, $type, $affiliate_id );
		if ( ! $can_export ) {
			return new \WP_Error( 'export_not_allowed', __( 'Export operation not allowed.', 'wc-affiliate' ) );
		}

		/**
		 * Action hook fired before data export.
		 *
		 * @param string $type         Export type.
		 * @param int    $affiliate_id Affiliate ID filter.
		 */
		do_action( 'wc_affiliate_data_exporter_before_export', $type, $affiliate_id );

		switch ( $type ) {
			case 'shortlinks':
				$result = self::export_shortlinks();
				break;
			case 'affiliates':
				$result = self::export_affiliates( $affiliate_id );
				break;
			default:
				return new \WP_Error( 'invalid_export_type', __( 'Invalid export type.', 'wc-affiliate' ) );
		}

		/**
		 * Filter to modify exported data.
		 *
		 * @param array|WP_Error $result       Export result.
		 * @param string         $type         Export type.
		 * @param int            $affiliate_id Affiliate ID filter.
		 */
		$result = apply_filters( 'wc_affiliate_data_exporter_export_data', $result, $type, $affiliate_id );

		/**
		 * Action hook fired after data export.
		 *
		 * @param array|WP_Error $result       Export result.
		 * @param string         $type         Export type.
		 * @param int            $affiliate_id Affiliate ID filter.
		 */
		do_action( 'wc_affiliate_data_exporter_after_export', $result, $type, $affiliate_id );

		return $result;
	}

	/**
	 * Export shortlinks data.
	 *
	 * @return array Shortlinks data.
	 */
	private static function export_shortlinks(): array {
		/**
		 * Action hook fired before shortlinks export.
		 */
		do_action( 'wc_affiliate_data_exporter_before_export_shortlinks' );
		global $wpdb;

		$name  = 'shortlinks';
		$table = $wpdb->prefix . 'wca_' . $name;

		if ( is_multisite() ) {
			$blog_id = get_current_blog_id();
			$table   = $wpdb->base_prefix . $blog_id . '_wca_' . $name;
		}

		$table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) );
		if ( $table_exists !== $table ) {
			return new \WP_Error( 'table_not_found', __( 'Shortlinks table does not exist.', 'wc-affiliate' ) );
		}

		$query   = 'SELECT * FROM ' . esc_sql( $table );
		$results = $wpdb->get_results( $query );

		if ( empty( $results ) ) {
			return new \WP_Error( 'no_data', __( 'No shortlinks data found for export.', 'wc-affiliate' ) );
		}

		$headings = array( 'id', 'affiliate', 'page_url', 'campaign', 'identifier', 'time' );
		$data     = array();

		foreach ( $results as $result ) {
			$user   = get_userdata( $result->affiliate );
			$data[] = array(
				'id'         => $result->id,
				'affiliate'  => $user ? $user->user_email : 'Unknown',
				'page_url'   => $result->page_url,
				'campaign'   => $result->campaign,
				'identifier' => $result->identifier,
				'time'       => $result->time,
			);
		}

		$result = array(
			'headings' => $headings,
			'data'     => $data,
		);

		/**
		 * Action hook fired after shortlinks export.
		 *
		 * @param array $result Export result.
		 */
		do_action( 'wc_affiliate_data_exporter_after_export_shortlinks', $result );

		return $result;
	}

	/**
	 * Get the proper usermeta table name for multi-site support.
	 *
	 * @return string The usermeta table name.
	 */
	public static function get_usermeta_table(): string {
		global $wpdb;

		$meta_table = $wpdb->prefix . 'usermeta';

		if ( is_multisite() ) {
			$blog_id    = get_current_blog_id();
			$meta_table = $wpdb->base_prefix . $blog_id . '_usermeta';
		}

		return $meta_table;
	}

	/**
	 * Export affiliates data.
	 *
	 * @param int $affiliate_id Optional affiliate ID filter.
	 *
	 * @return array Affiliates data.
	 */
	private static function export_affiliates( int $affiliate_id = 0 ): array {
		/**
		 * Action hook fired before affiliates export.
		 *
		 * @param int $affiliate_id Affiliate ID filter.
		 */
		do_action( 'wc_affiliate_data_exporter_before_export_affiliates', $affiliate_id );
		global $wpdb;

		if ( is_multisite() ) {
			$blog_id    = get_current_blog_id();
			$meta_table = $wpdb->base_prefix . $blog_id . '_usermeta';
		} else {
			$meta_table = $wpdb->prefix . 'usermeta';
		}

		// If current user is an affiliate (not admin), limit to their own data.
		$current_user_id   = get_current_user_id();
		$is_affiliate_only = ! current_user_can( 'manage_options' ) && wca_is_affiliate( $current_user_id );

		$affiliate_model = new Affiliate();
		if ( $is_affiliate_only ) {
			$affiliates_data = array();
			$affiliate       = $affiliate_model->get_by_user_id( $current_user_id );
			if ( $affiliate ) {
				$affiliates_data[] = (object) array(
					'user_id'    => $current_user_id,
					'meta_value' => $affiliate->get( 'time_applied' ) ?? time(),
				);
			}
		} else {
			// Get all affiliates or specific affiliate.
			$args = array();
			if ( $affiliate_id > 0 ) {
				$args['user_id'] = $affiliate_id;
			}

			$affiliates      = $affiliate_model->get_affiliates( $args );
			$affiliates_data = array();

			foreach ( $affiliates as $affiliate ) {
				$affiliates_data[] = (object) array(
					'user_id'    => $affiliate->user_id,
					'meta_value' => $affiliate->get( 'time_applied' ) ?? time(),
				);
			}
		}

		if ( empty( $affiliates_data ) ) {
			return new \WP_Error( 'no_data', __( 'No affiliates data found for export.', 'wc-affiliate' ) );
		}

		$headings = array(
			'user_id',
			'user_login',
			'user_email',
			'display_name',
			'first_name',
			'last_name',
			'affiliate_status',
			'commission_type',
			'commission_amount',
			'payment_method',
			'payment_details',
			'time_applied',
			'referrer',
			'website_url',
			'promotion_method',
		);

		$data = array();
		foreach ( $affiliates_data as $affiliate_data ) {
			$user = get_userdata( $affiliate_data->user_id );
			if ( ! $user ) {
				continue;
			}

			$user_model = new User( $affiliate_data->user_id );

			$data[] = array(
				'user_id'           => $user->ID,
				'user_login'        => $user->user_login,
				'user_email'        => $user->user_email,
				'display_name'      => $user->display_name,
				'first_name'        => $user->first_name,
				'last_name'         => $user->last_name,
				'affiliate_status'  => $user_model->get_meta( '_wc_affiliate_status' ),
				'commission_type'   => $user_model->get_meta( 'commission_type' ),
				'commission_amount' => $user_model->get_meta( 'commission_amount' ),
				'payment_method'    => $user_model->get_meta( '_wc_affiliate_payout_method' ),
				'payment_details'   => $user_model->get_meta( '_wc_affiliate_payment_details' ),
				'time_applied'      => $affiliate_data->meta_value,
				'referrer'          => $user_model->get_meta( '_wc_affiliate_referrer' ),
				'website_url'       => $user_model->get_meta( '_wc_affiliate_website_url' ),
				'promotion_method'  => $user_model->get_meta( '_wc_affiliate_promotion_method' ),
			);
		}

		$result = array(
			'headings' => $headings,
			'data'     => $data,
		);

		/**
		 * Action hook fired after affiliates export.
		 *
		 * @param array $result       Export result.
		 * @param int   $affiliate_id Affiliate ID filter.
		 */
		do_action( 'wc_affiliate_data_exporter_after_export_affiliates', $result, $affiliate_id );

		return $result;
	}
}
