<?php
/**
 * Invoice document type.
 *
 * @package Kramar
 * @since   1.0.0
 */

declare( strict_types=1 );

namespace Kramar\Modules\Invoices;

defined( 'ABSPATH' ) || exit;

/**
 * Invoice document — full EU VAT Directive Art. 226 compliant.
 *
 * @since 1.0.0
 */
final class Invoice extends Document {

	/** {@inheritDoc} */
	public function get_type(): string {
		return 'invoice';
	}

	/** {@inheritDoc} */
	public function get_title_label(): string {
		return __( 'INVOICE', 'kramar' );
	}

	/**
	 * Assign a sequential invoice number to this order (if not already assigned).
	 *
	 * @since 1.0.0
	 *
	 * @return string Formatted invoice number.
	 */
	public function assign_number(): string {
		$existing = $this->order->get_meta( '_kramar_invoice_number' );
		if ( '' !== $existing && false !== $existing ) {
			return (string) $existing;
		}

		$raw = Number_Store::get_next_number( $this->order->get_id(), 'invoice' );

		$formatted = Number_Store::format_number(
			$raw,
			$this->settings['number_prefix'] ?? '',
			$this->settings['number_suffix'] ?? '',
			(int) ( $this->settings['number_padding'] ?? 4 )
		);

		$this->order->update_meta_data( '_kramar_invoice_number', $formatted );
		$this->order->update_meta_data( '_kramar_invoice_number_raw', $raw );

		// Keep an issue date that already exists. Regenerate clears the number so
		// this method runs again, and stamping unconditionally re-dated an old
		// invoice to today — an accurate issue date is required by art. 226(3) of
		// Directive 2006/112/EC, and a rebuilt PDF is the same invoice.
		$existing_date = $this->order->get_meta( '_kramar_invoice_date' );
		if ( '' === $existing_date || false === $existing_date ) {
			$this->order->update_meta_data( '_kramar_invoice_date', current_time( 'mysql' ) );
		}

		$this->order->save_meta_data();

		return $formatted;
	}

	/** {@inheritDoc} */
	public function get_document_data(): array {
		$data = parent::get_document_data();

		if ( '' === $data['number'] ) {
			if ( $this->preview ) {
				// Display-only placeholder — no DB write, no sequence consumed.
				$data['number'] = Number_Store::format_number(
					1,
					$this->settings['number_prefix'] ?? '',
					$this->settings['number_suffix'] ?? '',
					(int) ( $this->settings['number_padding'] ?? 4 )
				);
				if ( '' === $data['date'] ) {
					$data['date'] = current_time( 'mysql' );
				}
			} else {
				$data['number'] = $this->assign_number();
				$data['date']   = (string) $this->order->get_meta( '_kramar_invoice_date' );
			}
		}

		if ( '' !== $data['date'] ) {
			$dt = \DateTime::createFromFormat( 'Y-m-d H:i:s', $data['date'] );
			if ( $dt ) {
				$data['date'] = wp_date( wc_date_format(), $dt->getTimestamp() );
			}
		}

		return $data;
	}

	/**
	 * Generate the PDF and store it encrypted.
	 *
	 * @since 1.0.0
	 *
	 * @return string Relative path to stored encrypted file.
	 */
	public function generate_and_store(): string {
		$existing = $this->order->get_meta( '_kramar_invoice_file' );
		if ( '' !== $existing && false !== $existing ) {
			return (string) $existing;
		}

		$number = $this->assign_number();
		$html   = Block_Renderer::render( $this );
		$pdf    = Pdf_Renderer::render( $html, $this->settings['paper_size'] ?? 'a4' );

		$rel_path = Storage::store( $pdf, 'invoice', $number );

		$this->order->update_meta_data( '_kramar_invoice_file', $rel_path );
		$this->order->save_meta_data();

		return $rel_path;
	}

	/**
	 * Get the download filename for this invoice.
	 *
	 * @since 1.0.0
	 */
	public function get_filename(): string {
		$number = $this->order->get_meta( '_kramar_invoice_number' );
		$safe   = preg_replace( '/[^a-zA-Z0-9\-]/', '', (string) $number );
		return 'invoice-' . $safe . '.pdf';
	}
}
