<?php

namespace PortalPeople\virtualstock\commands;

use Yii;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\helpers\Json;
use PortalPeople\virtualstock\Module;

/**
 * Test VirtualStock API endpoints from the command line.
 *
 * Usage:
 *   ./yii virtualstock/api/get-orders
 *   ./yii virtualstock/api/get-orders --cursor=2026-01-01T00:00:00Z --limit=10
 *   ./yii virtualstock/api/get-order --order-no=VS-00123
 *   ./yii virtualstock/api/list-products
 *   ./yii virtualstock/api/list-products --filters='{"limit":5}'
 *   ./yii virtualstock/api/get-product --product-no=SKU-123
 *   ./yii virtualstock/api/get-product-stock --product-no=SKU-123
 */
class ApiController extends Controller
{
    /** @var string|null Cursor / updatedSince timestamp for get-orders */
    public ?string $cursor = null;

    /** @var int Max records to fetch */
    public int $limit = 100;

    /** @var string|null Order number for get-order */
    public ?string $orderNo = null;

    /** @var string|null Supplier product number for get-product / get-product-stock */
    public ?string $productNo = null;

    /** @var string JSON object of extra filters for list-products */
    public string $filters = '{}';

    public function options($actionID): array
    {
        $common = ['cursor', 'limit', 'orderNo', 'productNo', 'filters'];
        return array_merge(parent::options($actionID), $common);
    }

    public function optionAliases(): array
    {
        return [
            'c' => 'cursor',
            'l' => 'limit',
            'o' => 'orderNo',
            'p' => 'productNo',
            'f' => 'filters',
        ];
    }

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

    /**
     * Fetch orders (optionally filtered by cursor).
     *
     * ./yii virtualstock/api/get-orders [--cursor=<ts>] [--limit=<n>]
     */
    public function actionGetOrders(): int
    {
        $client = $this->client();
        if ($client === null) {
            return ExitCode::UNSPECIFIED_ERROR;
        }

        try {
            $result = $client->getOrdersUpdatedSince(
                $this->cursor !== '' ? $this->cursor : null,
                $this->limit
            );
            $this->printResult($result);
            return ExitCode::OK;
        } catch (\Throwable $e) {
            return $this->fail($e);
        }
    }

    /**
     * Fetch a single order by order number.
     *
     * ./yii virtualstock/api/get-order --order-no=<orderNo>
     */
    public function actionGetOrder(): int
    {
        if (!$this->orderNo) {
            $this->stderr("--order-no is required.\n");
            return ExitCode::USAGE;
        }

        $client = $this->client();
        if ($client === null) {
            return ExitCode::UNSPECIFIED_ERROR;
        }

        try {
            $result = $client->getOrder($this->orderNo);
            $this->printResult($result);
            return ExitCode::OK;
        } catch (\Throwable $e) {
            return $this->fail($e);
        }
    }

    /**
     * Fetch a single order line item by its numeric ID.
     * Item IDs appear in the `items` array of each order.
     *
     * ./yii virtualstock/api/get-item --product-no=<itemId>   (e.g. 577754)
     */
    public function actionGetItem(): int
    {
        if (!$this->productNo) {
            $this->stderr("--product-no (item ID) is required. Find IDs inside get-orders results.\n");
            return ExitCode::USAGE;
        }

        $client = $this->client();
        if ($client === null) {
            return ExitCode::UNSPECIFIED_ERROR;
        }

        try {
            $result = $client->getItem($this->productNo);
            $this->printResult($result);
            return ExitCode::OK;
        } catch (\Throwable $e) {
            return $this->fail($e);
        }
    }

    /**
     * List customers/retailers.
     *
     * ./yii virtualstock/api/list-customers [--filters='{"limit":10}']
     */
    public function actionListCustomers(): int
    {
        $client = $this->client();
        if ($client === null) {
            return ExitCode::UNSPECIFIED_ERROR;
        }

        $filters = [];
        $raw = trim($this->filters);
        if ($raw !== '' && $raw !== '{}') {
            $decoded = json_decode($raw, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                $this->stderr("--filters must be valid JSON. Got: {$raw}\n");
                return ExitCode::USAGE;
            }
            $filters = (array) $decoded;
        }

        try {
            $result = $client->listCustomers($filters);
            $this->printResult($result);
            return ExitCode::OK;
        } catch (\Throwable $e) {
            return $this->fail($e);
        }
    }

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

    /**
     * Probe a list of paths to find which ones return 200.
     * ./yii virtualstock/api/probe
     */
    public function actionProbe(): int
    {
        $client = $this->client();
        if ($client === null) {
            return ExitCode::UNSPECIFIED_ERROR;
        }
        $paths = ['items', 'items/577754', 'supplier-products', 'catalogue', 'products', 'skus', 'stock', 'suppliers', 'customers', 'orders/631541', 'orders/631541/items'];
        foreach ($paths as $path) {
            try {
                $r = $client->request('GET', $path, []);
                $keys = array_keys($r);
                $this->stdout($path . ': OK [' . implode(', ', $keys) . ']' . PHP_EOL);
            } catch (\Throwable $e) {
                $this->stdout($path . ': ' . $e->getMessage() . PHP_EOL);
            }
        }
        return ExitCode::OK;
    }

    private function client(): ?\PortalPeople\virtualstock\components\VirtualStockClient
    {
        /** @var Module|null $module */
        $module = Yii::$app->getModule('virtualstock');

        if (!$module instanceof Module) {
            $this->stderr("VirtualStock module is not registered.\n");
            return null;
        }

        if (!$module->isConfigured()) {
            $this->stderr("VirtualStock module is not configured (apiEndpoint missing or disabled).\n");
            return null;
        }

        return $module->createClient();
    }

    private function printResult(array $data): void
    {
        $this->stdout(Json::encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . PHP_EOL);
    }

    private function fail(\Throwable $e): int
    {
        $this->stderr("Error: {$e->getMessage()}\n");
        return ExitCode::UNSPECIFIED_ERROR;
    }
}
