<?php

namespace WPDesk\FakturyKSEF\Api\Model;

class DocumentState {

	private const STATUS_ERROR   = 'failed';
	private const STATUS_PENDING = 'pending';
	private const STATUS_SUCCESS = 'success';

	private string $status;

	private array $errors;

	private ?string $document_ref_number;

	private ?string $ksef_number;

	private ?array $raw_response;

	private ?string $verification_key;

	private bool $is_network_error;

	public function __construct(
		string $status = self::STATUS_PENDING,
		array $errors = [],
		?string $document_ref_number = null,
		?string $ksef_number = null,
		?array $raw_response = null,
		?string $verification_key = null,
		bool $is_network_error = false
	) {
		$this->raw_response        = $raw_response;
		$this->document_ref_number = $document_ref_number;
		$this->ksef_number         = $ksef_number;
		$this->errors              = $errors;
		$this->status              = $status;
		$this->verification_key    = $verification_key;
		$this->is_network_error    = $is_network_error;
	}

	public function is_success(): bool {
		return $this->status === self::STATUS_SUCCESS && $this->ksef_number !== null;
	}

	public function has_errors(): bool {
		return ! empty( $this->errors ) || $this->status === self::STATUS_ERROR;
	}

	public function get_errors(): array {
		return $this->errors;
	}

	public function get_error_messages(): array {
		return array_column( $this->errors, 'message' );
	}

	public function set_raw_response( array $raw_response ): self {
		$this->raw_response = $raw_response;
		return $this;
	}

	public function get_raw_response(): ?array {
		return $this->raw_response;
	}

	public function clear_errors(): self {
		$this->errors = [];
		return $this;
	}

	public function get_formatted_errors( string $separator = ', ' ): string {
		return implode( $separator, $this->get_error_messages() );
	}

	public function get_reference_number(): ?string {
		return $this->document_ref_number;
	}

	public function get_ksef_number(): ?string {
		return $this->ksef_number;
	}

	public function get_status(): string {
		return $this->status;
	}

	public function set_verification_key( string $key ): self {
		$this->verification_key = $key;
		return $this;
	}

	public function get_verification_key(): ?string {
		return $this->verification_key;
	}

	public function set_network_error( bool $is_network_error ): self {
		$this->is_network_error = $is_network_error;
		return $this;
	}

	public function is_network_error(): bool {
		return $this->is_network_error;
	}

	public function mark_as_success( string $document_ref_number ): self {
		$this->status              = self::STATUS_SUCCESS;
		$this->errors              = [];
		$this->document_ref_number = $document_ref_number;
		return $this;
	}

	public function add_error( string $message ): self {
		$this->status   = self::STATUS_ERROR;
		$this->errors[] = [
			'message' => $message,
		];
		return $this;
	}


	public function to_array(): array {
		return [
			'status'              => $this->status,
			'errors'              => $this->errors,
			'raw_response'        => $this->raw_response,
			'document_ref_number' => $this->document_ref_number,
			'ksef_number'         => $this->ksef_number,
			'verification_key'    => $this->verification_key,
			'is_network_error'    => $this->is_network_error,
		];
	}

	public static function from_array( ?array $data ): self {
		if ( ! $data ) {
			return new self();
		}
		return new self(
			$data['status'] ?? self::STATUS_PENDING,
			$data['errors'] ?? [],
			$data['document_ref_number'] ?? null,
			/* Firstly check if ksef number is stored inside normal response. If not - check duplicates report for ksefNumber. Return null if nothing is correct */
			$data['raw_response']['ksefNumber'] ?? $data['raw_response']['status']['extensions']['originalKsefNumber'] ?? null,
			$data['raw_response'] ?? null,
			$data['verification_key'] ?? null,
			$data['is_network_error'] ?? false
		);
	}
}
