<?php
/**
 * PA export package (ZIP + CSV manifest) and B2C e-reporting extract
 * (daily-aggregated per-VAT-rate, "ticket Z" model — NO transaction count,
 * removed from the spec Sept 2025) with a regime-aware transmission calendar.
 *
 * @package FEPW
 */

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

/**
 * Class FEPW_Export
 */
class FEPW_Export {

	/**
	 * Singleton.
	 *
	 * @var FEPW_Export|null
	 */
	private static $instance = null;

	/**
	 * Instance.
	 *
	 * @return FEPW_Export
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	private function __construct() {
		add_action( 'admin_post_fepw_export_zip', array( $this, 'handle_export_zip' ) );
		add_action( 'admin_post_fepw_ereporting_csv', array( $this, 'handle_ereporting_csv' ) );
	}

	/**
	 * Export ZIP: all documents of a period + CSV manifest — the package a
	 * merchant uploads to their Plateforme Agréée manually (free tier).
	 */
	public function handle_export_zip() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'buildsbyluke-facture-electronique-for-woocommerce' ) );
		}
		check_admin_referer( 'fepw_export' );

		$from = self::sanitize_date( isset( $_GET['from'] ) ? sanitize_text_field( wp_unslash( $_GET['from'] ) ) : '', wp_date( 'Y-m-01' ) );
		$to   = self::sanitize_date( isset( $_GET['to'] ) ? sanitize_text_field( wp_unslash( $_GET['to'] ) ) : '', wp_date( 'Y-m-d' ) );

		$docs = FEPW_Documents::get_documents( array( 'from' => $from, 'to' => $to ) );
		if ( empty( $docs ) ) {
			wp_die( esc_html__( 'No documents in this period. Generate invoices first.', 'buildsbyluke-facture-electronique-for-woocommerce' ) );
		}

		if ( ! class_exists( 'ZipArchive' ) ) {
			wp_die( esc_html__( 'The PHP zip extension is not available on this server.', 'buildsbyluke-facture-electronique-for-woocommerce' ) );
		}

		$tmp = wp_tempnam( 'fepw-export' );
		$zip = new ZipArchive();
		$zip->open( $tmp, ZipArchive::OVERWRITE );

		$manifest   = array();
		$manifest[] = array( 'numero', 'type', 'date', 'commande', 'total_ht', 'total_tva', 'total_ttc', 'fichiers' );
		$dir        = FEPW_Documents::storage_dir();

		foreach ( $docs as $doc ) {
			$base  = sanitize_file_name( $doc['doc_number'] );
			$files = array();
			foreach ( array( '-facturx.pdf', '-cii.xml', '-ubl.xml', '.pdf' ) as $suffix ) {
				if ( file_exists( $dir . $base . $suffix ) ) {
					$zip->addFile( $dir . $base . $suffix, $base . $suffix );
					$files[] = $base . $suffix;
				}
			}
			$manifest[] = array(
				$doc['doc_number'],
				'credit_note' === $doc['doc_type'] ? 'avoir' : 'facture',
				$doc['issued_at'],
				$doc['order_id'],
				$doc['total_ht'],
				$doc['total_tva'],
				$doc['total_ttc'],
				implode( '|', $files ),
			);
		}

		$csv = fopen( 'php://temp', 'w+' ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- in-memory CSV assembly.
		foreach ( $manifest as $row ) {
			fputcsv( $csv, $row, ';' );
		}
		rewind( $csv );
		$zip->addFromString( 'manifest.csv', (string) stream_get_contents( $csv ) );
		fclose( $csv ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- paired with fopen above.
		$zip->close();

		nocache_headers();
		header( 'Content-Type: application/zip' );
		header( 'Content-Disposition: attachment; filename="fepw-export-' . $from . '-' . $to . '.zip"' );
		header( 'Content-Length: ' . (string) filesize( $tmp ) );
		readfile( $tmp ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- controlled download.
		unlink( $tmp ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- temp cleanup.
		exit;
	}

	/**
	 * B2C e-reporting extract: daily aggregated bases HT + VAT per rate, EUR.
	 * Covers completed/processing orders that are NOT B2B-with-SIREN (those go
	 * through e-invoicing instead).
	 *
	 * @param string $from Y-m-d.
	 * @param string $to   Y-m-d.
	 * @return array rows: date, rate, base_ht, tva.
	 */
	public static function build_ereporting( $from, $to ) {
		$days = array();
		$page = 1;
		do {
			// Paged iteration: month-sized periods on busy stores would exhaust
			// memory with limit -1.
			$orders = wc_get_orders(
				array(
					'status'       => array( 'completed', 'processing' ),
					'date_created' => $from . '...' . $to,
					'limit'        => 200,
					'paged'        => $page,
					'return'       => 'objects',
				)
			);
			foreach ( $orders as $order ) {
				$fields = FEPW_Checkout::get_order_fields( $order );
				if ( 'b2b' === $fields['type'] && '' !== $fields['siren'] ) {
					continue; // Domestic B2B goes through e-invoicing, not e-reporting.
				}
				$date = $order->get_date_created() ? $order->get_date_created()->date( 'Y-m-d' ) : $from;

				foreach ( $order->get_items( array( 'line_item', 'shipping', 'fee' ) ) as $item ) {
					$rate_pct = 0.0;
					$taxes    = $item->get_taxes();
					if ( ! empty( $taxes['total'] ) ) {
						foreach ( $taxes['total'] as $rate_id => $tax_amount ) {
							if ( '' === $tax_amount || null === $tax_amount ) {
								continue;
							}
							$rate_pct = (float) WC_Tax::get_rate_percent_value( $rate_id );
							break;
						}
					}
					$key = $date . '|' . number_format( $rate_pct, 2, '.', '' );
					if ( ! isset( $days[ $key ] ) ) {
						$days[ $key ] = array(
							'date' => $date,
							'rate' => $rate_pct,
							'base' => 0.0,
							'tva'  => 0.0,
						);
					}
					$days[ $key ]['base'] += (float) $item->get_total();
					$days[ $key ]['tva']  += (float) $item->get_total_tax();
				}
			}
			$page++;
		} while ( count( $orders ) === 200 );
		ksort( $days );
		return array_values( $days );
	}

	/**
	 * Validate a Y-m-d date string, falling back to a default.
	 *
	 * @param string $value    Candidate.
	 * @param string $fallback Default (already Y-m-d).
	 * @return string
	 */
	private static function sanitize_date( $value, $fallback ) {
		return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ? $value : $fallback;
	}

	/**
	 * Download the e-reporting extract CSV.
	 */
	public function handle_ereporting_csv() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'buildsbyluke-facture-electronique-for-woocommerce' ) );
		}
		check_admin_referer( 'fepw_ereporting' );

		$from = self::sanitize_date( isset( $_GET['from'] ) ? sanitize_text_field( wp_unslash( $_GET['from'] ) ) : '', wp_date( 'Y-m-01' ) );
		$to   = self::sanitize_date( isset( $_GET['to'] ) ? sanitize_text_field( wp_unslash( $_GET['to'] ) ) : '', wp_date( 'Y-m-d' ) );

		$rows = self::build_ereporting( $from, $to );

		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="fepw-ereporting-' . $from . '-' . $to . '.csv"' );
		$out = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- streamed CSV download.
		fputcsv( $out, array( 'date', 'taux_tva', 'base_ht_eur', 'montant_tva_eur' ), ';' );
		foreach ( $rows as $row ) {
			fputcsv( $out, array( $row['date'], number_format( $row['rate'], 2, '.', '' ), number_format( $row['base'], 2, '.', '' ), number_format( $row['tva'], 2, '.', '' ) ), ';' );
		}
		fclose( $out ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- paired with fopen above.
		exit;
	}

	/**
	 * Next e-reporting transmission dates for the configured VAT regime.
	 *
	 * @return array{label:string,dates:string[]}
	 */
	public static function calendar() {
		$settings = get_option( 'fepw_settings', array() );
		$regime   = isset( $settings['vat_regime'] ) ? $settings['vat_regime'] : 'reel_normal';
		$today    = current_time( 'timestamp' ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp -- site-local calendar math.

		$dates = array();
		if ( 'reel_normal' === $regime ) {
			$label = __( 'Réel normal: transmission every ~10 days (3× per month).', 'buildsbyluke-facture-electronique-for-woocommerce' );
			foreach ( array( 10, 20 ) as $dom ) {
				$t = mktime( 0, 0, 0, (int) wp_date( 'n' ), $dom, (int) wp_date( 'Y' ) );
				if ( $t > $today ) {
					$dates[] = wp_date( 'Y-m-d', $t );
				}
			}
			$dates[] = wp_date( 'Y-m-t' );
		} elseif ( 'simplifie' === $regime ) {
			$label   = __( 'Régime simplifié: monthly transmission.', 'buildsbyluke-facture-electronique-for-woocommerce' );
			$dates[] = wp_date( 'Y-m-t' );
		} else {
			$label   = __( 'Franchise en base: transmission every 2 months.', 'buildsbyluke-facture-electronique-for-woocommerce' );
			$month   = (int) wp_date( 'n' );
			$even    = $month + ( $month % 2 ); // Next even month end.
			$dates[] = wp_date( 'Y-m-t', mktime( 0, 0, 0, $even, 1, (int) wp_date( 'Y' ) ) );
		}

		return array(
			'label' => $label,
			'dates' => array_slice( $dates, 0, 3 ),
		);
	}
}
