<?php
/**
 * Consignment Form Model – DX Despatch Manager Module
 *
 * @category    PortalPeople
 * @package     DX
 * @author      Portal People Development Team
 * @copyright   Copyright (c) 2026 Portal People (https://portalpeople.co.uk)
 */

namespace PortalPeople\dx\models;

use yii\base\Model;

/**
 * ConsignmentForm
 *
 * Validates and builds the payload for a single DX consignment.
 * Maps to the CreateConsignment API request body structure.
 *
 * Package type codes: BX=Box, PLT=Pallet, ENV=Envelope, etc.
 * Service codes: obtained from Services/GetServices for the delivery postcode.
 */
class ConsignmentForm extends Model
{
    // -------------------------------------------------------------------------
    // Delivery address (DX uses single address — the destination)
    // -------------------------------------------------------------------------

    /** @var string Recipient name (max 30). */
    public $recipient;

    /** @var string Company name (max 40). */
    public $company;

    /** @var string Address line 1 (max 50) – required. */
    public $address1;

    /** @var string Address line 2 (max 50). */
    public $address2;

    /** @var string Address line 3 (max 50). */
    public $address3;

    /** @var string Town (max 30) – required. */
    public $town;

    /** @var string County (max 30) – required for IE only. */
    public $county;

    /** @var string Postcode (max 8) – required. */
    public $postcode;

    /** @var string ISO 2-letter country code (max 2) – required, default GB. */
    public $countryCode = 'GB';

    /** @var string Phone number (max 15). */
    public $phone;

    /** @var string Email address (max 50). */
    public $email;

    /** @var string Special instructions (max 75). */
    public $specialInstructions;

    // -------------------------------------------------------------------------
    // Consignment details
    // -------------------------------------------------------------------------

    /** @var string Customer reference / unique order reference. */
    public $reference;

    /** @var string Despatch date in YYYY-MM-DD format. */
    public $despatchDate;

    /** @var string DX service code, e.g. 'NS'. Populated from GetServices. */
    public $serviceCode = 'NS';

    // -------------------------------------------------------------------------
    // Items (each item in the consignment)
    // -------------------------------------------------------------------------

    /** @var int Number of items/packages. */
    public $itemQuantity = 1;

    /** @var string Package type code (max 3), e.g. 'BX', 'PLT'. */
    public $packageTypeCode = 'BX';

    /** @var float Weight in kg per item. */
    public $weight;

    // -------------------------------------------------------------------------

    /** @inheritdoc */
    public function rules(): array
    {
        return [
            // Required delivery address fields
            [['address1', 'town', 'postcode', 'countryCode'], 'required'],
            [['recipient'], 'string', 'max' => 30],
            [['company'], 'string', 'max' => 40],
            [['address1', 'address2', 'address3'], 'string', 'max' => 50],
            [['town', 'county'], 'string', 'max' => 30],
            [['postcode'], 'string', 'max' => 8],
            [['countryCode'], 'string', 'length' => 2],
            [['phone'], 'string', 'max' => 15],
            [['email'], 'email'],
            [['email'], 'string', 'max' => 50],
            [['specialInstructions'], 'string', 'max' => 75],

            // Consignment
            [['despatchDate', 'serviceCode'], 'required'],
            [['despatchDate'], 'date', 'format' => 'php:Y-m-d'],
            [['reference', 'serviceCode', 'packageTypeCode'], 'string'],
            [['packageTypeCode'], 'string', 'max' => 3],

            // Items
            [['itemQuantity'], 'integer', 'min' => 1],
            [['weight'], 'required'],
            [['weight'], 'number', 'min' => 0.01],

            // Optional nullable fields
            [['recipient', 'company', 'address2', 'address3', 'county', 'phone', 'email', 'specialInstructions', 'reference'], 'default', 'value' => ''],
        ];
    }

    /** @inheritdoc */
    public function attributeLabels(): array
    {
        return [
            'recipient'            => 'Recipient Name',
            'company'              => 'Company Name',
            'address1'             => 'Address Line 1',
            'address2'             => 'Address Line 2',
            'address3'             => 'Address Line 3',
            'town'                 => 'Town',
            'county'               => 'County',
            'postcode'             => 'Postcode',
            'countryCode'          => 'Country Code',
            'phone'                => 'Phone',
            'email'                => 'Email',
            'specialInstructions'  => 'Special Instructions',
            'reference'            => 'Customer Reference',
            'despatchDate'         => 'Despatch Date',
            'serviceCode'          => 'Service Code',
            'itemQuantity'         => 'Item Quantity',
            'packageTypeCode'      => 'Package Type Code',
            'weight'               => 'Weight (kg)',
        ];
    }

    // -------------------------------------------------------------------------

    /**
     * Build the delivery address array for the DX API.
     * @return array
     */
    public function getDeliveryAddress(): array
    {
        $address = [
            'address1'    => $this->address1,
            'town'        => $this->town,
            'postcode'    => $this->postcode,
            'countryCode' => $this->countryCode ?: 'GB',
        ];

        if (!empty($this->recipient))  { $address['recipient']  = $this->recipient; }
        if (!empty($this->company))    { $address['company']    = $this->company; }
        if (!empty($this->address2))   { $address['address2']   = $this->address2; }
        if (!empty($this->address3))   { $address['address3']   = $this->address3; }
        if (!empty($this->county))     { $address['county']     = $this->county; }
        if (!empty($this->phone))      { $address['phone']      = $this->phone; }
        if (!empty($this->email))      { $address['email']      = $this->email; }
        if (!empty($this->specialInstructions)) {
            $address['specialInstructions'] = $this->specialInstructions;
        }

        return $address;
    }

    /**
     * Build the consignment data array for CreateConsignment.
     *
     * @param string $accountCode  Injected from module config
     * @return array
     */
    public function getConsignmentData(string $accountCode = ''): array
    {
        return [
            'accountCode'     => $accountCode,
            'reference'       => $this->reference,
            'despatchDate'    => $this->despatchDate,
            'deliveryAddress' => $this->getDeliveryAddress(),
            'serviceCode'     => $this->serviceCode,
            'items'           => [
                [
                    'quantity'        => (int) $this->itemQuantity,
                    'packageTypeCode' => $this->packageTypeCode,
                    'weight'          => (float) $this->weight,
                ],
            ],
        ];
    }
}
