<?php

namespace WPKIN_SHOP_MANAGER\Modules;

if ( ! defined( 'ABSPATH' ) ) {
	wp_die( esc_html__( 'You can\'t access this page', 'shop-manager' ) );
}

/**
 * Employee Manager Module
 *
 * Handles custom WP roles, activity logging, and admin access blocking
 * for oxi_sm_* employee roles.
 *
 * @since 1.2.1
 */
class EmployeeManager {

	private static array $oxi_roles = [
		'oxi_sm_fulfillment',
		'oxi_sm_product_manager',
		'oxi_sm_accountant',
		'oxi_sm_manager',
	];

	public static function init(): void {
		add_action( 'admin_init', [ self::class, 'redirect_oxi_users_from_admin' ] );
		add_action( 'woocommerce_order_status_changed', [ self::class, 'log_order_status_change' ], 10, 4 );
		add_action( 'profile_update',                   [ self::class, 'log_customer_update' ],      10, 2 );

		// Map oxi_sm_* capabilities to the WC/WP core caps that WooCommerce REST API checks.
		add_filter( 'user_has_cap', [ self::class, 'map_oxi_to_wc_caps' ], 10, 4 );
	}

	public static function register_roles(): void {
		add_role(
			'oxi_sm_fulfillment',
			'SM: Fulfillment Staff',
			[
				'read'               => true,
				'oxi_sm_view_orders' => true,
				'oxi_sm_edit_orders' => true,
			]
		);

		add_role(
			'oxi_sm_product_manager',
			'SM: Product Manager',
			[
				'read'                 => true,
				'oxi_sm_view_products' => true,
				'oxi_sm_edit_products' => true,
			]
		);

		add_role(
			'oxi_sm_accountant',
			'SM: Accountant',
			[
				'read'                  => true,
				'oxi_sm_view_analytics' => true,
			]
		);

		add_role(
			'oxi_sm_manager',
			'SM: Store Manager',
			[
				'read'                  => true,
				'oxi_sm_view_orders'    => true,
				'oxi_sm_edit_orders'    => true,
				'oxi_sm_view_products'  => true,
				'oxi_sm_edit_products'  => true,
				'oxi_sm_view_customers' => true,
				'oxi_sm_view_analytics' => true,
			]
		);
	}

	public static function remove_roles(): void {
		foreach ( self::$oxi_roles as $role ) {
			remove_role( $role );
		}
	}

	public static function create_activity_log_table(): void {
		global $wpdb;

		$table           = $wpdb->prefix . 'oxi_sm_activity_log';
		$charset_collate = $wpdb->get_charset_collate();

		$sql = "CREATE TABLE IF NOT EXISTS {$table} (
			id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
			user_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
			action VARCHAR(100) NOT NULL DEFAULT '',
			details LONGTEXT NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			KEY user_id (user_id),
			KEY created_at (created_at)
		) {$charset_collate};";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $sql );
	}

	public static function log_activity( int $user_id, string $action, array $details = [] ): void {
		global $wpdb;

		$wpdb->insert(
			$wpdb->prefix . 'oxi_sm_activity_log',
			[
				'user_id'    => $user_id,
				'action'     => sanitize_text_field( $action ),
				'details'    => wp_json_encode( $details ),
				'created_at' => current_time( 'mysql' ),
			],
			[ '%d', '%s', '%s', '%s' ]
		);
	}

	/**
	 * Prune log entries older than the configured retention days.
	 */
	public static function prune_old_logs(): void {
		global $wpdb;

		$settings       = get_option( 'wpkin_sm_admin_settings', [] );
		$retention_days = (int) ( $settings['employee_management']['log_retention_days'] ?? 30 );

		$wpdb->query(
			$wpdb->prepare(
				"DELETE FROM {$wpdb->prefix}oxi_sm_activity_log WHERE created_at < DATE_SUB(NOW(), INTERVAL %d DAY)",
				$retention_days
			)
		);
	}

	public static function redirect_oxi_users_from_admin(): void {
		if ( ! is_admin() || defined( 'DOING_AJAX' ) ) {
			return;
		}

		$user = wp_get_current_user();

		// Use get_oxi_roles() so custom roles are also blocked from wp-admin.
		if ( ! empty( array_intersect( self::get_oxi_roles(), (array) $user->roles ) ) ) {
			wp_safe_redirect( home_url( '/sm-dashboard/' ) );
			exit;
		}
	}

	/**
	 * Dynamically grant WooCommerce / WP core capabilities to oxi_sm employees
	 * based on their oxi_sm_* caps. This lets WooCommerce REST API calls
	 * (e.g. /wc/v3/products/attributes, /wc/v3/products/shipping_classes)
	 * succeed without storing broad WC caps in the role definition.
	 */
	public static function map_oxi_to_wc_caps( array $allcaps, array $_caps, array $_args, \WP_User $user ): array {
		// Only apply to oxi_sm employees.
		if ( empty( array_intersect( self::get_oxi_roles(), (array) $user->roles ) ) ) {
			return $allcaps;
		}

		// ── Products ─────────────────────────────────────────────────────────
		if ( ! empty( $allcaps['oxi_sm_products_access'] ) || ! empty( $allcaps['oxi_sm_view_products'] ) ) {
			$allcaps['read_private_products'] = true;
			$allcaps['edit_products']         = true;
		}
		if ( ! empty( $allcaps['oxi_sm_create_products'] ) ) {
			$allcaps['publish_products'] = true;
			$allcaps['edit_products']    = true;
		}
		if ( ! empty( $allcaps['oxi_sm_edit_products'] ) ) {
			$allcaps['edit_products']           = true;
			$allcaps['edit_others_products']    = true;
			$allcaps['edit_published_products'] = true;
			$allcaps['edit_private_products']   = true;
		}
		if ( ! empty( $allcaps['oxi_sm_delete_products'] ) ) {
			$allcaps['delete_products']            = true;
			$allcaps['delete_others_products']     = true;
			$allcaps['delete_published_products']  = true;
			$allcaps['delete_private_products']    = true;
		}

		// ── Product taxonomies (categories / tags / brands / attributes) ──────
		$taxonomy_access = [
			'oxi_sm_categories_access', 'oxi_sm_tags_access',
			'oxi_sm_brands_access',     'oxi_sm_attributes_access',
			'oxi_sm_categories_view',   'oxi_sm_tags_view',
			'oxi_sm_brands_view',       'oxi_sm_attributes_view',
		];
		foreach ( $taxonomy_access as $tc ) {
			if ( ! empty( $allcaps[ $tc ] ) ) {
				$allcaps['manage_product_terms'] = true;
				$allcaps['edit_product_terms']   = true;
				$allcaps['delete_product_terms'] = true;
				$allcaps['assign_product_terms'] = true;
				break;
			}
		}
		// AddProduct form needs taxonomy caps to load categories/attributes.
		if ( ! empty( $allcaps['oxi_sm_products_access'] ) ) {
			$allcaps['manage_product_terms'] = true;
			$allcaps['edit_product_terms']   = true;
			$allcaps['assign_product_terms'] = true;
		}

		// ── manage_woocommerce — needed for shipping_classes & tax classes ────
		// Scope strictly to employees who have product-level access so that
		// the privilege surface stays as small as possible. WP admin is already
		// blocked for all oxi_sm roles via redirect_oxi_users_from_admin().
		if ( ! empty( $allcaps['oxi_sm_products_access'] ) ||
		     ! empty( $allcaps['oxi_sm_create_products'] ) ||
		     ! empty( $allcaps['oxi_sm_edit_products'] ) ) {
			$allcaps['manage_woocommerce'] = true;
		}

		// ── Media library — wp_ajax_query-attachments & upload AJAX handlers ──
		// WP core checks upload_files before returning any media results.
		// Grant it for any employee who works with products or taxonomies so
		// the featured image / gallery / category thumbnail pickers work.
		if ( ! empty( $allcaps['oxi_sm_products_access'] ) ||
		     ! empty( $allcaps['oxi_sm_create_products'] ) ||
		     ! empty( $allcaps['oxi_sm_edit_products'] ) ||
		     ! empty( $allcaps['oxi_sm_categories_access'] ) ||
		     ! empty( $allcaps['oxi_sm_tags_access'] ) ||
		     ! empty( $allcaps['oxi_sm_brands_access'] ) ||
		     ! empty( $allcaps['oxi_sm_attributes_access'] ) ) {
			$allcaps['upload_files'] = true;
		}

		// ── Orders ───────────────────────────────────────────────────────────
		if ( ! empty( $allcaps['oxi_sm_orders_access'] ) || ! empty( $allcaps['oxi_sm_view_orders'] ) ) {
			$allcaps['read_private_shop_orders'] = true;
		}
		if ( ! empty( $allcaps['oxi_sm_create_orders'] ) ) {
			$allcaps['publish_shop_orders'] = true;
			$allcaps['edit_shop_orders']    = true;
		}
		// edit_shop_orders is required for status change, edit, and restore actions.
		if ( ! empty( $allcaps['oxi_sm_edit_orders'] ) ||
		     ! empty( $allcaps['oxi_sm_orders_status_change'] ) ||
		     ! empty( $allcaps['oxi_sm_orders_restore'] ) ) {
			$allcaps['edit_shop_orders']              = true;
			$allcaps['edit_others_shop_orders']       = true;
			$allcaps['edit_published_shop_orders']    = true;
		}
		if ( ! empty( $allcaps['oxi_sm_orders_trash'] ) || ! empty( $allcaps['oxi_sm_delete_orders'] ) ) {
			$allcaps['delete_shop_orders']            = true;
			$allcaps['delete_others_shop_orders']     = true;
			$allcaps['delete_published_shop_orders']  = true;
			$allcaps['delete_private_shop_orders']    = true;
		}

		return $allcaps;
	}

	public static function log_order_status_change( int $order_id, string $old_status, string $new_status ): void {
		$user = wp_get_current_user();

		if ( empty( array_intersect( self::get_oxi_roles(), (array) $user->roles ) ) ) {
			return;
		}

		self::log_activity( $user->ID, 'order_status_changed', [
			'order_id'   => $order_id,
			'old_status' => $old_status,
			'new_status' => $new_status,
		] );
	}

	public static function log_product_edit( int $product_id, \WC_Product $product ): void {
		$user = wp_get_current_user();

		if ( empty( array_intersect( self::get_oxi_roles(), (array) $user->roles ) ) ) {
			return;
		}

		self::log_activity( $user->ID, 'product_edited', [
			'product_id'   => $product_id,
			'product_name' => $product->get_name(),
		] );
	}

	public static function log_customer_update( int $user_id ): void {
		$user = wp_get_current_user();

		if ( empty( array_intersect( self::get_oxi_roles(), (array) $user->roles ) ) ) {
			return;
		}

		self::log_activity( $user->ID, 'customer_updated', [
			'customer_id' => $user_id,
		] );
	}

	public static function get_oxi_roles(): array {
		$settings = get_option( 'wpkin_sm_admin_settings', [] );
		$custom   = $settings['employee_management']['custom_roles'] ?? [];
		return array_merge( self::$oxi_roles, array_column( $custom, 'key' ) );
	}

	public static function get_active_oxi_roles(): array {
		$settings    = get_option( 'wpkin_sm_admin_settings', [] );
		$custom      = $settings['employee_management']['custom_roles'] ?? [];
		$custom_keys = wpkin_sm_v()->can_use_premium_code() ? array_column( $custom, 'key' ) : [];
		return array_merge( self::$oxi_roles, $custom_keys );
	}

	public static function get_role_labels(): array {
		$labels = [
			'oxi_sm_fulfillment'     => 'SM: Fulfillment Staff',
			'oxi_sm_product_manager' => 'SM: Product Manager',
			'oxi_sm_accountant'      => 'SM: Accountant',
			'oxi_sm_manager'         => 'SM: Store Manager',
		];
		$settings = get_option( 'wpkin_sm_admin_settings', [] );
		$custom   = $settings['employee_management']['custom_roles'] ?? [];
		foreach ( $custom as $role ) {
			$labels[ $role['key'] ] = $role['name'];
		}
		return $labels;
	}

	public static function get_all_oxi_cap_keys(): array {
		global $wp_roles;
		$keys = [];
		foreach ( $wp_roles->roles as $role_data ) {
			foreach ( array_keys( $role_data['capabilities'] ?? [] ) as $cap ) {
				if ( strpos( $cap, 'oxi_sm_' ) === 0 ) {
					$keys[] = $cap;
				}
			}
		}
		return array_values( array_unique( $keys ) );
	}

	public static function get_user_oxi_permissions( \WP_User $user ): array {
		$all_caps    = self::get_all_oxi_cap_keys();
		$is_employee = ! empty( array_intersect( self::get_oxi_roles(), (array) $user->roles ) );

		$permissions = [];
		foreach ( $all_caps as $cap ) {
			$permissions[ $cap ] = $is_employee ? ! empty( $user->allcaps[ $cap ] ) : true;
		}
		return $permissions;
	}

	public static function is_employee_role( string $role ): bool {
		return in_array( $role, self::$oxi_roles, true );
	}
}
