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

namespace PortalPeople\palletforce\controllers;

use Yii;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use PortalPeople\palletforce\models\ConsignmentForm;
use PortalPeople\palletforce\jobs\ConsignmentJob;

/**
 * ConsignmentController
 *
 * Handles consignment creation, cancellation and tracking via the
 * Palletforce API.
 */
class ConsignmentController extends Controller
{
    /** @inheritdoc */
    public function behaviors(): array
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
            'verbs' => [
                'class'   => VerbFilter::class,
                'actions' => [
                    'create'   => ['POST'],
                    'cancel'   => ['POST'],
                    'accept'   => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Form to create a new consignment.
     *
     * On POST: validates, then dispatches a ConsignmentJob or sends directly
     * depending on whether a queue is available.
     *
     * @return string|Response
     */
    public function actionCreate()
    {
        $model = new ConsignmentForm();

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            $uniqueRef = 'NGPF-' . date('YmdHis') . '-' . rand(1000, 9999);

            // Use queue if available, otherwise send synchronously
            if (Yii::$app->has('queue')) {
                Yii::$app->queue->push(new ConsignmentJob([
                    'consignmentData'   => $model->getConsignmentData(),
                    'collectionAddress' => $model->getCollectionAddress(),
                    'deliveryAddress'   => $model->getDeliveryAddress(),
                    'uniqueRef'         => $uniqueRef,
                ]));

                Yii::$app->session->setFlash('success', 'Consignment queued for dispatch (Ref: ' . $uniqueRef . ').');
                return $this->refresh();
            }

            // Synchronous send
            $result = $this->sendConsignment($model, $uniqueRef);

            if ($result['success'] ?? false) {
                Yii::$app->session->setFlash('success', 'Consignment created. Tracking: ' . implode(', ', $result['TrackingCodes'] ?? []));
                return $this->refresh();
            }

            Yii::$app->session->setFlash('error', 'Palletforce error: ' . ($result['message'] ?? 'unknown error'));
        }

        return $this->render('create', ['model' => $model]);
    }

    /**
     * AJAX: cancel (delete) a consignment before acceptance.
     *
     * @return array
     */
    public function actionCancel(): array
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $trackingCode = Yii::$app->request->post('trackingCode');
        $uniqueRef    = 'NGPF-DEL-' . date('YmdHis');

        if (empty($trackingCode)) {
            return ['success' => false, 'message' => 'trackingCode is required.'];
        }

        try {
            $client = Yii::$app->palletforceClient;
            $result = $client->deleteConsignment($trackingCode, $uniqueRef);
            return ['success' => $result['Success'] ?? false, 'message' => $result['Message'] ?? ''];
        } catch (\Exception $e) {
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * AJAX: accept one or more pending consignments.
     *
     * @return array
     */
    public function actionAccept(): array
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $trackingCodes = (array) Yii::$app->request->post('trackingCodes', []);
        $uniqueRef     = 'NGPF-ACC-' . date('YmdHis');

        if (empty($trackingCodes)) {
            return ['success' => false, 'message' => 'trackingCodes is required.'];
        }

        try {
            $client = Yii::$app->palletforceClient;
            $result = $client->acceptConsignments($trackingCodes, $uniqueRef);
            return ['success' => $result['Success'] ?? false, 'message' => $result['Message'] ?? ''];
        } catch (\Exception $e) {
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * AJAX: download tracking data for a consignment.
     *
     * @return array
     */
    public function actionTracking(): array
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $trackingNumber = Yii::$app->request->get('trackingNumber');
        $uniqueRef      = 'NGPF-TRK-' . date('YmdHis');

        if (empty($trackingNumber)) {
            return ['success' => false, 'message' => 'trackingNumber is required.'];
        }

        try {
            $client = Yii::$app->palletforceClient;
            $result = $client->downloadTrackingData($trackingNumber, $uniqueRef, [
                'lastUpdated' => '19700101000000',
            ]);
            return ['success' => true, 'data' => $result];
        } catch (\Exception $e) {
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * AJAX: get ETA for one or more consignments.
     *
     * @return array
     */
    public function actionEta(): array
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $trackingCodes = (array) Yii::$app->request->get('trackingCodes', []);
        $uniqueRef     = 'NGPF-ETA-' . date('YmdHis');

        if (empty($trackingCodes)) {
            return ['success' => false, 'message' => 'trackingCodes is required.'];
        }

        try {
            $client = Yii::$app->palletforceClient;
            $result = $client->downloadETATimes($trackingCodes, $uniqueRef);
            return ['success' => true, 'data' => $result];
        } catch (\Exception $e) {
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * AJAX: print / retrieve labels (base64 images) for a consignment.
     *
     * @return array
     */
    public function actionLabels(): array
    {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $trackingNumber = Yii::$app->request->get('trackingNumber');
        $palletNumber   = Yii::$app->request->get('palletNumber');
        $uniqueRef      = 'NGPF-LBL-' . date('YmdHis');

        if (empty($trackingNumber)) {
            return ['success' => false, 'message' => 'trackingNumber is required.'];
        }

        try {
            $client = Yii::$app->palletforceClient;
            $result = $client->printLabels(
                $trackingNumber,
                $uniqueRef,
                $palletNumber !== null ? (int) $palletNumber : null
            );
            return ['success' => true, 'data' => $result];
        } catch (\Exception $e) {
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

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

    /**
     * Send a consignment synchronously and return the API response.
     *
     * @param ConsignmentForm $model
     * @param string          $uniqueRef
     * @return array
     */
    private function sendConsignment(ConsignmentForm $model, string $uniqueRef): array
    {
        try {
            $client = Yii::$app->palletforceClient;
            return $client->uploadManifest(
                $model->getConsignmentData(),
                $uniqueRef,
                $model->getCollectionAddress(),
                $model->getDeliveryAddress()
            );
        } catch (\Exception $e) {
            Yii::error('Palletforce consignment error: ' . $e->getMessage(), 'palletforce');
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }
}
