<?php
/**
 * CSV report exporter.
 *
 * @package CertaCart_EU_Product_Readiness
 */

namespace CertaCart\EU_Product_Readiness;

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

final class Exporter {
	public static function handle(): void {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to export this report.', 'certacart-eu-product-readiness' ) );
		}
		check_admin_referer( 'ccpr_export_scan' );
		$scan_id = isset( $_GET['scan_id'] ) ? absint( wp_unslash( $_GET['scan_id'] ) ) : 0;
		$repo    = new Scan_Repository();
		$scan = $scan_id ? $repo->get( $scan_id ) : null;
		if ( ! $scan ) {
			wp_die( esc_html__( 'Scan not found.', 'certacart-eu-product-readiness' ) );
		}
		$score_available = Scanner::is_score_available( $scan );

		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename=certacart-scan-' . $scan_id . '-' . gmdate( 'Y-m-d' ) . '.csv' );
		$out = fopen( 'php://output', 'w' );
		if ( false === $out ) {
			wp_die( esc_html__( 'Unable to open export stream.', 'certacart-eu-product-readiness' ) );
		}
		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite -- The response is streamed directly to php://output; WP_Filesystem cannot write an HTTP response stream.
		fwrite( $out, "\xEF\xBB\xBF" );
		fputcsv( $out, array( 'product_id', 'product_name', 'product_url', 'scope', 'score', 'critical', 'warnings', 'information', 'finding_rules', 'finding_messages' ), ',', '"', '' );

		$page = 1;
		do {
			$rows = $repo->results( $scan_id, array( 'page' => $page, 'per_page' => 200 ) );
			foreach ( $rows as $row ) {
				$findings = json_decode( (string) $row['findings_json'], true );
				$rules    = array();
				$messages = array();
				foreach ( is_array( $findings ) ? $findings : array() as $finding ) {
					$rules[]    = sanitize_key( (string) ( $finding['rule'] ?? '' ) );
					$messages[] = sanitize_text_field( (string) ( $finding['message'] ?? '' ) );
				}
				fputcsv(
					$out,
					array_map(
						array( __CLASS__, 'csv_safe' ),
						array(
							(int) $row['product_id'],
							$row['post_title'],
							get_permalink( (int) $row['product_id'] ),
							! empty( $row['in_scope'] ) ? ( $score_available ? 'in_scope' : 'review' ) : 'out_of_scope',
							! empty( $row['in_scope'] ) && $score_available ? (float) $row['score'] : '',
							(int) $row['critical_count'],
							(int) $row['warning_count'],
							(int) $row['info_count'],
							implode( ' | ', $rules ),
							implode( ' | ', $messages ),
						)
					),
					',',
					'"',
					''
				);
			}
			++$page;
		} while ( count( $rows ) === 200 );

		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Close the php://output response stream opened above.
		fclose( $out );
		exit;
	}

	public static function csv_safe( $value ): string {
		$value = (string) $value;
		if ( preg_match( '/^[=+\-@]/', $value ) ) {
			return "'" . $value;
		}
		return $value;
	}
}
