<?php
/**
 * Caterpoint Order Management Controller
 *
 * @category    PortalPeople
 * @package     Caterpoint
 * @author      Portal People Development Team
 * @copyright   Copyright (c) 2026 Portal People (https://portalpeople.co.uk)
 */

namespace PortalPeople\caterpoint\controllers;

use Yii;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use PortalPeople\caterpoint\Module;

/**
 * Order Management Controller
 * 
 * Provides friendly HTML interfaces for Caterpoint order operations
 * 
 * Routes (for /NGauge/caterpoint/*):
 *   GET    /NGauge/caterpoint/order/index           Order management dashboard
 *   GET    /NGauge/caterpoint/order/fetch-raw       View raw order data from API
 *   GET    /NGauge/caterpoint/order/bulk-list       Browse incoming orders for selective import
 *   POST   /NGauge/caterpoint/order/bulk-import     Import selected cached orders
 *   POST   /NGauge/caterpoint/order/import          Trigger manual import
 */
class OrderController extends Controller
{
    /**
     * @var Module Module instance
     */
    private ?Module $caterpointModule = null;

    /**
     * Configure controller behaviors
     * 
     * @return array
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
            'verbs' => [
                'class' => VerbFilter::class,
                'actions' => [
                    'bulk-import' => ['POST'],
                    'import' => ['POST'],
                    'reset' => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Initialize the controller
     * 
     * @throws \Exception
     */
    public function init()
    {
        parent::init();

        try {
            $this->caterpointModule = Yii::$app->getModule('caterpoint');
        } catch (\Exception $e) {
            throw new \yii\web\ServerErrorHttpException('Caterpoint module not configured: ' . $e->getMessage());
        }

        if ($this->caterpointModule === null) {
            throw new \yii\web\ServerErrorHttpException('Caterpoint module not found');
        }
    }

    /**
     * Order management dashboard
     * 
     * @return string HTML response
     */
    public function actionIndex()
    {
        $service = $this->caterpointModule->createOrderImportService();
        $cursor = $service->cursorStore->get();
        
        return $this->render('index', [
            'module' => $this->caterpointModule,
            'currentCursor' => $cursor,
            'configured' => $this->caterpointModule->isConfigured(),
        ]);
    }

    /**
     * View raw order data from Caterpoint API
     * 
     * Query parameters:
     *   - cursor: Optional cursor for pagination
     *   - limit: Limit per request (default 1)
     *   - format: Response format (html, json, xml) - default html
     *   - normalize: Return data in Magento format (0 or 1) - default 0
     * 
     * @return string|Response HTML response or raw data
     */
    public function actionFetchRaw()
    {
        $request = Yii::$app->request;
        $cursor = $request->get('cursor');
        $limit = (int) $request->get('limit', 1);
        $format = (string) $request->get('format', 'html');
        $normalize = (bool) $request->get('normalize', false);
        $client = null;

        try {
            $client = $this->caterpointModule->createClient();
            $result = $client->getOrdersUpdatedSince($cursor, $limit);
            $sourceFormat = $client->getLastResponseFormat();

            // Apply normalization if requested
            $data = $result;
            if ($normalize && isset($result['orders'])) {
                $data = [
                    'orders' => \PortalPeople\caterpoint\components\DataNormalizer::normalizeOrders($result['orders']),
                    'nextCursor' => $result['nextCursor'] ?? null,
                    'total' => $result['total'] ?? count($result['orders'] ?? []),
                ];
            }

            if ($format === 'json') {
                Yii::$app->response->format = Response::FORMAT_JSON;
                return [
                    'success' => true,
                    'message' => 'Raw orders fetched from Caterpoint API',
                    'sourceFormat' => $sourceFormat,
                    'normalized' => $normalize,
                    'data' => $data,
                ];
            }

            if ($format === 'xml') {
                Yii::$app->response->format = Response::FORMAT_XML;
                return [
                    'success' => true,
                    'message' => 'Raw orders fetched from Caterpoint API',
                    'sourceFormat' => $sourceFormat,
                    'normalized' => $normalize,
                    'data' => $data,
                ];
            }

            return $this->render('fetch-raw', [
                'result' => $result,
                'sourceFormat' => $sourceFormat,
                'cursor' => $cursor,
                'limit' => $limit,
                'error' => null,
            ]);
        } catch (\Throwable $e) {
            $errorMessage = 'Failed to fetch orders: ' . $e->getMessage();
            $sourceFormat = $client !== null ? $client->getLastResponseFormat() : null;

            if ($format === 'json') {
                Yii::$app->response->format = Response::FORMAT_JSON;
                Yii::$app->response->statusCode = 502;

                return [
                    'success' => false,
                    'message' => $errorMessage,
                    'sourceFormat' => $sourceFormat,
                    'normalized' => $normalize,
                    'data' => null,
                ];
            }

            if ($format === 'xml') {
                Yii::$app->response->format = Response::FORMAT_XML;
                Yii::$app->response->statusCode = 502;

                return [
                    'success' => false,
                    'message' => $errorMessage,
                    'sourceFormat' => $sourceFormat,
                    'normalized' => $normalize,
                    'data' => null,
                ];
            }

            return $this->render('fetch-raw', [
                'result' => [],
                'sourceFormat' => $sourceFormat ?? 'unknown',
                'cursor' => $cursor,
                'limit' => $limit,
                'error' => $errorMessage,
            ]);
        }
    }

    /**
     * Trigger manual import
     * 
     * @return Response
     */
    public function actionImport()
    {
        if (!$this->caterpointModule->isConfigured()) {
            Yii::$app->session->setFlash('error', 'Caterpoint module is not configured');
            return $this->redirect(['index']);
        }

        $request = Yii::$app->request;
        $limit = (int) $request->post('limit', 0);
        $dryRun = (bool) $request->post('dryRun', false);

        try {
            $service = $this->caterpointModule->createOrderImportService();
            $result = $service->run(null, $limit, $dryRun);

            $message = $dryRun ? 'Dry run completed' : 'Import completed';
            $message .= ": {$result['created']} created, {$result['updated']} updated";
            
            Yii::$app->session->setFlash('success', $message);
        } catch (\Throwable $e) {
            Yii::error('Order import failed: ' . $e->getMessage(), 'caterpoint.import');
            Yii::$app->session->setFlash('error', 'Import failed: ' . $e->getMessage());
        }

        return $this->redirect(['index']);
    }

    /**
     * Reset import cursor
     * 
     * @return Response
     */
    public function actionReset()
    {
        try {
            $service = $this->caterpointModule->createOrderImportService();
            $service->cursorStore->clear();
            Yii::$app->session->setFlash('success', 'Import cursor reset successfully');
        } catch (\Throwable $e) {
            Yii::$app->session->setFlash('error', 'Failed to reset cursor: ' . $e->getMessage());
        }

        return $this->redirect(['index']);
    }

    /**
     * List incoming orders with caching and bulk import options
     * 
     * Fetches orders from Caterpoint, normalizes them, caches the data,
     * and displays them in a GridView with checkboxes for selective import
     * 
     * @return string HTML response with order grid
     */
    public function actionBulkList()
    {
        if (!$this->caterpointModule->isConfigured()) {
            Yii::$app->session->setFlash('error', 'Caterpoint module is not configured');
            return $this->redirect(['index']);
        }

        $request = Yii::$app->request;
        $cursor = $request->get('cursor');
        $limit = (int) $request->get('limit', 50);
        $refresh = (bool) $request->get('refresh', false);

        try {
            $cache = Yii::$app->cache;
            $cacheKey = "caterpoint_orders_{$cursor}_{$limit}";

            // Get orders - either from cache or fresh from API
            if (!$refresh && $cache->exists($cacheKey)) {
                $cachedData = $cache->get($cacheKey);
                $orders = $cachedData['orders'];
                $nextCursor = $cachedData['nextCursor'];
                $timestamp = $cachedData['timestamp'] ?? time();
                $cached = true;
            } else {
                $client = $this->caterpointModule->createClient();
                $result = $client->getOrdersUpdatedSince($cursor, $limit);
                
                // Normalize orders for backend import
                $orders = \PortalPeople\caterpoint\components\DataNormalizer::normalizeOrders(
                    $result['orders'] ?? []
                );
                $nextCursor = $result['nextCursor'] ?? null;
                $timestamp = time();
                $cached = false;
            }

            $orders = \PortalPeople\caterpoint\components\ProductLookup::enrichOrders($orders);

            // Cache the enriched orders for 1 hour
            $cache->set($cacheKey, [
                'orders' => $orders,
                'nextCursor' => $nextCursor,
                'timestamp' => $timestamp,
            ], 3600);

            return $this->render('bulk-list', [
                'orders' => $orders,
                'nextCursor' => $nextCursor,
                'cursor' => $cursor,
                'limit' => $limit,
                'cacheKey' => $cacheKey,
                'cached' => $cached,
            ]);
        } catch (\Throwable $e) {
            Yii::error('Failed to list orders: ' . $e->getMessage(), 'caterpoint.bulk');
            Yii::$app->session->setFlash('error', 'Failed to fetch orders: ' . $e->getMessage());
            return $this->redirect(['index']);
        }
    }

    /**
     * Bulk import selected orders to backend
     * 
     * Processes checked orders and creates backend cart records
     * 
     * @return Response Redirect with success/error message
     */
    public function actionBulkImport()
    {
        if (!$this->caterpointModule->isConfigured()) {
            Yii::$app->session->setFlash('error', 'Caterpoint module is not configured');
            return $this->redirect(['bulk-list']);
        }

        $request = Yii::$app->request;
        $orderIds = $request->post('order_ids', []);
        $cacheKey = $request->post('cache_key');
        $productMap = $request->post('product_map', []);
        $orderKeys = $request->post('order_keys', []);

        if (empty($orderIds) || !$cacheKey) {
            Yii::$app->session->setFlash('error', 'No orders selected for import');
            return $this->redirect(['bulk-list']);
        }

        try {
            $cache = Yii::$app->cache;
            $cachedData = $cache->get($cacheKey);

            if (!$cachedData) {
                Yii::$app->session->setFlash('error', 'Cache expired. Please refresh the order list.');
                return $this->redirect(['bulk-list']);
            }

            $orders = $cachedData['orders'];
            $successful = 0;
            $failed = 0;
            $skipped = 0;
            $productMappingsByOrderId = [];

            if (is_array($orderKeys) && is_array($productMap)) {
                foreach ($orderKeys as $orderIndex => $mappedOrderId) {
                    $mappedOrderId = (string) $mappedOrderId;
                    if ($mappedOrderId === '') {
                        continue;
                    }

                    $productMappingsByOrderId[$mappedOrderId] = [];
                    if (!isset($productMap[$orderIndex]) || !is_array($productMap[$orderIndex])) {
                        continue;
                    }

                    foreach ($productMap[$orderIndex] as $itemIndex => $productId) {
                        $productId = trim((string) $productId);
                        if ($productId === '') {
                            continue;
                        }

                        $productMappingsByOrderId[$mappedOrderId][$itemIndex] = $productId;
                    }
                }
            }

            foreach ($orderIds as $orderId) {
                // Find the order in cache by ID (order.id in normalized data)
                $orderData = null;
                foreach ($orders as $order) {
                    if ($order['order']['id'] === $orderId) {
                        $orderData = $order;
                        break;
                    }
                }

                if (!$orderData) {
                    $skipped++;
                    continue;
                }

                try {
                    $cart = \PortalPeople\caterpoint\components\OrderImporter::newCaterPointOrder(
                        $orderData,
                        $productMappingsByOrderId[(string) $orderId] ?? []
                    );
                    
                    if ($cart) {
                        $successful++;
                        Yii::info("Order imported: {$orderId} -> {$cart->id}", 'caterpoint.bulk');
                    } else {
                        $failed++;
                        Yii::warning("Failed to import order: {$orderId}", 'caterpoint.bulk');
                    }
                } catch (\Throwable $e) {
                    $failed++;
                    Yii::error("Exception importing order {$orderId}: {$e->getMessage()}", 'caterpoint.bulk');
                }
            }

            $message = "Import completed: {$successful} succeeded";
            if ($failed > 0) {
                $message .= ", {$failed} failed";
            }
            if ($skipped > 0) {
                $message .= ", {$skipped} skipped";
            }

            Yii::$app->session->setFlash('success', $message);
        } catch (\Throwable $e) {
            Yii::error('Bulk import failed: ' . $e->getMessage(), 'caterpoint.bulk');
            Yii::$app->session->setFlash('error', 'Bulk import failed: ' . $e->getMessage());
        }

        return $this->redirect(['bulk-list']);
    }
}
