<?php

declare(strict_types=1);

namespace CloudXM\NFe\DTOs;

use JsonSerializable;

/**
 * Issue Invoice Request DTO
 * 
 * Represents the v2 API request for issuing an invoice
 * CRITICAL: service_code field is REMOVED in v2 - use municipal_service_code and national_service_code
 */
class IssueInvoiceRequest implements JsonSerializable
{
    public function __construct(
        public string $order_number,
        public ClientData $client,
        public string $description,
        public float $quantity,
        public float $unit_price,
        public string $municipality_code,
        public ?bool $debug = null,
        public ?string $municipal_service_code = null,
        public ?string $national_service_code = null,
        public ?string $nbs_code = null,
        public ?string $tax_classification = null,
        public ?float $iss_rate = null,
        public ?string $internal_contributor_code = null,
        public ?string $complementary_information = null,
        public ?FederalTaxation $federal_taxation = null,
        // Idempotency field - prevents duplicate invoices on retry
        public ?string $idempotency_key = null,
        // Scheduling / webhook fields
        public ?string $issue_mode = null,
        public ?string $scheduled_at = null,
        public ?string $timezone = null,
        public ?bool $retry_on_failure = null,
        public ?int $max_retries = null,
        public ?int $retry_interval_minutes = null,
        public ?string $webhook_url = null,
        public ?string $webhook_secret = null,
        public ?string $cnpj_issuer = null,
    ) {}

    /**
     * Validate request data
     * 
     * @return array Empty array if valid, array of errors if invalid
     */
    public function validate(): array
    {
        $errors = [];

        if (empty($this->order_number)) {
            $errors['order_number'] = 'Order number is required';
        }

        if (empty($this->municipality_code)) {
            $errors['municipality_code'] = 'Municipality code is required';
        }

        if (empty($this->description)) {
            $errors['description'] = 'Description is required';
        }

        if ($this->quantity <= 0) {
            $errors['quantity'] = 'Quantity must be greater than zero';
        }

        if ($this->unit_price < 0) {
            $errors['unit_price'] = 'Unit price must be non-negative';
        }

        if ($this->iss_rate !== null && ($this->iss_rate < 0 || $this->iss_rate > 100)) {
            $errors['iss_rate'] = 'ISS rate must be between 0 and 100';
        }

        // Validate client data
        $clientErrors = $this->client->validate();
        if (!empty($clientErrors)) {
            $errors['client'] = $clientErrors;
        }

        // Validate federal taxation if provided
        if ($this->federal_taxation !== null) {
            $taxationErrors = $this->federal_taxation->validate();
            if (!empty($taxationErrors)) {
                $errors['federal_taxation'] = $taxationErrors;
            }
        }

        return $errors;
    }

    /**
     * Serialize to JSON for API request
     * CRITICAL: service_code is NOT included in v2 API
     */
    public function jsonSerialize(): array
    {
        $data = [
            'order_number' => $this->order_number,
            'municipality_code' => $this->municipality_code,
            'client' => $this->client->jsonSerialize(),
            'description' => $this->description,
            'quantity' => $this->quantity,
            'unit_price' => $this->unit_price,
        ];

        // Idempotency key - include first if present
        if ($this->idempotency_key !== null) {
            $data['idempotency_key'] = $this->idempotency_key;
        }

        // Add optional fields
        if ($this->debug !== null) {
            $data['debug'] = $this->debug;
        }

        if ($this->municipal_service_code !== null) {
            $data['municipal_service_code'] = $this->municipal_service_code;
        }

        if ($this->national_service_code !== null) {
            $data['national_service_code'] = $this->national_service_code;
        }

        if ($this->nbs_code !== null) {
            $data['nbs_code'] = $this->nbs_code;
        }

        if ($this->tax_classification !== null) {
            $data['tax_classification'] = $this->tax_classification;
        }

        if ($this->iss_rate !== null) {
            $data['iss_rate'] = $this->iss_rate;
        }

        if ($this->internal_contributor_code !== null) {
            $data['internal_contributor_code'] = $this->internal_contributor_code;
        }

        $data['complementary_information'] = $this->complementary_information ?? '';

        if ($this->federal_taxation !== null) {
            $data['federal_taxation'] = $this->federal_taxation->jsonSerialize();
        }

        // Scheduling / webhook fields
        if ($this->issue_mode !== null) {
            $data['issue_mode'] = $this->issue_mode;
        }

        if ($this->scheduled_at !== null) {
            $data['scheduled_at'] = $this->scheduled_at;
        }

        if ($this->timezone !== null) {
            $data['timezone'] = $this->timezone;
        }

        if ($this->retry_on_failure !== null) {
            $data['retry_on_failure'] = $this->retry_on_failure;
        }

        if ($this->max_retries !== null) {
            $data['max_retries'] = $this->max_retries;
        }

        if ($this->retry_interval_minutes !== null) {
            $data['retry_interval_minutes'] = $this->retry_interval_minutes;
        }

        if ($this->webhook_url !== null) {
            $data['webhook_url'] = $this->webhook_url;
        }

        if ($this->webhook_secret !== null) {
            $data['webhook_secret'] = $this->webhook_secret;
        }

        if ($this->cnpj_issuer !== null) {
            $data['cnpj_issuer'] = $this->cnpj_issuer;
        }

        return $data;
    }
}
