<?php

namespace Modules\PurchaseRequisition\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\PurchaseRequisition\Entities\PrRequest;
use Modules\PurchaseRequisition\Entities\PrSupplierProduct;
use Modules\PurchaseRequisition\Entities\PrSetting;
use Modules\PurchaseRequisition\Entities\Services\CalculationService;
use Yajra\DataTables\Facades\DataTables;
use DB;

class PrApprovalController extends Controller
{
    protected $calculationService;

    public function __construct(CalculationService $calculationService)
    {
        $this->calculationService = $calculationService;
    }

    /**
     * Display approval page.
     *
     * @param int $id
     * @return \Illuminate\View\View
     */
    public function index($id)
    {
        if (!auth()->user()->can('purchase_requisition.approve')) {
            abort(403, 'Unauthorized action.');
        }

        $prRequest = PrRequest::with([
                'products.product',
                'products.variation',
                'supplierResponses.supplier',
                'supplierResponses.currency'
            ])
            ->findOrFail($id);

        $businessId = request()->session()->get('user.business_id');
        $settings = PrSetting::getSettings($businessId);

        // Get specific supplier response if response_id is provided
        $responseId = request()->get('response_id');
        $supplierResponse = null;
        if ($responseId) {
            $supplierResponse = $prRequest->supplierResponses->where('id', $responseId)->first();
        }

        // Check if status allows viewing
        // Allow if: PR status is pending_approval/approved/completed OR specific supplier response is submitted/approved
        $allowedPrStatuses = ['pending_approval', 'approved', 'completed'];
        $hasViewableResponse = false;

        if ($supplierResponse && in_array($supplierResponse->status, ['submitted', 'approved'])) {
            $hasViewableResponse = true;
        }

        if (!in_array($prRequest->status, $allowedPrStatuses) && !$hasViewableResponse) {
            return redirect()->back()->with('status', [
                'success' => 0,
                'msg' => 'This requisition is not available for viewing.'
            ]);
        }

        return view('purchaseRequisition::approval.index', compact('prRequest', 'settings', 'responseId', 'supplierResponse'));
    }

    /**
     * Get products for approval DataTable.
     *
     * @param Request $request
     * @param int $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function getProducts(Request $request, $id)
    {
        if (!auth()->user()->can('purchase_requisition.approve')) {
            abort(403, 'Unauthorized action.');
        }

        if ($request->ajax()) {
            $businessId = request()->session()->get('user.business_id');
            $settings = PrSetting::getSettings($businessId);

            $prRequest = PrRequest::findOrFail($id);
            $responseId = $request->get('response_id');

            // Get supplier products with joins (filter out zero available_qty)
            $query = PrSupplierProduct::with([
                    'prProduct.product.brand',
                    'prProduct.product.category',
                    'prProduct.product.sub_category',
                    'prProduct.variation',
                    'supplierResponse.supplier',
                    'supplierResponse.currency'
                ])
                ->whereHas('supplierResponse', function ($q) use ($id, $responseId) {
                    $q->where('pr_request_id', $id)
                      ->whereIn('status', ['submitted', 'approved']);
                    // Filter by specific supplier response if provided
                    if ($responseId) {
                        $q->where('id', $responseId);
                    }
                })
                ->where('available_qty', '>', 0)
                ->select('pr_supplier_products.*');

            return DataTables::of($query)
                ->addColumn('supplier_name', function ($row) {
                    $supplier = $row->supplierResponse->supplier;
                    return $supplier ? ($supplier->name ?: $supplier->supplier_business_name ?: '-') : '-';
                })
                ->addColumn('product_name', function ($row) {
                    $product = $row->prProduct->product;
                    $variation = $row->prProduct->variation;
                    $variationName = ($product->type == 'variable' && $variation && !in_array(strtoupper(trim($variation->name)), ['DUMMY', ''])) ? ' ' . $variation->name : '';
                    $productName = $product->name . $variationName;

                    $brand     = $product->brand->name     ?? null;
                    $category  = $product->category->name  ?? null;
                    $subCat    = $product->sub_category->name ?? null;

                    $meta = implode(' &bull; ', array_filter([$brand, $category, $subCat]));
                    $subRow = $meta ? '<br><small class="text-muted">' . $meta . '</small>' : '';

                    return '<a href="#" class="product-link" data-product-id="' . $product->id . '">' . $productName . '</a>' . $subRow;
                })
                ->addColumn('sku', function ($row) {
                    $product = $row->prProduct->product;
                    $variation = $row->prProduct->variation;
                    return $variation->sub_sku ?: $product->sku;
                })
                ->addColumn('product_custom_field4', function ($row) {
                    $extraPart = $row->prProduct->product->product_custom_field4 ?? '-';
                    if ($extraPart && $extraPart !== '-') {
                        $triggerClass = strlen($extraPart) > 15 ? 'extra-part-trigger' : '';
                        return '<span class="extra-part-cell ' . $triggerClass . '" title="' . htmlspecialchars($extraPart) . '">' . $extraPart . '</span>';
                    }
                    return $extraPart;
                })
                ->addColumn('product_image', function ($row) {
                    $product = $row->prProduct->product;
                    if (!empty($product->image)) {
                        $imageUrl = $product->image_url ?? asset('img/default.png');
                        return '<img src="' . $imageUrl . '" class="product-thumb" alt="Product">';
                    }
                    return '-';
                })
                ->addColumn('pr_product_notes', function ($row) {
                    return $row->prProduct->notes ?? '-';
                })
                ->addColumn('current_stock', function ($row) {
                    return number_format($row->prProduct->current_stock, 2);
                })
                ->addColumn('required_quantity', function ($row) {
                    return number_format($row->prProduct->required_quantity, 2);
                })
                ->addColumn('avg_unit_cost', function ($row) {
                    return number_format($row->prProduct->avg_unit_cost, 2);
                })
                ->addColumn('last_purchase_price', function ($row) {
                    return number_format($row->prProduct->last_purchase_price, 2);
                })
                ->addColumn('last_purchased_qty', function ($row) {
                    return number_format($row->prProduct->last_purchased_qty ?? 0, 2);
                })
                ->addColumn('last_purchased_adjusted_qty', function ($row) {
                    return number_format($row->prProduct->last_purchased_adjusted_qty ?? 0, 2);
                })
                ->addColumn('year_ago_sold_qty', function ($row) {
                    return number_format($row->prProduct->year_ago_sold_qty ?? 0, 2);
                })
                ->addColumn('selling_price', function ($row) {
                    return number_format($row->prProduct->selling_price, 2);
                })
                ->addColumn('available_qty', function ($row) {
                    return number_format($row->available_qty, 2);
                })
                ->addColumn('order_qty', function ($row) {
                    $defaultQty = $row->order_qty > 0 ? $row->order_qty : $row->available_qty;
                    $displayQty = rtrim(rtrim(number_format((float)$defaultQty, 2, '.', ''), '0'), '.');
                    $maxQty = rtrim(rtrim(number_format((float)$row->available_qty, 2, '.', ''), '0'), '.');
                    return '<input type="number" class="form-control input-sm order-qty-input" data-id="' . $row->id . '" data-max="' . $maxQty . '" value="' . $displayQty . '" min="0" max="' . $maxQty . '" step="1">';
                })
                ->addColumn('supplier_price', function ($row) {
                    $currency = $row->supplierResponse->currency;
                    $symbol = $currency ? $currency->symbol : '';
                    return $symbol . ' ' . number_format($row->supplier_price, 2);
                })
                ->addColumn('supplier_notes', function ($row) {
                    return $row->supplier_notes ?? '-';
                })
                ->addColumn('converted_price_egp', function ($row) {
                    $currency = $row->supplierResponse->currency;
                    $highlight = $currency && $currency->code != 'EGP' ? 'background-color: #FFF3CD;' : '';
                    return '<span style="' . $highlight . '">EGP ' . number_format($row->converted_price_egp, 2) . '</span>';
                })
                ->addColumn('margin', function ($row) use ($settings) {
                    $margin = $this->calculationService->calculateMargin(
                        $row->prProduct->selling_price,
                        $row->converted_price_egp
                    );

                    $color = $margin < $settings['margin_ratio'] ? 'color: red;' : '';
                    return '<span style="' . $color . '">' . number_format($margin, 2) . '%</span>';
                })
                ->addColumn('approve_checkbox', function ($row) {
                    $checked = $row->approved ? 'checked' : '';
                    return '<input type="checkbox" class="approve-product" data-id="' . $row->id . '" ' . $checked . '>';
                })
                ->setRowAttr([
                    'data-id' => function ($row) {
                        return $row->id;
                    },
                    'style' => function ($row) use ($settings) {
                        $margin = $this->calculationService->calculateMargin(
                            $row->prProduct->selling_price,
                            $row->converted_price_egp
                        );

                        if ($margin < $settings['margin_ratio']) {
                            return 'background-color: ' . $settings['bg_color_low_margin'] . ';';
                        }

                        return '';
                    }
                ])
                ->rawColumns(['product_name', 'product_custom_field4', 'product_image', 'converted_price_egp', 'margin', 'approve_checkbox', 'order_qty'])
                ->make(true);
        }
    }

    /**
     * Side-by-side supplier comparison page.
     *
     * @param int $id
     * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
     */
    public function compare($id)
    {
        if (!auth()->user()->can('purchase_requisition.approve')) {
            abort(403, 'Unauthorized action.');
        }

        $prRequest = PrRequest::with([
                'products.product.brand',
                'products.product.category',
                'products.product.sub_category',
                'products.variation',
            ])
            ->findOrFail($id);

        $businessId = request()->session()->get('user.business_id');
        $settings = PrSetting::getSettings($businessId);

        // Load submitted supplier responses
        $responses = $prRequest->supplierResponses()
            ->whereIn('status', ['submitted', 'approved'])
            ->with(['supplier', 'currency', 'supplierProducts'])
            ->get();

        if ($responses->count() < 2) {
            $single = $responses->first();
            $url = action([self::class, 'index'], ['id' => $id]);
            if ($single) {
                $url .= '?response_id=' . $single->id;
            }
            return redirect($url);
        }

        // Build products × suppliers matrix (only rows with at least one available offer)
        $matrix = [];
        foreach ($prRequest->products as $prProduct) {
            $responseData = [];
            $hasAnyAvailable = false;

            foreach ($responses as $response) {
                $sp = $response->supplierProducts
                    ->where('pr_product_id', $prProduct->id)
                    ->where('available_qty', '>', 0)
                    ->first();

                if ($sp) {
                    $sp->computed_margin = $this->calculationService->calculateMargin(
                        $prProduct->selling_price ?? 0,
                        $sp->converted_price_egp
                    );
                    $hasAnyAvailable = true;
                }
                $responseData[$response->id] = $sp;
            }

            if ($hasAnyAvailable) {
                $matrix[] = [
                    'pr_product' => $prProduct,
                    'responses' => $responseData,
                ];
            }
        }

        return view('purchaseRequisition::approval.compare',
            compact('prRequest', 'responses', 'matrix', 'settings'));
    }

    /**
     * Submit approval.
     *
     * @param Request $request
     * @param int $id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function approve(Request $request, $id)
    {
        if (!auth()->user()->can('purchase_requisition.approve')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate([
            'approved_products' => 'required|array',
            'approved_products.*' => 'exists:pr_supplier_products,id',
            'order_quantities' => 'nullable|array',
        ]);

        try {
            DB::beginTransaction();

            $prRequest = PrRequest::findOrFail($id);

            // Update approved products with order quantities
            $orderQuantities = $request->order_quantities ?? [];
            foreach ($request->approved_products as $productId) {
                $update = ['approved' => true];
                if (isset($orderQuantities[$productId])) {
                    $update['order_qty'] = $orderQuantities[$productId];
                }
                PrSupplierProduct::where('id', $productId)->update($update);
            }

            // Update supplier response status
            $supplierResponseIds = PrSupplierProduct::whereIn('id', $request->approved_products)
                ->pluck('pr_supplier_response_id')
                ->unique();

            foreach ($supplierResponseIds as $responseId) {
                $response = \Modules\PurchaseRequisition\Entities\PrSupplierResponse::find($responseId);
                if ($response) {
                    $response->update([
                        'status' => 'approved',
                        'approved_at' => now(),
                        'approved_by' => auth()->user()->id,
                    ]);
                }
            }

            // Update PR status
            $prRequest->update(['status' => 'approved']);

            DB::commit();

            $output = [
                'success' => 1,
                'msg' => __('purchaseRequisition::lang.approval_successful')
            ];
        } catch (\Exception $e) {
            DB::rollBack();
            \Log::emergency('File:' . $e->getFile() . ' Line:' . $e->getLine() . ' Message:' . $e->getMessage());

            $output = [
                'success' => 0,
                'msg' => __('messages.something_went_wrong')
            ];
        }

        return redirect()->action([\Modules\PurchaseRequisition\Http\Controllers\PrIndexController::class, 'index'])->with('status', $output);
    }
}
