<?php

namespace PortalPeople\qvc\components;

use Yii;
use yii\base\Component;

class QvcImportService extends Component
{
    public static function cartsbeFields(): array
    {
        return [
            'account_code' => 'Account Code',
            'name' => 'Order Name',
            'email' => 'Email',
            'contact' => 'Contact Name',
            'telephone' => 'Telephone',
            'postcode' => 'Postcode',
            'ordernumber' => 'Order Number (ext ref)',
            'porderref' => 'PO Reference',
            'paymentmethod' => 'Payment Method',
            'message' => 'Notes / Message',
            'delivery_notes' => 'Delivery Notes',
            'shippingmethod' => 'Shipping Method',
            'deliveryaddress' => 'Delivery Address',
            'billingaddress' => 'Billing Address',
            'status' => 'Order Status',
        ];
    }

    public static function cartlinesFields(): array
    {
        return [
            'productid' => 'Product ID',
            'stock_code' => 'Stock Code',
            'product_name' => 'Product Name',
            'product_description' => 'Product Description',
            'qty' => 'Quantity',
            'price' => 'Unit Price (inc. VAT)',
            'price_exvat' => 'Unit Price (ex. VAT)',
            'disc' => 'Discount %',
            'sequence' => 'Line Sequence',
            'currency_code' => 'Currency Code',
        ];
    }

    public static function guessMapping(string $header): string
    {
        $norm = strtolower(preg_replace('/[\s\-_.]+/', '_', trim($header)));

        $hints = [
            'qty' => 'cartlines.qty',
            'quantity' => 'cartlines.qty',
            'sku' => 'cartlines.stock_code',
            'item_code' => 'cartlines.stock_code',
            'stock_code' => 'cartlines.stock_code',
            'product_name' => 'cartlines.product_name',
            'product' => 'cartlines.product_name',
            'description' => 'cartlines.product_description',
            'product_description' => 'cartlines.product_description',
            'unit_price' => 'cartlines.price',
            'price' => 'cartlines.price',
            'price_ex' => 'cartlines.price_exvat',
            'price_exvat' => 'cartlines.price_exvat',
            'discount' => 'cartlines.disc',
            'disc' => 'cartlines.disc',
            'currency' => 'cartlines.currency_code',
            'currency_code' => 'cartlines.currency_code',
            'account_code' => 'cartsbe.account_code',
            'account' => 'cartsbe.account_code',
            'order_number' => 'cartsbe.ordernumber',
            'ordernumber' => 'cartsbe.ordernumber',
            'order_no' => 'cartsbe.ordernumber',
            'order_ref' => 'cartsbe.ordernumber',
            'po' => 'cartsbe.porderref',
            'po_number' => 'cartsbe.porderref',
            'porderref' => 'cartsbe.porderref',
            'purchase_order' => 'cartsbe.porderref',
            'email' => 'cartsbe.email',
            'name' => 'cartsbe.name',
            'contact' => 'cartsbe.contact',
            'telephone' => 'cartsbe.telephone',
            'phone' => 'cartsbe.telephone',
            'postcode' => 'cartsbe.postcode',
            'delivery_address' => 'cartsbe.deliveryaddress',
            'deliveryaddress' => 'cartsbe.deliveryaddress',
            'billing_address' => 'cartsbe.billingaddress',
            'billingaddress' => 'cartsbe.billingaddress',
            'notes' => 'cartsbe.message',
            'message' => 'cartsbe.message',
            'delivery_notes' => 'cartsbe.delivery_notes',
            'shipping_method' => 'cartsbe.shippingmethod',
            'shippingmethod' => 'cartsbe.shippingmethod',
            'payment_method' => 'cartsbe.paymentmethod',
            'paymentmethod' => 'cartsbe.paymentmethod',
            'status' => 'cartsbe.status',
        ];

        return $hints[$norm] ?? '__skip__';
    }

    public function convertRowsToOrders(array $rows): array
    {
        $orders = [];
        $skippedRows = [];

        foreach ($rows as $index => $row) {
            $lineNumber = $index + 2;
            $orderRef = $this->findValue($row, ['order_number', 'order_no', 'orderno', 'order_ref', 'orderid', 'order_id']);
            $sku = $this->findValue($row, ['sku', 'item', 'item_code', 'itemcode']);
            $qtyRaw = $this->findValue($row, ['qty', 'quantity']);

            if ($orderRef === '' || $sku === '' || $qtyRaw === '') {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Missing required values: order reference, sku, or quantity.',
                    'row' => $row,
                ];
                continue;
            }

            $quantity = (int) $qtyRaw;
            if ($quantity <= 0) {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Quantity must be greater than zero.',
                    'row' => $row,
                ];
                continue;
            }

            if (!isset($orders[$orderRef])) {
                $orders[$orderRef] = [
                    'orderRef' => $orderRef,
                    'customerRef' => $this->findValue($row, ['customer_ref', 'customer_reference', 'customer']),
                    'poNumber' => $this->findValue($row, ['po_number', 'po', 'purchase_order']),
                    'lines' => [],
                ];
            }

            $orders[$orderRef]['lines'][] = [
                'sku' => $sku,
                'quantity' => $quantity,
                'price' => $this->findValue($row, ['price', 'unit_price']),
                'raw' => $row,
            ];
        }

        return [
            'orders' => array_values($orders),
            'skippedRows' => $skippedRows,
        ];
    }

    public function convertRowsWithMapping(array $rows, array $mapping): array
    {
        $orders = [];
        $skippedRows = [];

        $orderKeyCol = null;
        $orderKeyPriority = ['cartsbe.ordernumber', 'cartsbe.porderref', 'cartsbe.account_code'];
        foreach ($orderKeyPriority as $priority) {
            $col = array_search($priority, $mapping, true);
            if ($col !== false) {
                $orderKeyCol = $col;
                break;
            }
        }

        foreach ($rows as $index => $row) {
            $lineNumber = $index + 2;

            $groupKey = $orderKeyCol !== null && isset($row[$orderKeyCol])
                ? trim((string) $row[$orderKeyCol])
                : '';

            if ($groupKey === '') {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Order identifier column is empty.',
                    'row' => $row,
                ];
                continue;
            }

            $cartsbeData = [];
            $cartlineData = [];

            foreach ($mapping as $csvCol => $target) {
                if (empty($target) || $target === '__skip__') {
                    continue;
                }

                [$model, $field] = explode('.', $target, 2);
                $value = isset($row[$csvCol]) ? trim((string) $row[$csvCol]) : '';

                if ($model === 'cartsbe') {
                    $cartsbeData[$field] = $value;
                } elseif ($model === 'cartlines') {
                    $cartlineData[$field] = $value;
                }
            }

            $qty = isset($cartlineData['qty']) ? (int) $cartlineData['qty'] : 0;
            if ($qty <= 0) {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Quantity is zero or missing.',
                    'row' => $row,
                ];
                continue;
            }
            $cartlineData['qty'] = $qty;

            if (!isset($orders[$groupKey])) {
                $orders[$groupKey] = [
                    'groupKey' => $groupKey,
                    'cartsbe' => $cartsbeData,
                    'lines' => [],
                ];
            }

            $orders[$groupKey]['lines'][] = $cartlineData;
        }

        return [
            'orders' => array_values($orders),
            'skippedRows' => $skippedRows,
        ];
    }

    public function buildSummary(array $orders, array $skippedRows): array
    {
        $lineCount = 0;
        foreach ($orders as $order) {
            $lineCount += count($order['lines']);
        }

        return [
            'orderCount' => count($orders),
            'lineCount' => $lineCount,
            'skippedCount' => count($skippedRows),
        ];
    }

    public function importOrders(array $orders): array
    {
        $imported = 0;
        $errors = [];

        foreach ($orders as $order) {
            try {
                Yii::warning([
                    'message' => 'QVC order import approved',
                    'order' => $order,
                ], 'qvc.order.import');

                $imported++;
            } catch (\Throwable $e) {
                $errors[] = [
                    'orderRef' => $order['orderRef'] ?? 'unknown',
                    'error' => $e->getMessage(),
                ];
            }
        }

        if (!empty($errors)) {
            return [
                'success' => false,
                'message' => sprintf('Imported %d orders, %d failed.', $imported, count($errors)),
                'errors' => $errors,
            ];
        }

        return [
            'success' => true,
            'message' => sprintf('Successfully imported %d orders.', $imported),
            'errors' => [],
        ];
    }

    public function importMappedOrders(array $orders): array
    {
        $imported = 0;
        $errors = [];

        foreach ($orders as $order) {
            $db = Yii::$app->db;
            $transaction = $db->beginTransaction();

            try {
                $cartsbe = new \backend\models\Cartsbe();
                foreach ($order['cartsbe'] as $field => $value) {
                    if ($cartsbe->hasAttribute($field)) {
                        $cartsbe->$field = $value;
                    }
                }
                $cartsbe->nooflines = count($order['lines']);

                if (!$cartsbe->save()) {
                    throw new \RuntimeException(
                        'Cartsbe save failed: ' . implode('; ', array_map(
                            static fn($msgs) => implode(', ', $msgs),
                            $cartsbe->getErrors()
                        ))
                    );
                }

                foreach ($order['lines'] as $lineData) {
                    $cartline = new \backend\models\Cartlines();
                    $cartline->basketid = $cartsbe->id;

                    foreach ($lineData as $field => $value) {
                        if ($cartline->hasAttribute($field)) {
                            $cartline->$field = $value;
                        }
                    }

                    if (!$cartline->save()) {
                        throw new \RuntimeException(
                            'Cartlines save failed: ' . implode('; ', array_map(
                                static fn($msgs) => implode(', ', $msgs),
                                $cartline->getErrors()
                            ))
                        );
                    }
                }

                $transaction->commit();
                $imported++;
            } catch (\Throwable $e) {
                $transaction->rollBack();
                $errors[] = [
                    'groupKey' => $order['groupKey'] ?? 'unknown',
                    'error' => $e->getMessage(),
                ];
                Yii::error([
                    'message' => 'QVC mapped import failed',
                    'groupKey' => $order['groupKey'] ?? 'unknown',
                    'error' => $e->getMessage(),
                ], 'qvc.mapped.import');
            }
        }

        if (!empty($errors)) {
            return [
                'success' => false,
                'message' => sprintf('Imported %d orders, %d failed.', $imported, count($errors)),
                'errors' => $errors,
            ];
        }

        return [
            'success' => true,
            'message' => sprintf(
                'Successfully imported %d orders (%d lines total).',
                $imported,
                array_sum(array_map(static fn($o) => count($o['lines']), $orders))
            ),
            'errors' => [],
        ];
    }

    private function findValue(array $row, array $aliases): string
    {
        foreach ($aliases as $alias) {
            foreach ($row as $key => $value) {
                if ($this->normalizeHeader((string) $key) === $this->normalizeHeader($alias)) {
                    return trim((string) $value);
                }
            }
        }

        return '';
    }

    private function normalizeHeader(string $header): string
    {
        return strtolower(str_replace([' ', '-', '.'], '_', trim($header)));
    }
}
