<?php
/**
 * QR Generator admin page.
 *
 * @package GoValid_QR
 */

defined( 'ABSPATH' ) || exit;

class GoValid_Admin_Generator {

	/**
	 * Register hooks.
	 */
	public function register(): void {
		add_action( 'admin_post_govalid_qr_create', array( $this, 'handle_create' ) );
	}

	/**
	 * Handle QR code creation.
	 */
	public function handle_create(): void {
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_die( esc_html__( 'Unauthorized.', 'govalid-qr-validator' ) );
		}
		check_admin_referer( 'govalid_qr_create' );

		// Enforce QR generation limit for free users.
		$limit_error = $this->check_qr_limit();
		if ( is_wp_error( $limit_error ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url(
				'admin.php?page=govalid-qr-generator&error=' . rawurlencode( $limit_error->get_error_message() )
			) ) );
			exit;
		}

		$type = isset( $_POST['qr_type'] ) ? sanitize_text_field( wp_unslash( $_POST['qr_type'] ) ) : 'url';
		$name = isset( $_POST['qr_name'] ) ? sanitize_text_field( wp_unslash( $_POST['qr_name'] ) ) : '';

		if ( empty( $name ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr-generator&error=missing_fields' ) ) );
			exit;
		}

		$security_level = isset( $_POST['security_level'] ) ? sanitize_text_field( wp_unslash( $_POST['security_level'] ) ) : 'SMART';

		$data = array(
			'security_level' => $security_level,
		);

		if ( 'certificate' === $type ) {
			$data['metadata'] = $this->collect_certificate_metadata();

			// Validate bulk name/identifier counts.
			// Valid: equal counts, or exactly 1 identifier for multiple names.
			if ( ! empty( $data['metadata']['name'] ) && ! empty( $data['metadata']['identifier'] ) ) {
				$names       = array_filter( preg_split( '/[\n;]+/', $data['metadata']['name'] ), 'strlen' );
				$identifiers = array_filter( preg_split( '/[\n;]+/', $data['metadata']['identifier'] ), 'strlen' );
				$id_count    = count( $identifiers );
				if ( $id_count > 0 && $id_count !== count( $names ) && $id_count !== 1 ) {
					wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr-generator&error=' . rawurlencode(
						sprintf(
							/* translators: 1: name count, 2: identifier count */
							__( 'Bulk mismatch: %1$d name(s) and %2$d identifier(s). Counts must match, or use a single identifier for all names.', 'govalid-qr-validator' ),
							count( $names ),
							$id_count
						)
					) ) ) );
					exit;
				}
			}
		}

		if ( 'timeline' === $type ) {
			$data['metadata'] = $this->collect_timeline_metadata();
		}

		if ( 'goods' === $type ) {
			$data['metadata'] = $this->collect_goods_metadata();
		}

		if ( 'document' === $type ) {
			$data['metadata'] = $this->collect_document_metadata();
		}

		// Handle file attachment upload (certificate, goods, or document).
		$upload_field = '';
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Checking tmp_name existence only.
		if ( ! empty( $_FILES['field_upload_certificate']['tmp_name'] ) ) {
			$upload_field = 'field_upload_certificate';
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		} elseif ( ! empty( $_FILES['field_upload_goods']['tmp_name'] ) ) {
			$upload_field = 'field_upload_goods';
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		} elseif ( ! empty( $_FILES['field_upload_document']['tmp_name'] ) ) {
			$upload_field = 'field_upload_document';
		}
		if ( $upload_field && isset( $_FILES[ $upload_field ] ) ) {
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- File validated by type and size below.
			$file    = $_FILES[ $upload_field ];
			$allowed = array( 'image/jpeg', 'image/png', 'application/pdf' );
			if ( in_array( $file['type'], $allowed, true ) && $file['size'] <= 5 * MB_IN_BYTES ) {
				$data['attachment_path'] = $file['tmp_name'];
				$data['attachment_name'] = sanitize_file_name( $file['name'] );
			}
		}

		// Handle timeline entry media uploads.
		if ( 'timeline' === $type ) {
			$allowed = array( 'image/jpeg', 'image/png', 'application/pdf' );
			$entry_count = isset( $data['metadata']['timeline_entries'] ) ? count( $data['metadata']['timeline_entries'] ) : 0;
			for ( $i = 0; $i < $entry_count; $i++ ) {
				$file_key = 'timeline_entries_media_' . $i;
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Checking tmp_name existence only.
				if ( ! empty( $_FILES[ $file_key ]['tmp_name'] ) ) {
					// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- File validated by type and size below.
					$file = $_FILES[ $file_key ];
					if ( in_array( $file['type'], $allowed, true ) && $file['size'] <= 5 * MB_IN_BYTES ) {
						$data['metadata']['timeline_entries'][ $i ]['media_path'] = $file['tmp_name'];
						$data['metadata']['timeline_entries'][ $i ]['media_name'] = sanitize_file_name( $file['name'] );
					}
				}
			}
		}

		$api = new GoValid_QR_API();

		// ── Build bulk iterations ────────────────────────────────
		// Each iteration is an array: array( 'name' => ..., 'identifier' => ... ).
		$iterations = array();

		if ( 'certificate' === $type ) {
			// Certificate bulk: driven by names, identifiers paired.
			$names = ! empty( $data['metadata']['name'] )
				? array_values( array_filter( array_map( 'trim', preg_split( '/[\n;]+/', $data['metadata']['name'] ) ), 'strlen' ) )
				: array();
			$ids = ! empty( $data['metadata']['identifier'] )
				? array_values( array_filter( array_map( 'trim', preg_split( '/[\n;]+/', $data['metadata']['identifier'] ) ), 'strlen' ) )
				: array();

			if ( count( $names ) > 1 ) {
				foreach ( $names as $i => $single_name ) {
					$iterations[] = array(
						'name'       => $single_name,
						'identifier' => count( $ids ) === 1 ? $ids[0] : ( isset( $ids[ $i ] ) ? $ids[ $i ] : '' ),
					);
				}
			}
		} elseif ( 'timeline' === $type || 'goods' === $type || 'document' === $type ) {
			// Timeline, goods & document bulk: driven by identifiers.
			$ids = ! empty( $data['metadata']['identifier'] )
				? array_values( array_filter( array_map( 'trim', preg_split( '/[\n;]+/', $data['metadata']['identifier'] ) ), 'strlen' ) )
				: array();

			if ( count( $ids ) > 1 ) {
				foreach ( $ids as $single_id ) {
					$iterations[] = array(
						'identifier' => $single_id,
					);
				}
			}
		}

		$is_bulk = count( $iterations ) > 1;

		if ( $is_bulk ) {
			// Bulk generation: one API call per iteration.
			$created = 0;
			$errors  = array();

			foreach ( $iterations as $idx => $iter ) {
				$iter_data = $data;

				if ( 'certificate' === $type ) {
					$iter_data['metadata']['name']       = $iter['name'];
					$iter_data['metadata']['identifier'] = $iter['identifier'];
				} elseif ( 'timeline' === $type || 'goods' === $type || 'document' === $type ) {
					$iter_data['metadata']['identifier'] = $iter['identifier'];
				}

				$iter_name = $name;

				$result = $api->create_qr_code( $type, $iter_name, $iter_data );

				if ( is_wp_error( $result ) ) {
					$label = ! empty( $iter['name'] ) ? $iter['name'] : ( ! empty( $iter['identifier'] ) ? $iter['identifier'] : '#' . ( $idx + 1 ) );
					$errors[] = sprintf( '%1$s: %2$s', $label, $result->get_error_message() );
				} else {
					$created++;
				}
			}

			// Flush QR list cache.
			GoValid_Cache::get_instance()->flush_prefix( 'qr_list_' );

			if ( $created > 0 ) {
				$redirect = admin_url( 'admin.php?page=govalid-qr-list&bulk_created=' . intval( $created ) );
		$redirect = add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), $redirect );
				if ( ! empty( $errors ) ) {
					$redirect .= '&bulk_errors=' . rawurlencode( implode( ' | ', $errors ) );
				}
				wp_safe_redirect( $redirect );
			} else {
				wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url(
					'admin.php?page=govalid-qr-generator&error=' . rawurlencode(
						__( 'Bulk generation failed: ', 'govalid-qr-validator' ) . implode( ' | ', $errors )
					)
				) ) );
			}
			exit;
		}

		// Single QR generation (one name/identifier or none).
		$result = $api->create_qr_code( $type, $name, $data );

		if ( is_wp_error( $result ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url(
				'admin.php?page=govalid-qr-generator&error=' . rawurlencode( $result->get_error_message() )
			) ) );
			exit;
		}

		// Flush QR list cache.
		GoValid_Cache::get_instance()->flush_prefix( 'qr_list_' );

		$uuid = isset( $result['uuid'] ) ? sanitize_text_field( $result['uuid'] ) : '';
		wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr-list&created=' . rawurlencode( $uuid ) ) ) );
		exit;
	}

	/**
	 * Collect certificate-specific metadata from POST data.
	 *
	 * @return array
	 */
	private function collect_certificate_metadata(): array {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_create().
		$metadata = array();

		// Verification-page priority order:
		// identifier → name → created_date → expire_date → purpose → description → sign_by.
		// Identifier and name first (bulk fields, use sanitize_textarea_field).
		if ( ! empty( $_POST['field_identifier'] ) ) {
			$metadata['identifier'] = sanitize_textarea_field( wp_unslash( $_POST['field_identifier'] ) );
		}
		if ( ! empty( $_POST['field_name'] ) ) {
			$metadata['name'] = sanitize_textarea_field( wp_unslash( $_POST['field_name'] ) );
		}

		// Then remaining priority fields in display order.
		$field_map = array(
			'field_generated_by' => 'generated_by',
			'field_created_date' => 'created_date',
			'field_expire_date'  => 'expire_date',
			'field_purpose'      => 'purpose_title',
			'field_description'  => 'description',
		);

		foreach ( $field_map as $post_key => $meta_key ) {
			if ( ! empty( $_POST[ $post_key ] ) ) {
				$metadata[ $meta_key ] = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
			}
		}

		// Signed by.
		if ( ! empty( $_POST['field_sign_by'] ) ) {
			$metadata['sign_by'] = sanitize_text_field( wp_unslash( $_POST['field_sign_by'] ) );
		}

		if ( ! empty( $_POST['mask_identifier'] ) ) {
			$metadata['mask_identifier'] = true;
		}
		if ( ! empty( $_POST['mask_name'] ) ) {
			$metadata['mask_name'] = true;
		}
		if ( ! empty( $_POST['anti_counterfeit_tags'] ) ) {
			$metadata['anti_counterfeit_tags'] = sanitize_text_field( wp_unslash( $_POST['anti_counterfeit_tags'] ) );
		}
		if ( ! empty( $_POST['pin_verified'] ) && 'true' === $_POST['pin_verified'] ) {
			$metadata['pin_verified'] = true;
		}

		// Password protection.
		if ( ! empty( $_POST['is_password_protected'] ) && 'true' === $_POST['is_password_protected'] ) {
			$metadata['is_password_protected'] = true;
			$password_type = isset( $_POST['password_type'] ) ? sanitize_text_field( wp_unslash( $_POST['password_type'] ) ) : 'master';
			$metadata['password_type'] = $password_type;
			if ( 'unique' === $password_type && ! empty( $_POST['field_password'] ) ) {
				$metadata['password'] = sanitize_text_field( wp_unslash( $_POST['field_password'] ) );
			}
		}

		// Removal / invalidation date.
		if ( ! empty( $_POST['combined_removal_datetime'] ) ) {
			$metadata['removal_datetime'] = sanitize_text_field( wp_unslash( $_POST['combined_removal_datetime'] ) );
			$metadata['removal_type'] = isset( $_POST['field_removal_type'] ) ? sanitize_text_field( wp_unslash( $_POST['field_removal_type'] ) ) : 'removal';
		}

		// phpcs:enable WordPress.Security.NonceVerification.Missing
		return $metadata;
	}

	/**
	 * Collect timeline-specific metadata from POST data.
	 *
	 * @return array
	 */
	private function collect_timeline_metadata(): array {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_create().
		$metadata = array();

		// Verification-page display order:
		// identifier → purpose → product → brand.
		// Identifier first (bulk field, uses sanitize_textarea_field).
		if ( ! empty( $_POST['field_identifier'] ) ) {
			$metadata['identifier'] = sanitize_textarea_field( wp_unslash( $_POST['field_identifier'] ) );
		}

		if ( ! empty( $_POST['mask_identifier'] ) ) {
			$metadata['mask_identifier'] = true;
		}

		// Remaining fields in display order.
		$field_map = array(
			'field_generated_by' => 'generated_by',
			'field_purpose'      => 'purpose_title',
			'field_product'      => 'product',
			'field_brand'        => 'brand',
		);

		foreach ( $field_map as $post_key => $meta_key ) {
			if ( ! empty( $_POST[ $post_key ] ) ) {
				$metadata[ $meta_key ] = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
			}
		}
		if ( ! empty( $_POST['anti_counterfeit_tags'] ) ) {
			$metadata['anti_counterfeit_tags'] = sanitize_text_field( wp_unslash( $_POST['anti_counterfeit_tags'] ) );
		}

		// Password protection.
		if ( ! empty( $_POST['is_password_protected'] ) && 'true' === $_POST['is_password_protected'] ) {
			$metadata['is_password_protected'] = true;
			$password_type = isset( $_POST['password_type'] ) ? sanitize_text_field( wp_unslash( $_POST['password_type'] ) ) : 'master';
			$metadata['password_type'] = $password_type;
			if ( 'unique' === $password_type && ! empty( $_POST['field_password'] ) ) {
				$metadata['password'] = sanitize_text_field( wp_unslash( $_POST['field_password'] ) );
			}
		}

		// Removal / invalidation date.
		if ( ! empty( $_POST['combined_removal_datetime'] ) ) {
			$metadata['removal_datetime'] = sanitize_text_field( wp_unslash( $_POST['combined_removal_datetime'] ) );
			$metadata['removal_type'] = isset( $_POST['field_removal_type'] ) ? sanitize_text_field( wp_unslash( $_POST['field_removal_type'] ) ) : 'removal';
		}

		// Timeline entries.
		if ( ! empty( $_POST['timeline_entries'] ) && is_array( $_POST['timeline_entries'] ) ) {
			$entries = array();
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized below per field.
			foreach ( wp_unslash( $_POST['timeline_entries'] ) as $raw_entry ) {
				$entry = array();

				if ( ! empty( $raw_entry['create_date'] ) ) {
					$entry['create_date'] = sanitize_text_field( $raw_entry['create_date'] );
				}
				if ( ! empty( $raw_entry['description'] ) ) {
					$entry['description'] = sanitize_textarea_field( $raw_entry['description'] );
				}
				if ( ! empty( $raw_entry['map_lat'] ) ) {
					$entry['map_lat'] = sanitize_text_field( $raw_entry['map_lat'] );
				}
				if ( ! empty( $raw_entry['map_lng'] ) ) {
					$entry['map_lng'] = sanitize_text_field( $raw_entry['map_lng'] );
				}
				if ( ! empty( $raw_entry['map_address'] ) ) {
					$entry['map_address'] = sanitize_text_field( $raw_entry['map_address'] );
				}

				$entries[] = $entry;
			}
			$metadata['timeline_entries'] = $entries;
		}

		// phpcs:enable WordPress.Security.NonceVerification.Missing
		return $metadata;
	}

	/**
	 * Collect goods (product)-specific metadata from POST data.
	 *
	 * @return array
	 */
	private function collect_goods_metadata(): array {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_create().
		$metadata = array();

		// Identifier first — uses sanitize_textarea_field to preserve newlines for bulk support.
		if ( ! empty( $_POST['field_identifier'] ) ) {
			$metadata['identifier'] = sanitize_textarea_field( wp_unslash( $_POST['field_identifier'] ) );
		}

		if ( ! empty( $_POST['mask_identifier'] ) ) {
			$metadata['mask_identifier'] = true;
		}

		// Remaining fields in verification-page display order:
		// identifier → generated_by → owned_by → production_date → expire_date → description.
		$field_map = array(
			'field_generated_by'    => 'generated_by',
			'field_owned_by'        => 'owned_by',
			'field_production_date' => 'production_date',
			'field_expire_date'     => 'expire_date',
			'field_description'     => 'description',
		);

		foreach ( $field_map as $post_key => $meta_key ) {
			if ( ! empty( $_POST[ $post_key ] ) ) {
				$metadata[ $meta_key ] = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
			}
		}
		if ( ! empty( $_POST['anti_counterfeit_tags'] ) ) {
			$metadata['anti_counterfeit_tags'] = sanitize_text_field( wp_unslash( $_POST['anti_counterfeit_tags'] ) );
		}

		// Password protection.
		if ( ! empty( $_POST['is_password_protected'] ) && 'true' === $_POST['is_password_protected'] ) {
			$metadata['is_password_protected'] = true;
			$password_type = isset( $_POST['password_type'] ) ? sanitize_text_field( wp_unslash( $_POST['password_type'] ) ) : 'master';
			$metadata['password_type'] = $password_type;
			if ( 'unique' === $password_type && ! empty( $_POST['field_password'] ) ) {
				$metadata['password'] = sanitize_text_field( wp_unslash( $_POST['field_password'] ) );
			}
		}

		// Removal / invalidation date.
		if ( ! empty( $_POST['combined_removal_datetime'] ) ) {
			$metadata['removal_datetime'] = sanitize_text_field( wp_unslash( $_POST['combined_removal_datetime'] ) );
			$metadata['removal_type'] = isset( $_POST['field_removal_type'] ) ? sanitize_text_field( wp_unslash( $_POST['field_removal_type'] ) ) : 'removal';
		}

		// phpcs:enable WordPress.Security.NonceVerification.Missing
		return $metadata;
	}

	/**
	 * Collect document-specific metadata from POST data.
	 *
	 * @return array
	 */
	private function collect_document_metadata(): array {
		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_create().
		$metadata = array();

		// Verification-page priority order:
		// identifier → created_date → expire_date → purpose → description.
		// Identifier first (bulk field, uses sanitize_textarea_field).
		if ( ! empty( $_POST['field_identifier'] ) ) {
			$metadata['identifier'] = sanitize_textarea_field( wp_unslash( $_POST['field_identifier'] ) );
		}

		if ( ! empty( $_POST['mask_identifier'] ) ) {
			$metadata['mask_identifier'] = true;
		}

		// Remaining fields in display order.
		$field_map = array(
			'field_generated_by' => 'generated_by',
			'field_created_date' => 'created_date',
			'field_expire_date'  => 'expire_date',
			'field_purpose'      => 'purpose_title',
			'field_description'  => 'description',
		);

		foreach ( $field_map as $post_key => $meta_key ) {
			if ( ! empty( $_POST[ $post_key ] ) ) {
				$metadata[ $meta_key ] = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
			}
		}
		if ( ! empty( $_POST['anti_counterfeit_tags'] ) ) {
			$metadata['anti_counterfeit_tags'] = sanitize_text_field( wp_unslash( $_POST['anti_counterfeit_tags'] ) );
		}

		// Password protection.
		if ( ! empty( $_POST['is_password_protected'] ) && 'true' === $_POST['is_password_protected'] ) {
			$metadata['is_password_protected'] = true;
			$password_type = isset( $_POST['password_type'] ) ? sanitize_text_field( wp_unslash( $_POST['password_type'] ) ) : 'master';
			$metadata['password_type'] = $password_type;
			if ( 'unique' === $password_type && ! empty( $_POST['field_password'] ) ) {
				$metadata['password'] = sanitize_text_field( wp_unslash( $_POST['field_password'] ) );
			}
		}

		// Removal / invalidation date.
		if ( ! empty( $_POST['combined_removal_datetime'] ) ) {
			$metadata['removal_datetime'] = sanitize_text_field( wp_unslash( $_POST['combined_removal_datetime'] ) );
			$metadata['removal_type'] = isset( $_POST['field_removal_type'] ) ? sanitize_text_field( wp_unslash( $_POST['field_removal_type'] ) ) : 'removal';
		}

		// phpcs:enable WordPress.Security.NonceVerification.Missing
		return $metadata;
	}

	/**
	 * Check if QR generation limit is reached for free users.
	 *
	 * Free users can generate up to 5 QR codes.
	 *
	 * @return true|WP_Error True if allowed, WP_Error if limit reached.
	 */
	private function check_qr_limit() {
		if ( ! GoValid_QR::is_connected() ) {
			return true; // Allow unconnected users (backend will enforce its own limits).
		}

		$api    = new GoValid_QR_API();
		$result = $api->get_subscription();

		$has_subscription = false;
		if ( ! is_wp_error( $result ) ) {
			$data = $result['data'] ?? $result;
			$sub  = $data['subscription'] ?? array();
			$plan = $sub['plan'] ?? array();
			$tier = $plan['tier'] ?? 'FREE';

			$has_subscription = ( 'FREE' !== $tier );
		}

		if ( ! $has_subscription ) {
			// Count existing QR codes from the API.
			$qr_result = $api->list_qr_codes( 1, 1 );

			$qr_count = 0;
			if ( ! is_wp_error( $qr_result ) ) {
				$qr_data  = $qr_result['data'] ?? $qr_result;
				$pagination = $qr_data['pagination'] ?? array();
				$qr_count = (int) ( $pagination['total'] ?? 0 );
			}

			if ( $qr_count >= 5 ) {
				return new WP_Error(
					'qr_limit_reached',
					__( 'Free accounts can generate up to 5 QR codes. Upgrade your subscription to generate more.', 'govalid-qr-validator' )
				);
			}
		}

		return true;
	}
}
