<?php
/**
 * Importación y exportación Excel/CSV de minutas.
 *
 * @package Logistica
 */

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

/**
 * Plantilla y carga de minutas.
 */
class Logistica_Minutas_Excel {

	/**
	 * @return array<string, string>
	 */
	public static function columns() {
		return Logistica_Minutas::columns();
	}

	/**
	 * Descarga .xlsx con hoja "minutas".
	 *
	 * @return void
	 */
	public static function download_template() {
		$rows = Logistica_Minutas::get_all();

		if ( class_exists( 'ZipArchive', false ) ) {
			self::download_xlsx_template( $rows );
		}

		self::download_csv_template( $rows );
	}

	/**
	 * @param array $file $_FILES row.
	 * @return array{message:string,created:int,skipped:int,error?:bool}
	 */
	public static function import_upload( $file ) {
		if ( empty( $file['tmp_name'] ) || ! is_uploaded_file( $file['tmp_name'] ) ) {
			return self::error( __( 'No se recibió ningún archivo.', 'logistica' ) );
		}

		$parsed = Logistica_Warehouse_Inventory_Excel::parse_upload_columns(
			$file,
			self::columns(),
			'minuta'
		);

		if ( is_wp_error( $parsed ) ) {
			return self::error( $parsed->get_error_message() );
		}

		$stats = Logistica_Minutas::replace_all( $parsed );

		if ( ! empty( $stats['error'] ) ) {
			return self::error( (string) $stats['error'] );
		}

		$message = (int) $stats['skipped'] > 0
			? sprintf(
				/* translators: 1: imported count 2: skipped count */
				__( 'Importación completada. Minutas cargadas: %1$d. Filas sin número de minuta: %2$d.', 'logistica' ),
				(int) $stats['created'],
				(int) $stats['skipped']
			)
			: sprintf(
				/* translators: %d: imported count */
				__( 'Importación completada. Minutas cargadas: %d.', 'logistica' ),
				(int) $stats['created']
			);

		return array(
			'message' => $message,
			'created' => (int) $stats['created'],
			'skipped' => (int) $stats['skipped'],
		);
	}

	/**
	 * @param array<int, array<string, mixed>> $rows Filas.
	 * @return void
	 */
	private static function download_xlsx_template( $rows ) {
		$sheet_xml = self::build_xlsx_sheet_xml( $rows );
		$tmp       = wp_tempnam( 'minutas-export.xlsx' );

		if ( ! $tmp ) {
			return;
		}

		$zip = new ZipArchive();
		if ( true !== $zip->open( $tmp, ZipArchive::OVERWRITE ) ) {
			@unlink( $tmp ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
			return;
		}

		$zip->addFromString(
			'[Content_Types].xml',
			'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
			. '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
			. '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'
			. '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>'
			. '<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>'
			. '</Types>'
		);
		$zip->addFromString(
			'_rels/.rels',
			'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
			. '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
			. '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'
			. '</Relationships>'
		);
		$zip->addFromString(
			'xl/workbook.xml',
			'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
			. '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
			. '<sheets><sheet name="minutas" sheetId="1" r:id="rId1"/></sheets>'
			. '</workbook>'
		);
		$zip->addFromString(
			'xl/_rels/workbook.xml.rels',
			'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
			. '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
			. '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>'
			. '</Relationships>'
		);
		$zip->addFromString( 'xl/worksheets/sheet1.xml', $sheet_xml );
		$zip->close();

		nocache_headers();
		header( 'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' );
		header( 'Content-Disposition: attachment; filename="minutas-export.xlsx"' );
		header( 'Content-Length: ' . (string) filesize( $tmp ) );
		readfile( $tmp ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
		@unlink( $tmp ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
		exit;
	}

	/**
	 * @param array<int, array<string, mixed>> $rows Filas.
	 * @return void
	 */
	private static function download_csv_template( $rows ) {
		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="minutas-export.csv"' );

		$handle = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
		if ( false === $handle ) {
			exit;
		}

		fwrite( $handle, "\xEF\xBB\xBF" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite
		fputcsv( $handle, array_values( self::columns() ), ';' );

		$data_rows = empty( $rows ) ? array( array() ) : $rows;
		foreach ( $data_rows as $row ) {
			$line = array();
			foreach ( array_keys( self::columns() ) as $key ) {
				$line[] = $row[ $key ] ?? '';
			}
			fputcsv( $handle, $line, ';' );
		}

		fclose( $handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
		exit;
	}

	/**
	 * @param array<int, array<string, mixed>> $rows Filas.
	 * @return string
	 */
	private static function build_xlsx_sheet_xml( $rows ) {
		$keys       = array_keys( self::columns() );
		$sheet_rows = array();
		$sheet_rows[] = Logistica_Warehouse_Inventory_Excel::build_xlsx_row_xml_public( 1, array_values( self::columns() ), $keys, true );

		if ( empty( $rows ) ) {
			$sheet_rows[] = Logistica_Warehouse_Inventory_Excel::build_xlsx_row_xml_public( 2, array(), $keys, false );
		} else {
			$row_number = 2;
			foreach ( $rows as $row ) {
				$cells = array();
				foreach ( $keys as $key ) {
					$cells[] = $row[ $key ] ?? '';
				}
				$sheet_rows[] = Logistica_Warehouse_Inventory_Excel::build_xlsx_row_xml_public( $row_number, $cells, $keys, false );
				++$row_number;
			}
		}

		return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
			. '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'
			. '<sheetData>' . implode( '', $sheet_rows ) . '</sheetData>'
			. '</worksheet>';
	}

	/**
	 * @param string $message Mensaje.
	 * @return array{message:string,created:int,skipped:int,error:bool}
	 */
	private static function error( $message ) {
		return array(
			'message' => $message,
			'created' => 0,
			'skipped' => 0,
			'error'   => true,
		);
	}
}
