<?php
declare(strict_types=1);

namespace App\Modules\Sales\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Sales\Models\Sale;
use App\Modules\Sales\Models\SaleItem;
use App\Modules\Sales\Models\SaleRefund;
use App\Modules\Sales\Services\SaleService;
use App\Modules\Sales\Services\RefundService;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Models\InventoryItem;
use App\Modules\Sales\Models\Package;

class SaleController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'q'             => trim((string) $request->get('q', '')),
            'status'        => trim((string) $request->get('status', '')),
            'customer_type' => trim((string) $request->get('customer_type', '')),
            'warehouse_id'  => trim((string) $request->get('warehouse_id', '')),
            'date_from'     => trim((string) $request->get('date_from', '')),
            'date_to'       => trim((string) $request->get('date_to', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = Sale::search($filters, 25, $page);

        return $this->view('Sales.Views.sales.index', [
            'sales'         => $result['data'],
            'pagination'    => $result['pagination'],
            'filters'       => $filters,
            'statuses'      => Sale::getStatuses(),
            'customerTypes' => Sale::getCustomerTypes(),
            'warehouses'    => Warehouse::allActive(),
        ]);
    }

    /**
     * POS screen for creating a new sale.
     */
    public function create(Request $request): Response
    {
        return $this->view('Sales.Views.pos.index', [
            'warehouses' => Warehouse::allActive(),
            'packages'   => Package::allActive(),
        ]);
    }

    public function store(Request $request): Response
    {
        $warehouseId  = (int) $request->post('warehouse_id', 0);
        $customerType = trim((string) $request->post('customer_type', 'guest'));
        $memberId     = (int) $request->post('member_id', 0);
        $playerId     = (int) $request->post('player_id', 0);
        $guestName    = trim((string) $request->post('guest_name', ''));
        $guestPhone   = trim((string) $request->post('guest_phone', ''));
        $discount     = trim((string) $request->post('discount_amount', '0'));
        $discountReason = trim((string) $request->post('discount_reason', ''));
        $paymentMethod = trim((string) $request->post('payment_method', 'cash'));
        $notes        = trim((string) $request->post('notes', ''));

        // Parse line items
        $itemIds     = $request->post('item_ids', []);
        $packageIds  = $request->post('package_ids', []);
        $quantities  = $request->post('quantities', []);
        $unitPrices  = $request->post('unit_prices', []);
        $itemNames   = $request->post('item_names', []);
        $costPrices  = $request->post('cost_prices', []);
        $taxAmounts  = $request->post('tax_amounts', []);

        $lines = [];
        $count = max(count($itemIds ?: []), count($packageIds ?: []));
        for ($i = 0; $i < $count; $i++) {
            $qty = (string) ($quantities[$i] ?? '0');
            if (bccomp($qty, '0', 3) <= 0) continue;

            $lines[] = [
                'item_id'      => ($itemIds[$i] ?? 0) ? (int) $itemIds[$i] : null,
                'package_id'   => ($packageIds[$i] ?? 0) ? (int) $packageIds[$i] : null,
                'quantity'     => $qty,
                'unit_price'   => (string) ($unitPrices[$i] ?? '0'),
                'item_name_ar' => (string) ($itemNames[$i] ?? ''),
                'cost_price'   => ($costPrices[$i] ?? '') ?: null,
                'tax_amount'   => (string) ($taxAmounts[$i] ?? '0'),
            ];
        }

        $result = SaleService::createSale([
            'warehouse_id'    => $warehouseId,
            'customer_type'   => $customerType,
            'member_id'       => $memberId ?: null,
            'player_id'       => $playerId ?: null,
            'guest_name'      => $guestName ?: null,
            'guest_phone'     => $guestPhone ?: null,
            'discount_amount' => $discount,
            'discount_reason' => $discountReason ?: null,
            'payment_method'  => $paymentMethod,
            'notes'           => $notes ?: null,
        ], $lines);

        if (!$result['success']) {
            return $this->redirect('/sales/create')->withError($result['error']);
        }

        return $this->redirect('/sales/' . $result['sale_id'])->withSuccess('تم إنشاء المبيعة بنجاح — فاتورة: ' . $result['invoice_number']);
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $sale = $db->selectOne(
            "SELECT s.*, w.`name_ar` as warehouse_name
             FROM `sales` s
             JOIN `warehouses` w ON w.`id` = s.`warehouse_id`
             WHERE s.`id` = ?",
            [(int) $id]
        );

        if (!$sale) {
            return $this->redirect('/sales')->withError('المبيعة غير موجودة');
        }

        // Customer name
        $customerName = $sale['guest_name'] ?? 'زائر';
        if ($sale['customer_type'] === 'member' && $sale['member_id']) {
            $member = $db->selectOne("SELECT `full_name_ar` FROM `members` WHERE `id` = ?", [(int) $sale['member_id']]);
            $customerName = $member['full_name_ar'] ?? '—';
        } elseif ($sale['customer_type'] === 'player' && $sale['player_id']) {
            $player = $db->selectOne("SELECT `full_name_ar` FROM `players` WHERE `id` = ?", [(int) $sale['player_id']]);
            $customerName = $player['full_name_ar'] ?? '—';
        }

        $items = SaleItem::getForSale((int) $id);
        $refunds = SaleRefund::getForSale((int) $id);

        return $this->view('Sales.Views.sales.show', [
            'sale'         => $sale,
            'customerName' => $customerName,
            'items'        => $items,
            'refunds'      => $refunds,
        ]);
    }

    public function void(Request $request, string $id): Response
    {
        $reason = trim((string) $request->post('reason', ''));
        if ($reason === '') {
            return $this->redirect('/sales/' . $id)->withError('يجب إدخال سبب الإلغاء');
        }

        $result = SaleService::voidSale((int) $id, $reason);
        if (!$result['success']) {
            return $this->redirect('/sales/' . $id)->withError($result['error']);
        }

        return $this->redirect('/sales/' . $id)->withSuccess('تم إلغاء المبيعة بنجاح');
    }

    public function refundForm(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $sale = $db->selectOne("SELECT * FROM `sales` WHERE `id` = ?", [(int) $id]);
        if (!$sale) {
            return $this->redirect('/sales')->withError('المبيعة غير موجودة');
        }

        $items = SaleItem::getForSale((int) $id);

        return $this->view('Sales.Views.sales.refund', [
            'sale'  => $sale,
            'items' => $items,
        ]);
    }

    public function refund(Request $request, string $id): Response
    {
        $amount        = trim((string) $request->post('refund_amount', '0'));
        $reason        = trim((string) $request->post('reason', ''));
        $returnToStock = (bool) $request->post('return_to_stock', 0);

        if ($reason === '') {
            return $this->redirect('/sales/' . $id . '/refund')->withError('يجب إدخال سبب الاسترجاع');
        }

        // Parse refund items
        $saleItemIds = $request->post('sale_item_ids', []);
        $refundQtys  = $request->post('refund_quantities', []);

        $refundItems = [];
        foreach ($saleItemIds as $i => $siId) {
            $qty = (string) ($refundQtys[$i] ?? '0');
            if (bccomp($qty, '0', 3) > 0) {
                $refundItems[] = ['sale_item_id' => (int) $siId, 'quantity' => $qty];
            }
        }

        $result = RefundService::processRefund((int) $id, $amount, $reason, $returnToStock, $refundItems);
        if (!$result['success']) {
            return $this->redirect('/sales/' . $id . '/refund')->withError($result['error']);
        }

        return $this->redirect('/sales/' . $id)->withSuccess('تم الاسترجاع بنجاح — رقم: ' . $result['refund_number']);
    }

    public function printInvoice(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $sale = $db->selectOne("SELECT s.*, w.`name_ar` as warehouse_name FROM `sales` s JOIN `warehouses` w ON w.`id` = s.`warehouse_id` WHERE s.`id` = ?", [(int) $id]);
        if (!$sale) {
            return $this->redirect('/sales')->withError('المبيعة غير موجودة');
        }

        $items = SaleItem::getForSale((int) $id);

        return $this->view('Sales.Views.pos.invoice', [
            'sale'  => $sale,
            'items' => $items,
        ]);
    }

    public function memberHistory(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT `id`, `full_name_ar` FROM `members` WHERE `id` = ?", [(int) $memberId]);

        $sales = $db->select(
            "SELECT * FROM `sales` WHERE `member_id` = ? ORDER BY `created_at` DESC LIMIT 50",
            [(int) $memberId]
        );

        return $this->view('Sales.Views.sales.member_history', [
            'member' => $member,
            'sales'  => $sales,
        ]);
    }

    public function searchItems(Request $request): Response
    {
        $q = trim((string) $request->get('q', ''));
        if (mb_strlen($q) < 2) {
            return $this->json(['results' => []]);
        }

        $db = App::getInstance()->db();
        $search = '%' . $q . '%';
        $rows = $db->select(
            "SELECT `id`, `sku`, `name_ar`, `sale_price_member`, `sale_price_nonmember`, `sale_price_player`, `cost_price`, `tax_rate`, `unit_of_measure`, `tracking_type`
             FROM `inventory_items`
             WHERE (`name_ar` LIKE ? OR `sku` LIKE ? OR `barcode` LIKE ?)
               AND `is_sellable` = 1 AND `is_active` = 1 AND `is_archived` = 0
             ORDER BY `name_ar` ASC LIMIT 20",
            [$search, $search, $search]
        );

        return $this->json(['results' => $rows]);
    }

    public function searchCustomers(Request $request): Response
    {
        $q = trim((string) $request->get('q', ''));
        $type = trim((string) $request->get('type', 'member'));

        if (mb_strlen($q) < 2) {
            return $this->json(['results' => []]);
        }

        $db = App::getInstance()->db();
        $search = '%' . $q . '%';

        if ($type === 'member') {
            $rows = $db->select(
                "SELECT `id`, `full_name_ar`, `form_number`, `membership_number`
                 FROM `members`
                 WHERE (`full_name_ar` LIKE ? OR `form_number` LIKE ? OR `membership_number` LIKE ?)
                   AND `is_archived` = 0
                 ORDER BY `full_name_ar` ASC LIMIT 20",
                [$search, $search, $search]
            );
        } else {
            $rows = $db->select(
                "SELECT `id`, `full_name_ar`, `player_code`
                 FROM `players`
                 WHERE (`full_name_ar` LIKE ? OR `player_code` LIKE ?)
                 ORDER BY `full_name_ar` ASC LIMIT 20",
                [$search, $search]
            );
        }

        return $this->json(['results' => $rows]);
    }
}
