<?php
/**
 * CSV export for alt text reports.
 *
 * @package AIAltTextGenerator
 * @since 1.5.0
 */

namespace AIAltTextGenerator;

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

/**
 * @since 1.5.0
 */
class Exporter {

	/**
	 * Stream a CSV report and exit.
	 */
	public static function download( string $type = 'missing' ): void {
		if ( ! Capabilities::canView() ) {
			wp_die( esc_html__( 'Permission denied.', 'wp-powersuite' ) );
		}

		$type = sanitize_key( $type );
		$rows = self::buildRows( $type );

		$filename = 'ai-alt-text-' . $type . '-' . gmdate( 'Y-m-d' ) . '.csv';

		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename=' . $filename );

		$out = fopen( 'php://output', 'w' );
		if ( $out === false ) {
			wp_die( esc_html__( 'Could not create export.', 'wp-powersuite' ) );
		}

		fputcsv(
			$out,
			[
				'attachment_id',
				'filename',
				'url',
				'current_alt',
				'suggestion',
				'status',
				'quality',
				'generated_at',
			]
		);

		foreach ( $rows as $row ) {
			fputcsv( $out, $row );
		}

		fclose( $out );
		exit;
	}

	/**
	 * Build CSV content for CLI or programmatic export.
	 */
	public static function toCsvString( string $type = 'missing' ): string {
		$type = sanitize_key( $type );
		$rows = self::buildRows( $type );

		$handle = fopen( 'php://temp', 'r+' );
		if ( $handle === false ) {
			return '';
		}

		fputcsv(
			$handle,
			[
				'attachment_id',
				'filename',
				'url',
				'current_alt',
				'suggestion',
				'status',
				'quality',
				'generated_at',
			]
		);

		foreach ( $rows as $row ) {
			fputcsv( $handle, $row );
		}

		rewind( $handle );
		$csv = stream_get_contents( $handle );
		fclose( $handle );

		return is_string( $csv ) ? $csv : '';
	}

	/**
	 * @return list<array<int|string>>
	 */
	private static function buildRows( string $type ): array {
		if ( $type === 'weak' ) {
			return self::buildWeakRows();
		}

		if ( $type === 'duplicates' ) {
			$rows = [];
			foreach ( DuplicateDetector::getDuplicateAttachmentIds() as $attachment_id ) {
				$rows[] = self::rowForAttachment( (int) $attachment_id );
			}
			return $rows;
		}

		$ids = match ( $type ) {
			'missing' => Scanner::getMissingIds( 5000, 0 ),
			'pending' => Scanner::getPendingReviewIds( 5000, 0 ),
			'all'     => self::getAllSupportedIds(),
			default   => Scanner::getMissingIds( 5000, 0 ),
		};

		$rows = [];
		foreach ( $ids as $attachment_id ) {
			$rows[] = self::rowForAttachment( (int) $attachment_id );
		}

		return $rows;
	}

	/** @return list<array<int|string>> */
	private static function buildWeakRows(): array {
		$rows = [];
		foreach ( self::getAllSupportedIds() as $attachment_id ) {
			$status = AttachmentStatus::resolve( (int) $attachment_id );
			if ( ! in_array( $status['slug'], [ 'weak', 'too_short', 'keyword_stuffed' ], true ) ) {
				continue;
			}
			$rows[] = self::rowForAttachment( (int) $attachment_id );
		}

		return $rows;
	}

	/** @return array<int|string> */
	private static function rowForAttachment( int $attachment_id ): array {
		$file       = get_attached_file( $attachment_id );
		$alt        = (string) get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
		$suggestion = AttachmentMeta::getSuggestion( $attachment_id );
		$status     = AttachmentStatus::resolve( $attachment_id );

		return [
			$attachment_id,
			$file ? basename( $file ) : '',
			wp_get_attachment_url( $attachment_id ) ?: '',
			$alt,
			$suggestion,
			AttachmentMeta::getStatus( $attachment_id ),
			$status['label'],
			(string) get_post_meta( $attachment_id, AttachmentMeta::META_GENERATED_AT, true ),
		];
	}

	/** @return list<int> */
	private static function getAllSupportedIds(): array {
		global $wpdb;

		$mimes      = AltTextGenerator::getSupportedMimes();
		$mime_place = implode( ',', array_fill( 0, count( $mimes ), '%s' ) );
		$args       = array_merge( [ 'attachment', 'inherit' ], $mimes );

		$ids = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT ID FROM {$wpdb->posts}
				WHERE post_type = %s AND post_status = %s
				AND post_mime_type IN ($mime_place)
				ORDER BY ID ASC
				LIMIT 5000",
				...$args
			)
		);

		return array_map( 'intval', $ids ?: [] );
	}
}
