<?php
// ============================================================
//  MJPOS – SaleReturnController
// ============================================================

class SaleReturnController extends Controller
{
    public function create(string $id): void
    {
        Auth::requirePermission('sales.return');

        $sale = Database::fetchOne(
            "SELECT s.*, COALESCE(c.customer_name,'Walk-in') AS customer_name
             FROM sales s
             LEFT JOIN customers c ON c.id = s.customer_id
             WHERE s.id = ? AND s.status = 'completed'",
            [(int)$id]
        );

        if (!$sale) {
            $this->flash('error', 'Sale not found or cannot be returned.');
            $this->redirect(APP_URL . '/sales');
            return;
        }

        $items = Database::fetchAll(
            'SELECT si.*, p.product_name, p.product_code
             FROM sale_items si
             JOIN products p ON p.id = si.product_id
             WHERE si.sale_id = ?',
            [(int)$id]
        );

        // Already-returned quantities per product so user can't over-return
        $alreadyReturned = Database::fetchAll(
            'SELECT sri.product_id, SUM(sri.quantity) AS returned_qty
             FROM sales_return_items sri
             JOIN sales_returns sr ON sr.id = sri.sales_return_id
             WHERE sr.sale_id = ?
             GROUP BY sri.product_id',
            [(int)$id]
        );
        $returnedMap = array_column($alreadyReturned, 'returned_qty', 'product_id');

        $pageTitle  = 'Return – ' . $sale['invoice_no'];
        $breadcrumb = [
            ['label' => 'Sales', 'url' => APP_URL . '/sales'],
            ['label' => 'Return'],
        ];
        ob_start();
        require APP_PATH . '/views/sales/return.php';
        $content = ob_get_clean();
        require APP_PATH . '/views/layouts/main.php';
    }

    public function store(string $id): void
    {
        Auth::requirePermission('sales.return');
        Auth::requireCsrf();

        $sale = Database::fetchOne(
            "SELECT * FROM sales WHERE id = ? AND status = 'completed'",
            [(int)$id]
        );
        if (!$sale) {
            $this->flash('error', 'Sale not found or already fully returned.');
            $this->redirect(APP_URL . '/sales');
            return;
        }

        $returnItems  = json_decode($this->post('items_json', '[]'), true);
        $refundMethod = $this->post('refund_method', 'cash');
        $note         = trim($this->post('note', ''));

        if (empty($returnItems) || !is_array($returnItems)) {
            $this->flash('error', 'No items selected for return.');
            $this->back();
            return;
        }

        // Validate each item has a valid product_id and quantity
        foreach ($returnItems as $item) {
            if (empty($item['product_id']) || (float)($item['quantity'] ?? 0) <= 0) {
                $this->flash('error', 'Invalid return data. Please try again.');
                $this->back();
                return;
            }
        }

        $total = 0;
        foreach ($returnItems as $item) {
            $total += (float)$item['quantity'] * (float)$item['selling_price'];
        }

        $retNo = $this->generateInvoiceNo(setting('return_prefix', 'RET'), 'sales_returns');

        Database::beginTransaction();
        try {
            // 1. Insert return header
            $retId = (int) Database::insert(
                'INSERT INTO sales_returns
                 (sale_id, customer_id, invoice_no, return_date, total, refund_method, note, created_by)
                 VALUES (?, ?, ?, CURDATE(), ?, ?, ?, ?)',
                [
                    (int)$id,
                    $sale['customer_id'],
                    $retNo,
                    round($total, 2),
                    $refundMethod,
                    $note,
                    Auth::id(),
                ]
            );

            // 2. Process each returned item
            foreach ($returnItems as $item) {
                $productId = (int) $item['product_id'];
                $qty       = (float) $item['quantity'];
                $price     = (float) $item['selling_price'];
                $lineTotal = round($qty * $price, 2);
                $reason    = trim($item['reason'] ?? '');

                // Insert return item record
                Database::execute(
                    'INSERT INTO sales_return_items
                     (sales_return_id, product_id, quantity, selling_price, total, reason)
                     VALUES (?, ?, ?, ?, ?, ?)',
                    [$retId, $productId, $qty, $price, $lineTotal, $reason]
                );

                // Increase stock
                Database::execute(
                    'UPDATE products SET current_stock = current_stock + ? WHERE id = ?',
                    [$qty, $productId]
                );

                // Record stock movement
                $newStock = (float) Database::fetchColumn(
                    'SELECT current_stock FROM products WHERE id = ?',
                    [$productId]
                );
                Database::execute(
                    'INSERT INTO stock_movements
                     (product_id, movement_type, quantity_in, quantity_out, stock_after, reference_no, note, created_by)
                     VALUES (?, "sale_return", ?, 0, ?, ?, ?, ?)',
                    [$productId, $qty, $newStock, $retNo, "Sale Return: {$retNo}", Auth::id()]
                );
            }

            // 3. Reduce customer balance if credit sale
            if ($sale['customer_id'] && $total > 0) {
                Database::execute(
                    'UPDATE customers SET current_balance = GREATEST(0, current_balance - ?) WHERE id = ?',
                    [round($total, 2), (int)$sale['customer_id']]
                );
            }

            // 3b. Debit the linked finance account for the refund
            // The refund method tells us which account loses money
            if ($total > 0) {
                $settingKey = 'pmt_account_' . $refundMethod;
                $acctId     = (int)(setting($settingKey, '') ?: 0);

                if ($acctId > 0) {
                    $acct = Database::fetchOne(
                        'SELECT id, current_balance FROM finance_accounts WHERE id=? AND status="active"',
                        [$acctId]
                    );
                    if ($acct) {
                        $newBal = round(max(0, (float)$acct['current_balance'] - $total), 2);
                        Database::execute(
                            'UPDATE finance_accounts SET current_balance=? WHERE id=?',
                            [$newBal, $acctId]
                        );
                        Database::execute(
                            'INSERT INTO finance_transactions
                             (account_id, txn_type, amount, balance_after, reference, note, txn_date, created_by)
                             VALUES (?,?,?,?,?,?,NOW(),?)',
                            [$acctId, 'withdrawal', $total, $newBal,
                             $retNo,
                             'Sale Return: ' . $retNo . ' (Ref: ' . $sale['invoice_no'] . ')',
                             Auth::id()]
                        );
                    }
                }
            }

            // 4. Mark sale as returned
            Database::execute(
                "UPDATE sales SET status = 'returned' WHERE id = ?",
                [(int)$id]
            );

            Database::commit();

            Auth::logAudit(Auth::id(), 'sale_return', 'sales',
                "Return {$retNo} for sale ID {$id}, total: {$total}");

            redirectWith(
                APP_URL . '/sales/view/' . $id,
                'success',
                "Return {$retNo} processed successfully. Stock updated."
            );

        } catch (Exception $e) {
            Database::rollback();
            $this->flash('error', 'Return failed: ' . $e->getMessage());
            $this->back();
        }
    }
}