<?php
// ============================================================
//  MJPOS – PurchaseReturnController
// ============================================================

class PurchaseReturnController extends Controller
{
    public function create(string $id): void
    {
        Auth::requirePermission('purchases.edit');

        $purchase = Database::fetchOne(
            "SELECT p.*, s.supplier_name
             FROM purchases p
             JOIN suppliers s ON s.id = p.supplier_id
             WHERE p.id = ? AND p.status = 'received'",
            [(int)$id]
        );

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

        $items = Database::fetchAll(
            'SELECT pi.*, pr.product_name, pr.product_code
             FROM purchase_items pi
             JOIN products pr ON pr.id = pi.product_id
             WHERE pi.purchase_id = ?',
            [(int)$id]
        );

        $pageTitle  = 'Return – ' . $purchase['invoice_no'];
        $breadcrumb = [
            ['label' => 'Purchases',   'url' => APP_URL . '/purchases'],
            ['label' => 'View',        'url' => APP_URL . '/purchases/view/' . $id],
            ['label' => 'Return'],
        ];
        ob_start();
        require APP_PATH . '/views/purchases/return.php';
        $content = ob_get_clean();
        require APP_PATH . '/views/layouts/main.php';
    }

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

        $purchase = Database::fetchOne(
            "SELECT * FROM purchases WHERE id = ? AND status = 'received'",
            [(int)$id]
        );
        if (!$purchase) {
            $this->flash('error', 'Purchase not found.');
            $this->redirect(APP_URL . '/purchases');
            return;
        }

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

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

        // Validate items and quantities
        foreach ($retItems 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 ($retItems as $item) {
            $total += (float)$item['quantity'] * (float)$item['cost_price'];
        }
        $total = round($total, 2);

        $retNo = $this->generateInvoiceNo('PRET', 'purchase_returns');

        Database::beginTransaction();
        try {
            // 1. Insert return header
            $retId = (int) Database::insert(
                'INSERT INTO purchase_returns
                 (purchase_id, supplier_id, invoice_no, return_date, total, note, created_by)
                 VALUES (?, ?, ?, CURDATE(), ?, ?, ?)',
                [(int)$id, (int)$purchase['supplier_id'], $retNo, $total, $note, Auth::id()]
            );

            // 2. Process each return item
            foreach ($retItems as $item) {
                $productId = (int)   $item['product_id'];
                $qty       = (float) $item['quantity'];
                $cost      = (float) $item['cost_price'];
                $lineTotal = round($qty * $cost, 2);
                $reason    = trim($item['reason'] ?? '');

                Database::execute(
                    'INSERT INTO purchase_return_items
                     (purchase_return_id, product_id, quantity, cost_price, total, reason)
                     VALUES (?, ?, ?, ?, ?, ?)',
                    [$retId, $productId, $qty, $cost, $lineTotal, $reason]
                );

                // Reduce stock (items back to supplier)
                Database::execute(
                    'UPDATE products SET current_stock = GREATEST(0, current_stock - ?) WHERE id = ?',
                    [$qty, $productId]
                );

                // Stock movement — use single-quoted literals (no ANSI_QUOTES issue)
                $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 (?, ?, ?, ?, ?, ?, ?, ?)',
                    [$productId, 'purchase_return', 0, $qty, $newStock,
                     $retNo, 'Purchase Return: ' . $retNo, Auth::id()]
                );
            }

            // 3. Reduce purchase paid/adjust balance
            // Return reduces what we owe the supplier
            $newPaid    = round(max(0, (float)$purchase['paid']    - $total), 2);
            $newBalance = round(max(0, (float)$purchase['balance'] - $total), 2);

            // If balance was already 0 (fully paid), return amount refunds from paid
            if ((float)$purchase['balance'] <= 0) {
                $newPaid    = round(max(0, (float)$purchase['paid'] - $total), 2);
                $newBalance = 0;
            }

            $newPmtStatus = $newPaid <= 0 && $newBalance > 0
                ? 'due'
                : ($newBalance <= 0 ? 'paid' : 'partial');

            Database::execute(
                'UPDATE purchases SET paid = ?, balance = ?, payment_status = ? WHERE id = ?',
                [$newPaid, $newBalance, $newPmtStatus, (int)$id]
            );

            // 4. Reduce supplier outstanding balance
            Database::execute(
                'UPDATE suppliers SET current_balance = GREATEST(0, current_balance - ?) WHERE id = ?',
                [$total, (int)$purchase['supplier_id']]
            );

            Database::commit();

            Auth::logAudit(Auth::id(), 'purchase_return', 'purchases',
                "Return {$retNo} for {$purchase['invoice_no']}, total: {$total}, refund: {$refundMethod}");

            redirectWith(
                APP_URL . '/purchases/view/' . $id,
                'success',
                "Return {$retNo} processed. {$total} refund via " . ucfirst(str_replace('_', ' ', $refundMethod)) . '.'
            );

        } catch (Exception $e) {
            Database::rollback();
            redirectWith(APP_URL . '/purchases/view/' . $id, 'error', 'Return failed: ' . $e->getMessage());
        }
    }
}
