<?php
/**
 * Collection run (Beitragslauf): pick a date, generate the pain.008 file for
 * all active members, download it, upload it to the bank.
 *
 * The generated file is run through the bundled validator before it is
 * offered for download — the whole point of this plugin is that a file it
 * hands you is a file your bank accepts.
 */

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

class BSTEW_Admin_Run {

	public static function init() {
		add_action( 'admin_post_bstew_generate_run', array( __CLASS__, 'handle_generate' ) );
		add_action( 'admin_post_bstew_download_run', array( __CLASS__, 'handle_download' ) );
	}

	public static function handle_generate() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( 'forbidden' );
		}
		check_admin_referer( 'bstew_run' );

		$collection_date = isset( $_POST['collection_date'] ) ? sanitize_text_field( wp_unslash( $_POST['collection_date'] ) ) : '';
		$options         = bstew_get_options();
		$members         = BSTEW_Store::active_members();

		$year   = $collection_date ? substr( $collection_date, 0, 4 ) : gmdate( 'Y' );
		$purpose = str_replace( '{jahr}', $year, $options['purpose'] );

		$debits = array();
		$items  = array();
		foreach ( $members as $m ) {
			$debits[] = array(
				'name'          => $m->name,
				'iban'          => BSTEW_Store::member_iban( $m ),
				'mandate_ref'   => $m->mandate_ref,
				'mandate_date'  => $m->mandate_date,
				'sequence_type' => $m->sequence_type,
				'amount'        => $m->amount,
				'purpose'       => $purpose,
				'street'        => $m->street,
				'postcode'      => $m->postcode,
				'city'          => $m->city,
				'country'       => $m->country,
				'end_to_end'    => 'BST-' . $year . '-M' . $m->id,
			);
			$items[]  = array(
				'member_id'  => (int) $m->id,
				'amount'     => $m->amount,
				'end_to_end' => 'BST-' . $year . '-M' . $m->id,
			);
		}

		// One MsgId for the XML and the run record: max 35 chars per pain.008 schema
		// and the runs table — a longer value fails the insert on strict-mode MySQL.
		$msg_id = 'BST-' . gmdate( 'Ymd-His' ) . '-' . wp_rand( 100, 999 );
		$writer = new BSTEW_Sepa_Writer();
		$xml    = $writer->build( $options, $debits, array( 'collection_date' => $collection_date, 'msg_id' => $msg_id ) );

		if ( '' === $xml ) {
			set_transient( 'bstew_run_errors_' . get_current_user_id(), $writer->errors, 300 );
			wp_safe_redirect( add_query_arg( array( 'page' => 'beitrag-steward-run', 'bstew_msg' => 'errors' ), admin_url( 'admin.php' ) ) );
			exit;
		}

		// Trust nothing, including ourselves: the file the treasurer downloads
		// has passed the same checks the validator screen applies to foreign files.
		$validator = new BSTEW_Validator();
		$verdict   = $validator->validate( $xml );
		if ( ! $verdict['ok'] ) {
			$msgs = array_map( function ( $f ) {
				return $f['message'];
			}, $verdict['findings'] );
			set_transient( 'bstew_run_errors_' . get_current_user_id(), $msgs, 300 );
			wp_safe_redirect( add_query_arg( array( 'page' => 'beitrag-steward-run', 'bstew_msg' => 'errors' ), admin_url( 'admin.php' ) ) );
			exit;
		}

		bstew_prepare_storage_dir();
		$file = 'beitragslauf-' . gmdate( 'Ymd-His' ) . '.xml';
		file_put_contents( trailingslashit( bstew_storage_dir() ) . $file, $xml ); // phpcs:ignore

		$total = 0.0;
		foreach ( $debits as $d ) {
			$total += (float) $d['amount'];
		}
		$run_id = BSTEW_Store::record_run(
			array(
				'msg_id'          => $msg_id,
				'collection_date' => $collection_date,
				'purpose'         => $purpose,
				'tx_count'        => count( $debits ),
				'total'           => number_format( $total, 2, '.', '' ),
				'xml_file'        => $file,
			),
			$items
		);

		if ( $run_id < 1 ) {
			global $wpdb;
			set_transient( 'bstew_run_errors_' . get_current_user_id(), array( __( 'The file was generated but the run could not be recorded in the database.', 'beitrag-steward' ) . ' ' . $wpdb->last_error ), 300 );
			wp_safe_redirect( add_query_arg( array( 'page' => 'beitrag-steward-run', 'bstew_msg' => 'errors' ), admin_url( 'admin.php' ) ) );
			exit;
		}

		wp_safe_redirect( add_query_arg( array( 'page' => 'beitrag-steward-run', 'bstew_msg' => 'done', 'run' => $run_id ), admin_url( 'admin.php' ) ) );
		exit;
	}

	public static function handle_download() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( 'forbidden' );
		}
		$id = isset( $_GET['id'] ) ? (int) $_GET['id'] : 0;
		check_admin_referer( 'bstew_download_' . $id );
		$run = BSTEW_Store::get_run( $id );
		if ( ! $run || '' === $run->xml_file ) {
			wp_die( esc_html__( 'Run not found.', 'beitrag-steward' ) );
		}
		$path = trailingslashit( bstew_storage_dir() ) . basename( $run->xml_file );
		if ( ! file_exists( $path ) ) {
			wp_die( esc_html__( 'File no longer exists.', 'beitrag-steward' ) );
		}
		header( 'Content-Type: application/xml; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . basename( $path ) . '"' );
		header( 'Content-Length: ' . filesize( $path ) );
		readfile( $path ); // phpcs:ignore
		exit;
	}

	public static function render() {
		$members = BSTEW_Store::active_members();
		$options = bstew_get_options();
		$msg     = isset( $_GET['bstew_msg'] ) ? sanitize_key( $_GET['bstew_msg'] ) : ''; // phpcs:ignore
		$total   = 0.0;
		$ready   = 0;
		foreach ( $members as $m ) {
			$total += (float) $m->amount;
			if ( $m->iban_last4 && $m->mandate_ref && $m->mandate_date ) {
				$ready++;
			}
		}
		// Lead time: banks need the file 1-2 business days ahead; suggest +3 calendar days.
		$suggested = gmdate( 'Y-m-d', time() + 3 * DAY_IN_SECONDS );
		?>
		<div class="wrap">
			<h1><?php esc_html_e( 'Collection run', 'beitrag-steward' ); ?></h1>

			<?php if ( 'errors' === $msg ) : ?>
				<div class="notice notice-error"><p><strong><?php esc_html_e( 'No file was generated:', 'beitrag-steward' ); ?></strong></p><ul style="list-style:disc;margin-left:20px">
					<?php foreach ( (array) get_transient( 'bstew_run_errors_' . get_current_user_id() ) as $e ) : ?>
						<li><?php echo esc_html( $e ); ?></li>
					<?php endforeach; ?>
				</ul></div>
			<?php elseif ( 'done' === $msg ) : ?>
				<div class="notice notice-success"><p><?php esc_html_e( 'SEPA file generated and validated. Download it below and upload it in your online banking.', 'beitrag-steward' ); ?></p></div>
			<?php endif; ?>

			<p>
				<?php
				printf(
					/* translators: 1: member count, 2: ready count, 3: total */
					esc_html__( '%1$d active members, %2$d with complete SEPA data. Collection total: %3$s €.', 'beitrag-steward' ),
					count( $members ),
					(int) $ready,
					esc_html( number_format( $total, 2, ',', '.' ) )
				);
				?>
			</p>

			<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
				<?php wp_nonce_field( 'bstew_run' ); ?>
				<input type="hidden" name="action" value="bstew_generate_run">
				<table class="form-table" role="presentation" style="max-width:640px">
					<tr><th><label for="bstew_cdate"><?php esc_html_e( 'Collection date', 'beitrag-steward' ); ?></label></th>
						<td><input type="date" id="bstew_cdate" name="collection_date" value="<?php echo esc_attr( $suggested ); ?>" min="<?php echo esc_attr( gmdate( 'Y-m-d' ) ); ?>">
						<p class="description"><?php esc_html_e( 'Give your bank one or two business days of lead time.', 'beitrag-steward' ); ?></p></td></tr>
				</table>
				<?php submit_button( __( 'Generate SEPA file (pain.008.001.08)', 'beitrag-steward' ) ); ?>
			</form>

			<h2><?php esc_html_e( 'Previous runs', 'beitrag-steward' ); ?></h2>
			<table class="widefat striped" style="max-width:900px">
				<thead><tr>
					<th><?php esc_html_e( 'Created', 'beitrag-steward' ); ?></th>
					<th><?php esc_html_e( 'Collection date', 'beitrag-steward' ); ?></th>
					<th><?php esc_html_e( 'Members', 'beitrag-steward' ); ?></th>
					<th><?php esc_html_e( 'Total', 'beitrag-steward' ); ?></th>
					<th></th>
				</tr></thead>
				<tbody>
				<?php $runs = BSTEW_Store::runs(); ?>
				<?php if ( empty( $runs ) ) : ?>
					<tr><td colspan="5"><?php esc_html_e( 'No runs yet.', 'beitrag-steward' ); ?></td></tr>
				<?php endif; ?>
				<?php foreach ( $runs as $r ) : ?>
					<tr>
						<td><?php echo esc_html( $r->created_at ); ?></td>
						<td><?php echo esc_html( $r->collection_date ); ?></td>
						<td><?php echo (int) $r->tx_count; ?></td>
						<td><?php echo esc_html( number_format( (float) $r->total, 2, ',', '.' ) ); ?> €</td>
						<td><a href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=bstew_download_run&id=' . $r->id ), 'bstew_download_' . $r->id ) ); ?>"><?php esc_html_e( 'Download XML', 'beitrag-steward' ); ?></a></td>
					</tr>
				<?php endforeach; ?>
				</tbody>
			</table>
		</div>
		<?php
	}
}

BSTEW_Admin_Run::init();
