<?php

namespace Modules\PurchaseRequisition\Http\Controllers;

use DB;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Modules\PurchaseRequisition\Entities\PrPurchaseShare;
use Modules\PurchaseRequisition\Entities\PrPurchaseChange;
use Modules\PurchaseRequisition\Entities\PrPurchasePayment;
use Modules\PurchaseRequisition\Entities\PrCurrency;
use Modules\PurchaseRequisition\Entities\PrRequest;
use Modules\PurchaseRequisition\Entities\PrProduct;
use Modules\PurchaseRequisition\Entities\PrSupplierProduct;
use App\Transaction;
use App\PurchaseLine;

class PrPurchaseController extends Controller
{
    public function index()
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');

        $shares = PrPurchaseShare::where('business_id', $businessId)
            ->with(['transaction.contact', 'transaction.location'])
            ->whereHas('transaction', function ($q) {
                $q->where('status', '!=', 'received');
            })
            ->latest()
            ->get();

        $allPrIds = $shares->flatMap(fn($s) => $s->pr_request_ids)->unique()->values()->all();
        $prRefMap  = PrRequest::whereIn('id', $allPrIds)->pluck('ref_no', 'id');

        $pendingCounts = PrPurchaseChange::where('status', 'pending')
            ->whereIn('pr_purchase_share_id', $shares->pluck('id'))
            ->groupBy('pr_purchase_share_id')
            ->selectRaw('pr_purchase_share_id, count(*) as cnt')
            ->pluck('cnt', 'pr_purchase_share_id');

        $currencies = PrCurrency::where('business_id', $businessId)->where('is_active', true)->get();

        $shareIds = $shares->pluck('id');

        // Payment totals per share
        $paymentTotals = PrPurchasePayment::whereIn('pr_purchase_share_id', $shareIds)
            ->selectRaw('pr_purchase_share_id, SUM(egp_amount) as total_egp, SUM(order_currency_amount) as total_order_currency')
            ->groupBy('pr_purchase_share_id')
            ->get()->keyBy('pr_purchase_share_id');

        // Determine order currency per share (from first purchase line's supplier product)
        $allTransactionIds = $shares->pluck('transaction_id');
        $allPurchaseLines  = PurchaseLine::whereIn('transaction_id', $allTransactionIds)
            ->whereNotNull('purchase_requisition_line_id')
            ->get()
            ->groupBy('transaction_id');

        $allPrProductIds = $allPurchaseLines->flatten()->pluck('purchase_requisition_line_id')->filter()->unique()->values();
        $supplierIdMap   = $shares->pluck('transaction.contact_id', 'id');

        $supplierProductsForIndex = PrSupplierProduct::whereIn('pr_product_id', $allPrProductIds)
            ->where('approved', true)
            ->with('supplierResponse.currency')
            ->get()
            ->groupBy('pr_product_id');

        $orderCurrencies = [];
        foreach ($shares as $share) {
            $txLines = $allPurchaseLines[$share->transaction_id] ?? collect();
            $orderCurrencies[$share->id] = ['id' => null, 'symbol' => 'EGP'];
            foreach ($txLines as $line) {
                $spList = $supplierProductsForIndex[$line->purchase_requisition_line_id] ?? collect();
                $sp = $spList->first(function ($s) use ($supplierIdMap, $share) {
                    return optional($s->supplierResponse)->supplier_id == ($supplierIdMap[$share->id] ?? null)
                        && optional($s->supplierResponse)->status === 'approved';
                });
                if ($sp) {
                    $currency = optional($sp->supplierResponse)->currency;
                    if ($currency) {
                        $orderCurrencies[$share->id] = ['id' => $currency->id, 'symbol' => $currency->symbol];
                    }
                    break;
                }
            }
        }

        return view('purchaseRequisition::purchase.index',
            compact('shares', 'prRefMap', 'pendingCounts', 'currencies', 'paymentTotals', 'orderCurrencies'));
    }

    public function show($token)
    {
        $share = PrPurchaseShare::where('share_token', $token)->firstOrFail();

        $lang = request('lang', 'en');
        app()->setLocale($lang);

        $transaction = $share->transaction()->with([
            'contact',
            'location',
            'purchase_lines.product',
            'purchase_lines.variations',
        ])->first();

        $prProductIds = $transaction->purchase_lines
            ->pluck('purchase_requisition_line_id')
            ->filter()
            ->unique()
            ->values();

        $prProducts = PrProduct::with(['product', 'variation'])
            ->whereIn('id', $prProductIds)
            ->get()
            ->keyBy('id');

        $supplierId = $transaction->contact_id;
        $supplierProducts = PrSupplierProduct::whereIn('pr_product_id', $prProductIds)
            ->where('approved', true)
            ->whereHas('supplierResponse', function ($q) use ($supplierId) {
                $q->where('supplier_id', $supplierId)
                  ->where('status', 'approved');
            })
            ->with('supplierResponse.currency')
            ->get()
            ->keyBy('pr_product_id');

        $items = [];
        foreach ($transaction->purchase_lines as $line) {
            $prProductId = $line->purchase_requisition_line_id;
            $items[] = [
                'line'             => $line,
                'pr_product'       => $prProducts[$prProductId] ?? null,
                'supplier_product' => $supplierProducts[$prProductId] ?? null,
            ];
        }

        $prRefNos = PrRequest::whereIn('id', $share->pr_request_ids)->pluck('ref_no')->all();

        $changes = PrPurchaseChange::where('pr_purchase_share_id', $share->id)
            ->orderBy('created_at')
            ->get()
            ->groupBy('purchase_line_id');

        $payments = $share->payments()->with(['paidCurrency', 'orderCurrency', 'createdBy'])->get();

        return view('purchaseRequisition::purchase.show',
            compact('share', 'transaction', 'items', 'prRefNos', 'changes', 'payments'));
    }

    public function saveNotes($token, Request $request)
    {
        $share = PrPurchaseShare::where('share_token', $token)->firstOrFail();

        $request->validate([
            'order_note'    => 'nullable|string|max:2000',
            'row_notes'     => 'nullable|array',
            'row_notes.*'   => 'nullable|string|max:500',
            'images'        => 'nullable|array',
            'images.*'      => 'image|max:5120',
        ]);

        $existingImages = $share->images ?? [];
        if ($request->hasFile('images')) {
            foreach ($request->file('images') as $file) {
                $path = $file->store('pr-purchase-images', 'public');
                $existingImages[] = $path;
            }
        }

        $share->update([
            'supplier_order_note' => $request->input('order_note'),
            'row_notes'           => $request->input('row_notes', []),
            'images'              => $existingImages,
        ]);

        return response()->json(['success' => true, 'message' => __('purchaseRequisition::lang.notes_saved')]);
    }

    public function requestChange($token, Request $request)
    {
        $share = PrPurchaseShare::where('share_token', $token)->firstOrFail();

        $request->validate([
            'purchase_line_id' => 'required|integer|exists:purchase_lines,id',
            'requested_qty'    => 'required|numeric|min:0',
            'requested_price'  => 'required|numeric|min:0',
            'supplier_note'    => 'nullable|string|max:1000',
        ]);

        $line = PurchaseLine::where('id', $request->purchase_line_id)
            ->where('transaction_id', $share->transaction_id)
            ->firstOrFail();

        PrPurchaseChange::updateOrCreate(
            [
                'pr_purchase_share_id' => $share->id,
                'purchase_line_id'     => $line->id,
                'status'               => 'pending',
            ],
            [
                'original_qty'    => $line->quantity,
                'original_price'  => $line->purchase_price,
                'requested_qty'   => $request->requested_qty,
                'requested_price' => $request->requested_price,
                'supplier_note'   => $request->supplier_note,
            ]
        );

        $changeRecord = PrPurchaseChange::where('pr_purchase_share_id', $share->id)
            ->where('purchase_line_id', $line->id)
            ->where('status', 'pending')
            ->first();

        // Resolve currency for the history display
        $currencySymbol        = '';
        $originalSupplierPrice = $changeRecord ? (float) $changeRecord->original_price : 0;
        if ($changeRecord && $line->purchase_requisition_line_id) {
            $supplierId = $share->transaction->contact_id ?? null;
            $sp = PrSupplierProduct::where('pr_product_id', $line->purchase_requisition_line_id)
                ->where('approved', true)
                ->whereHas('supplierResponse', function ($q) use ($supplierId) {
                    $q->where('supplier_id', $supplierId)->where('status', 'approved');
                })
                ->with('supplierResponse.currency')
                ->first();
            if ($sp) {
                $currency              = optional($sp->supplierResponse)->currency;
                $currencySymbol        = $currency ? $currency->symbol : '';
                $originalSupplierPrice = (float) $sp->supplier_price;
            }
        }

        return response()->json([
            'success' => true,
            'message' => __('purchaseRequisition::lang.change_submitted'),
            'change'  => $changeRecord ? [
                'id'                     => $changeRecord->id,
                'original_qty'           => $changeRecord->original_qty,
                'original_price'         => $changeRecord->original_price,
                'original_supplier_price' => $originalSupplierPrice,
                'requested_qty'          => $changeRecord->requested_qty,
                'requested_price'        => $changeRecord->requested_price,
                'requested_supplier_price' => (float) $changeRecord->requested_price,
                'currency_symbol'        => $currencySymbol,
                'supplier_note'          => $changeRecord->supplier_note,
                'status'                 => $changeRecord->status,
                'created_at'             => $changeRecord->created_at ? $changeRecord->created_at->format('Y-m-d H:i') : null,
            ] : null,
        ]);
    }

    public function getChanges($token)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share = PrPurchaseShare::where('share_token', $token)
            ->with('transaction')
            ->firstOrFail();

        $supplierId = $share->transaction->contact_id;

        $changes = PrPurchaseChange::where('pr_purchase_share_id', $share->id)
            ->with(['purchaseLine.product', 'purchaseLine.variations'])
            ->get()
            ->map(function ($change) use ($token, $supplierId) {
                $line      = $change->purchaseLine;
                $product   = $line ? $line->product : null;
                $variation = $line ? $line->variations : null;

                $varName = '';
                if ($product && $product->type == 'variable' && $variation
                    && !in_array(strtoupper(trim($variation->name ?? '')), ['DUMMY', ''])) {
                    $varName = ' ' . $variation->name;
                }

                // Load supplier price + currency for this line
                $currencySymbol       = 'EGP';
                $conversionRate       = 1;
                $originalSupplierPrice = $change->original_price; // fallback = EGP price

                if ($line && $line->purchase_requisition_line_id) {
                    $sp = PrSupplierProduct::where('pr_product_id', $line->purchase_requisition_line_id)
                        ->where('approved', true)
                        ->whereHas('supplierResponse', function ($q) use ($supplierId) {
                            $q->where('supplier_id', $supplierId)->where('status', 'approved');
                        })
                        ->with('supplierResponse.currency')
                        ->first();

                    if ($sp) {
                        $currency             = optional($sp->supplierResponse)->currency;
                        $currencySymbol       = $currency ? $currency->symbol : 'EGP';
                        $conversionRate       = $currency ? (float) $currency->conversion_rate_to_egp : 1;
                        $originalSupplierPrice = (float) $sp->supplier_price;
                    }
                }

                $originalEgpPrice  = round($originalSupplierPrice * $conversionRate, 4);
                $requestedEgpPrice = round((float) $change->requested_price * $conversionRate, 4);

                return [
                    'id'                    => $change->id,
                    'purchase_line_id'      => $change->purchase_line_id,
                    'product_name'          => $product ? ($product->name . $varName) : '-',
                    'sku'                   => $variation ? ($variation->sub_sku ?: ($product->sku ?? '-')) : ($product->sku ?? '-'),
                    'currency_symbol'       => $currencySymbol,
                    'conversion_rate'       => $conversionRate,
                    'original_qty'          => $change->original_qty,
                    'original_supplier_price' => $originalSupplierPrice,
                    'original_egp_price'    => $originalEgpPrice,
                    'requested_qty'         => $change->requested_qty,
                    'requested_supplier_price' => (float) $change->requested_price,
                    'requested_egp_price'   => $requestedEgpPrice,
                    'supplier_note'         => $change->supplier_note,
                    'status'                => $change->status,
                    'admin_note'            => $change->admin_note,
                    'approve_url'           => route('pr.purchases.approveChange', ['token' => $token, 'change' => $change->id]),
                    'reject_url'            => route('pr.purchases.rejectChange',  ['token' => $token, 'change' => $change->id]),
                    'delete_url'            => route('pr.purchases.deleteChangeLine', ['token' => $token, 'change' => $change->id]),
                ];
            });

        return response()->json(['changes' => $changes, 'share_token' => $token]);
    }

    public function approveChange($token, $changeId, Request $request)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share  = PrPurchaseShare::where('share_token', $token)->with('transaction')->firstOrFail();
        $change = PrPurchaseChange::where('id', $changeId)
            ->where('pr_purchase_share_id', $share->id)
            ->firstOrFail();

        $finalQty = $request->input('admin_qty', $change->requested_qty);

        // admin_price arrives in supplier currency — convert to EGP
        $adminPriceSupplier = (float) $request->input('admin_price', $change->requested_price);
        $conversionRate = 1;
        $supplierId = $share->transaction->contact_id ?? null;
        $line = PurchaseLine::findOrFail($change->purchase_line_id);
        if ($line->purchase_requisition_line_id && $supplierId) {
            $sp = \Modules\PurchaseRequisition\Entities\PrSupplierProduct::where('pr_product_id', $line->purchase_requisition_line_id)
                ->where('approved', true)
                ->whereHas('supplierResponse', function ($q) use ($supplierId) {
                    $q->where('supplier_id', $supplierId)->where('status', 'approved');
                })
                ->with('supplierResponse.currency')
                ->first();
            if ($sp) {
                $currency = optional($sp->supplierResponse)->currency;
                $conversionRate = $currency ? (float) $currency->conversion_rate_to_egp : 1;
            }
        }
        $finalPrice = round($adminPriceSupplier * $conversionRate, 4);
        $line->update([
            'quantity'               => $finalQty,
            'purchase_price'         => $finalPrice,
            'pp_without_discount'    => $finalPrice,
            'purchase_price_inc_tax' => $finalPrice,
        ]);

        $this->recalculateTransactionTotal($share->transaction_id);

        $change->update([
            'status'         => 'approved',
            'admin_note'     => $request->input('admin_note'),
            'requested_qty'  => $finalQty,
            'requested_price' => $adminPriceSupplier, // stored in supplier currency
        ]);

        return response()->json(['success' => true, 'message' => __('purchaseRequisition::lang.change_approved')]);
    }

    public function rejectChange($token, $changeId, Request $request)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share  = PrPurchaseShare::where('share_token', $token)->firstOrFail();
        $change = PrPurchaseChange::where('id', $changeId)
            ->where('pr_purchase_share_id', $share->id)
            ->firstOrFail();

        $change->update(['status' => 'rejected', 'admin_note' => $request->input('admin_note')]);

        return response()->json(['success' => true, 'message' => __('purchaseRequisition::lang.change_rejected')]);
    }

    public function deleteChangeLine($token, $changeId)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share  = PrPurchaseShare::where('share_token', $token)->firstOrFail();
        $change = PrPurchaseChange::where('id', $changeId)
            ->where('pr_purchase_share_id', $share->id)
            ->firstOrFail();

        $lineId = $change->purchase_line_id;
        $change->delete();
        PurchaseLine::where('id', $lineId)->delete();

        $this->recalculateTransactionTotal($share->transaction_id);

        return response()->json(['success' => true, 'message' => __('purchaseRequisition::lang.line_deleted')]);
    }

    // ─── Payment Methods ──────────────────────────────────────────────────────

    public function getPayments($token)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share    = PrPurchaseShare::where('share_token', $token)->firstOrFail();
        $payments = $share->payments()->with(['paidCurrency', 'orderCurrency', 'createdBy'])->get();

        $data = $payments->map(function ($p) {
            return [
                'id'                      => $p->id,
                'paid_amount'             => $p->paid_amount,
                'paid_currency_id'        => $p->paid_currency_id,
                'paid_currency_symbol'    => $p->paidCurrency ? $p->paidCurrency->symbol : 'EGP',
                'rate_to_egp'             => $p->rate_to_egp,
                'egp_amount'              => $p->egp_amount,
                'order_currency_amount'   => $p->order_currency_amount,
                'order_currency_symbol'   => $p->orderCurrency ? $p->orderCurrency->symbol : 'EGP',
                'rate_to_order_currency'  => $p->rate_to_order_currency,
                'notes'                   => $p->notes,
                'document_url'            => $p->document ? asset('storage/' . $p->document) : null,
                'received'                => $p->received,
                'created_by'              => $p->createdBy ? $p->createdBy->first_name . ' ' . $p->createdBy->last_name : '-',
                'created_at'              => $p->created_at ? $p->created_at->format('Y-m-d H:i') : '-',
            ];
        });

        return response()->json(['payments' => $data]);
    }

    public function storePayment($token, Request $request)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share = PrPurchaseShare::where('share_token', $token)->firstOrFail();

        // Treat "egp" sentinel as null (native EGP — no currency record)
        $paidCurrencyId  = ($request->paid_currency_id === 'egp' || !$request->paid_currency_id) ? null : $request->paid_currency_id;
        $orderCurrencyId = ($request->order_currency_id === 'egp' || !$request->order_currency_id) ? null : $request->order_currency_id;

        $request->validate([
            'paid_amount'            => 'required|numeric|min:0.0001',
            'rate_to_egp'            => 'required|numeric|min:0.0001',
            'rate_to_order_currency' => 'required|numeric|min:0.0001',
            'notes'                  => 'nullable|string|max:2000',
            'document'               => 'nullable|file|mimes:jpg,jpeg,png,gif,webp|max:5120',
        ]);

        if ($paidCurrencyId && !\DB::table('pr_currencies')->where('id', $paidCurrencyId)->exists()) {
            return response()->json(['message' => 'Invalid paid currency.'], 422);
        }
        if ($orderCurrencyId && !\DB::table('pr_currencies')->where('id', $orderCurrencyId)->exists()) {
            return response()->json(['message' => 'Invalid order currency.'], 422);
        }

        // Deep image validation using getimagesize()
        $documentPath = null;
        if ($request->hasFile('document') && $request->file('document')->isValid()) {
            $tmpPath = $request->file('document')->getRealPath();
            if (!@getimagesize($tmpPath)) {
                return response()->json(['message' => __('purchaseRequisition::lang.invalid_image_file')], 422);
            }
            $documentPath = $request->file('document')->store('pr_payments', 'public');
        }

        $paidAmount          = (float) $request->paid_amount;
        $rateToEgp           = $paidCurrencyId ? (float) $request->rate_to_egp : 1;
        $rateToOrderCurrency = ($orderCurrencyId && $orderCurrencyId !== $paidCurrencyId) ? (float) $request->rate_to_order_currency : 1;

        $payment = PrPurchasePayment::create([
            'pr_purchase_share_id'   => $share->id,
            'paid_amount'            => $paidAmount,
            'paid_currency_id'       => $paidCurrencyId,
            'rate_to_egp'            => $rateToEgp,
            'egp_amount'             => round($paidAmount * $rateToEgp, 4),
            'order_currency_id'      => $orderCurrencyId,
            'rate_to_order_currency' => $rateToOrderCurrency,
            'order_currency_amount'  => round($paidAmount * $rateToOrderCurrency, 4),
            'notes'                  => $request->notes,
            'document'               => $documentPath,
            'created_by'             => auth()->id(),
        ]);

        $payment->load(['paidCurrency', 'orderCurrency', 'createdBy']);

        return response()->json([
            'success' => true,
            'message' => __('purchaseRequisition::lang.payment_recorded'),
            'payment' => [
                'id'                     => $payment->id,
                'paid_amount'            => $payment->paid_amount,
                'paid_currency_id'       => $payment->paid_currency_id,
                'paid_currency_symbol'   => $payment->paidCurrency ? $payment->paidCurrency->symbol : 'EGP',
                'rate_to_egp'            => $payment->rate_to_egp,
                'egp_amount'             => $payment->egp_amount,
                'order_currency_amount'  => $payment->order_currency_amount,
                'order_currency_symbol'  => $payment->orderCurrency ? $payment->orderCurrency->symbol : 'EGP',
                'rate_to_order_currency' => $payment->rate_to_order_currency,
                'notes'                  => $payment->notes,
                'document_url'           => $documentPath ? asset('storage/' . $documentPath) : null,
                'received'               => false,
                'created_by'             => $payment->createdBy ? $payment->createdBy->first_name . ' ' . $payment->createdBy->last_name : '-',
                'created_at'             => $payment->created_at->format('Y-m-d H:i'),
            ],
        ]);
    }

    public function updatePayment($token, $paymentId, Request $request)
    {
        if (!auth()->user()->can('purchase_requisition.make_purchase') &&
            !auth()->user()->can('purchase_requisition.view_all')) {
            abort(403);
        }

        $share   = PrPurchaseShare::where('share_token', $token)->firstOrFail();
        $payment = PrPurchasePayment::where('id', $paymentId)
            ->where('pr_purchase_share_id', $share->id)
            ->firstOrFail();

        $paidCurrencyId  = ($request->paid_currency_id === 'egp' || !$request->paid_currency_id) ? null : $request->paid_currency_id;
        $orderCurrencyId = ($request->order_currency_id === 'egp' || !$request->order_currency_id) ? null : $request->order_currency_id;

        $request->validate([
            'paid_amount'            => 'required|numeric|min:0.0001',
            'rate_to_egp'            => 'required|numeric|min:0.0001',
            'rate_to_order_currency' => 'required|numeric|min:0.0001',
            'notes'                  => 'nullable|string|max:2000',
            'document'               => 'nullable|file|mimes:jpg,jpeg,png,gif,webp|max:5120',
        ]);

        if ($paidCurrencyId && !\DB::table('pr_currencies')->where('id', $paidCurrencyId)->exists()) {
            return response()->json(['message' => 'Invalid paid currency.'], 422);
        }

        $documentPath = $payment->document;
        if ($request->hasFile('document') && $request->file('document')->isValid()) {
            $tmpPath = $request->file('document')->getRealPath();
            if (!@getimagesize($tmpPath)) {
                return response()->json(['message' => __('purchaseRequisition::lang.invalid_image_file')], 422);
            }
            $documentPath = $request->file('document')->store('pr_payments', 'public');
        }

        $paidAmount          = (float) $request->paid_amount;
        $rateToEgp           = $paidCurrencyId ? (float) $request->rate_to_egp : 1;
        $rateToOrderCurrency = ($orderCurrencyId && $orderCurrencyId !== $paidCurrencyId) ? (float) $request->rate_to_order_currency : 1;

        $payment->update([
            'paid_amount'            => $paidAmount,
            'paid_currency_id'       => $paidCurrencyId,
            'rate_to_egp'            => $rateToEgp,
            'egp_amount'             => round($paidAmount * $rateToEgp, 4),
            'order_currency_id'      => $orderCurrencyId,
            'rate_to_order_currency' => $rateToOrderCurrency,
            'order_currency_amount'  => round($paidAmount * $rateToOrderCurrency, 4),
            'notes'                  => $request->notes,
            'document'               => $documentPath,
        ]);

        $payment->load(['paidCurrency', 'orderCurrency', 'createdBy']);

        return response()->json([
            'success' => true,
            'message' => __('purchaseRequisition::lang.payment_updated'),
            'payment' => [
                'id'                    => $payment->id,
                'paid_amount'           => $payment->paid_amount,
                'paid_currency_id'      => $payment->paid_currency_id,
                'paid_currency_symbol'  => $payment->paidCurrency ? $payment->paidCurrency->symbol : 'EGP',
                'egp_amount'            => $payment->egp_amount,
                'order_currency_amount' => $payment->order_currency_amount,
                'order_currency_symbol' => $payment->orderCurrency ? $payment->orderCurrency->symbol : 'EGP',
                'notes'                 => $payment->notes,
                'document_url'          => $documentPath ? asset('storage/' . $documentPath) : null,
                'received'              => $payment->received,
                'created_by'            => $payment->createdBy ? $payment->createdBy->first_name . ' ' . $payment->createdBy->last_name : '-',
                'created_at'            => $payment->created_at->format('Y-m-d H:i'),
            ],
        ]);
    }

    public function markReceived($token, $paymentId, Request $request)
    {
        $share   = PrPurchaseShare::where('share_token', $token)->firstOrFail();
        $payment = PrPurchasePayment::where('id', $paymentId)
            ->where('pr_purchase_share_id', $share->id)
            ->firstOrFail();

        $request->validate([
            'received'      => 'required|boolean',
            'received_note' => 'nullable|string|max:2000',
        ]);

        $received = (bool) $request->received;
        $payment->update([
            'received'      => $received,
            'received_note' => $request->received_note,
            'received_at'   => $received ? now() : null,
        ]);

        return response()->json(['success' => true, 'message' => __('purchaseRequisition::lang.received_updated')]);
    }

    // ─────────────────────────────────────────────────────────────────────────

    protected function recalculateTransactionTotal($transactionId)
    {
        $total = PurchaseLine::where('transaction_id', $transactionId)
            ->selectRaw('SUM(quantity * purchase_price_inc_tax) as total')
            ->value('total') ?? 0;

        Transaction::where('id', $transactionId)->update([
            'total_before_tax' => $total,
            'final_total'      => $total,
        ]);
    }
}
