<?php

namespace App\Http\Controllers;

use App\Models\GoodsReceiving;
use App\Models\StoreIssueRequisition;
use App\Http\Requests\StoreIssueRequisitionRequest;
use App\Models\Company;
use App\Models\GoodsReceivingItem;
use App\Models\GrnItemBatch;
use App\Models\InvoiceItem;
use App\Models\RawMaterialItem;
use App\Services\ProductVariationService;
use App\Services\StoreIssueRequisitionService;
use App\Services\ChartOfAccountService;
use App\Services\RawMaterialItemService;
use App\Services\CompanyService;
use App\Services\ProductService;
use App\Services\BatchService;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class StoreIssueRequisitionController extends Controller
{
    protected $storeIssueRequisitionService;
    protected $productVariationService;
    protected $chartOfAccountService;
    protected $rawMaterialItemService;
    protected $batchService;
    protected $companyService;
    protected $productService;

    public function __construct(BatchService $batchService, StoreIssueRequisitionService $storeIssueRequisitionService, RawMaterialItemService $rawMaterialItemService, ChartOfAccountService $chartOfAccountService, CompanyService $companyService, ProductService $productService, ProductVariationService $productVariationService)
    {
        $this->storeIssueRequisitionService = $storeIssueRequisitionService;
        $this->productVariationService = $productVariationService;
        $this->chartOfAccountService = $chartOfAccountService;
        $this->rawMaterialItemService = $rawMaterialItemService;
        $this->companyService = $companyService;
        $this->productService = $productService;
        $this->batchService = $batchService;
    }

    public function index()
    {
        if (!auth()->user()->hasPermission('Store Issue Rquisition List')) {
            abort(403, 'Unauthorized action.');
        }
        $requisitions = $this->storeIssueRequisitionService->getAll();
        return view('admin.store-issue-requisition.index', compact('requisitions'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        if (!auth()->user()->hasPermission('Store Issue Rquisition Create')) {
            abort(403, 'Unauthorized action.');
        }
        if (auth()->user()->hasRole('Superadmin')) {
            $newRequisitionCode = "SIR";
        } else {
            $newRequisitionCode = $this->storeIssueRequisitionService->createCode(auth()->user()->employee->company_id);
        }
        $uniqueValue = Str::random(6);
        $companies = $this->companyService->getAllCompanies();
        $chartOfAccounts = $this->chartOfAccountService->getAllChartOfAccounts();
        $products = $this->productService->getAllProducts();
        $rawMaterialItems = $this->rawMaterialItemService->getAllRawMaterialItems();
        $productVariations = $this->productVariationService->getAllProductVariations();
        $batches = $this->batchService->getAllBatches();
        $defaultCompany = $companies->where('name', 'Benson Pharmaceuticals')->first();
        $defaultCompanyId = $defaultCompany->id;
        return view('admin.store-issue-requisition.create', compact('companies', 'products', 'rawMaterialItems', 'chartOfAccounts', 'productVariations', 'batches', 'newRequisitionCode', 'uniqueValue', 'defaultCompanyId'));
    }

    public function productionCreate()
    {
        if (!auth()->user()->hasPermission('Store Issue Rquisition Create')) {
            abort(403, 'Unauthorized action.');
        }
        if (auth()->user()->hasRole('Superadmin')) {
            $newRequisitionCode = "SIR";
        } else {
            $newRequisitionCode = $this->storeIssueRequisitionService->createCode(auth()->user()->employee->company_id);
        }
        $uniqueValue = Str::random(6);
        $companies = $this->companyService->getAllCompanies();
        $products = $this->productService->getAllProducts();
        $rawMaterialItems = $this->rawMaterialItemService->getAllRawMaterialItems();
        $productVariations = $this->productVariationService->getAllProductVariations();
        $batches = $this->batchService->getAllBatches();
        $defaultCompanyId = Company::where('name', 'Benson Pharmaceuticals')->first()?->id ?? auth()->user()->employee->company_id;
        return view('admin.store-issue-requisition.production-create', compact('companies', 'products', 'rawMaterialItems', 'batches', 'newRequisitionCode', 'productVariations', 'uniqueValue', 'defaultCompanyId'));
    }

    public function itemDetails(Request $request)
    {
        // dd($request->all());

        if ($request->filled('item_id')) {
            if (str_starts_with($request->item_id, 'raw_')) {
                $itemId = (int) str_replace('raw_', '', $request->item_id);
                $raw_material_item = RawMaterialItem::find($itemId);
                if (!$raw_material_item) {
                    return response()->json(['success' => false, 'message' => 'Raw Material Item not found.']);
                }

                $grnItems = GoodsReceivingItem::where('raw_material_item_id', $raw_material_item->id)
                    ->pluck('id')
                    ->toArray();

                $grnItemBatches = GrnItemBatch::whereIn('grn_item_id', $grnItems)
                    ->with('grn')
                    ->orderBy('grn_item_id')
                    ->orderBy('id')
                    ->get();

                return response()->json([
                    'success' => true,
                    'stock' => $raw_material_item->current_stock,
                    // 'unit' => $raw_material_item->unit,
                    // 'price' => $raw_material_item->avg_unit_price,
                    'grnItemBatches' => $grnItemBatches,
                ]);
            }
            // $product_variation = null;
            // $balance = 0;
            // $unit = null;
            // $average_price = 0;

            // if (str_starts_with($productVariationId, 'raw_')) {
            //     $raw_material_item = (int) str_replace('raw_', '', $productVariationId);
            //     $stock = Stock::currentBalanceForItem(null, $raw_material_item);
            //     $balance = $stock['balance'] ?? 0;

            //     $items = GoodsReceivingItem::where('raw_material_item_id', $raw_material_item)
            //         ->orderByDesc('id')
            //         ->get();
            // } elseif (str_starts_with($productVariationId, 'var_')) {
            //     $product_variation = (int) str_replace('var_', '', $productVariationId);
            //     $stock = Stock::currentBalanceForItem(null, null, $product_variation);
            //     $balance = $stock['balance'] ?? 0;

            //     $items = FinishedGoodsReceivingItem::where('product_variation_id', $product_variation)
            //         ->orderByDesc('id')
            //         ->get();
            // } else {
            //     $raw_material_item = $productVariationId;
            //     $stock = Stock::currentBalanceForItem(null, $raw_material_item);
            //     $balance = $stock['balance'] ?? 0;

            //     $items = GoodsReceivingItem::where('raw_material_item_id', $raw_material_item)
            //         ->orderByDesc('id')
            //         ->get();
            // }

            // $accumulatedQty = 0;
            // $totalCost = 0;

            // $remainingBalance = $balance;

            // foreach ($items as $item) {
            //     $qty = (float) (($item->quantity_received != 0) ? $item->quantity_received : ($item->balance_receivable ?? 0));
            //     $price = (float) ($item->unit_price ?? 0);

            //     if ($remainingBalance <= 0) break;

            //     $usedQty = min($qty, $remainingBalance);

            //     $accumulatedQty += $usedQty;
            //     $totalCost += $usedQty * $price;
            //     $remainingBalance -= $usedQty;

            //     $unit = $item->unit ?? $unit;
            // }

            // $average_price = $accumulatedQty > 0 ? round($totalCost / $accumulatedQty, 2) : 0;

            return response()->json([
                'unit' => $unit ?? 'Unit',
                'price' => '',
                'stock' => '',
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => 'Item not found'
            ]);
        }
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(StoreIssueRequisitionRequest $request)
    {
        // dd($request->all());
        if (!auth()->user()->hasPermission('Store Issue Rquisition Create')) {
            abort(403, 'Unauthorized action.');
        }
        $sir = $this->storeIssueRequisitionService->create($request->validated());
        if ($sir) {
            return redirect()->route('store-issue-requisitions.show', $sir->id)->with('success', 'Store Issue Requisition created successfully.');
        } else {
            return redirect()->back()->with('error', 'Store Issue Requisition creation failed.');
        }
    }

    /**
     * Display the specified resource.
     */
    public function show($id)
    {
        if (!auth()->user()->hasPermission('Store Issue Rquisition View')) {
            abort(403, 'Unauthorized action.');
        }
        $sir = $this->storeIssueRequisitionService->getById($id);
        $previous = StoreIssueRequisition::where('id', '<', $sir->id)
            ->orderBy('id', 'desc')
            ->first();

        $next = StoreIssueRequisition::where('id', '>', $sir->id)
            ->orderBy('id', 'asc')
            ->first();

        // Get all purchase orders for the dropdown (ordered by creation date, newest first)
        $allSIRs = StoreIssueRequisition::orderBy('created_at', 'desc')
            ->select('id', 'code', 'created_at')
            ->get();

        $requisition = $sir;

        return view('admin.store-issue-requisition.show', compact('requisition', 'previous', 'next', 'allSIRs'));
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit($id)
    {
        if (!auth()->user()->hasPermission('Store Issue Rquisition Update')) {
            abort(403, 'Unauthorized action.');
        }
        $uniqueValue = Str::random(6);
        $requisition = $this->storeIssueRequisitionService->getById($id);
        $companies = $this->companyService->getAllCompanies();
        $products = $this->productService->getAllProducts();
        $chartOfAccounts = $this->chartOfAccountService->getAllChartOfAccounts();
        $rawMaterialItems = $this->rawMaterialItemService->getAllRawMaterialItems();
        $batches = $this->batchService->getAllBatches();
        $productVariations = $this->productVariationService->getAllProductVariations();
        $defaultCompany = $companies->where('name', 'Benson Pharmaceuticals')->first();
        $defaultCompanyId = $defaultCompany->id;

        // dd($requisition);
        $data = [
            'requisition' => $requisition,
            'companies' => $companies,
            'products' => $products,
            'chartOfAccounts' => $chartOfAccounts,
            'rawMaterialItems' => $rawMaterialItems,
            'productVariations' => $productVariations,
            'batches' => $batches,
            'uniqueValue' => $uniqueValue,
            'defaultCompanyId' => $defaultCompanyId,
        ];
        if ($requisition->is_production == 1) {
            return view('admin.store-issue-requisition.production-edit', $data);
        } else {
            return view('admin.store-issue-requisition.edit', $data);
        }
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(StoreIssueRequisitionRequest $request, StoreIssueRequisition $storeIssueRequisition)
    {
        // dd($request->all());
        if (!auth()->user()->hasPermission('Store Issue Rquisition Update')) {
            abort(403, 'Unauthorized action.');
        }
        $sir = $this->storeIssueRequisitionService->update($storeIssueRequisition, $request->validated());
        return redirect()->route('store-issue-requisitions.show', $sir->id)->with('success', 'Store Issue Requisition updated successfully');
    }

    public function destroy(StoreIssueRequisition $storeIssueRequisition)
    {
        if (!auth()->user()->hasPermission('Store Issue Rquisition Delete')) {
            abort(403, 'Unauthorized action.');
        }
        $this->storeIssueRequisitionService->delete($storeIssueRequisition);
        return redirect()->route('store-issue-requisitions.index')->with('success', 'Store Issue Requisition deleted successfully');
    }

    public function createCodeByCompany($companyId)
    {
        $store_requisition_code = $this->storeIssueRequisitionService->createCode($companyId);
        return response()->json(['store_requisition_code' => $store_requisition_code]);
    }

    public function getGeneralStoreRequisitionsByCompany($companyId)
    {
        $storeIssueRequisitions = StoreIssueRequisition::where('company_id', $companyId)->where('is_general', '1')->orderBy('code', 'asc')->get();
        return response()->json(['storeIssueRequisitions' => $storeIssueRequisitions]);
    }

    public function getProductionSIRByInvoice($companyId, $invoiceId)
    {
        // $grns = GoodsReceiving::where('invoice_id', $invoiceId)->get();
        // $storeIssueRequisitions = StoreIssueRequisition::where('company_id', $companyId)->where('is_production', '1')->orderBy('code', 'asc')->get();

        $grnIds = GoodsReceiving::where('invoice_id', $invoiceId)->pluck('id')->toArray();
        $grnItemBatchIds = GrnItemBatch::whereIn('grn_id', $grnIds)->pluck('id')->toArray();


        // Step 2: get SIRs that used these items
        $storeIssueRequisitions = StoreIssueRequisition::where('is_production', '1')
            ->whereHas('items', function ($q) use ($grnItemBatchIds) {
                $q->whereIn('batch_id', $grnItemBatchIds);
            })
            ->orderBy('code')
            ->get();

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

    public function getProductionStoreRequisitionsByCompany($companyId, Request $request)
    {
        $storeIssueRequisitions = StoreIssueRequisition::where('company_id', $companyId)->where('product_id', $request->productId)->where('is_production', '1')->orderBy('code', 'asc')->get();
        return response()->json(['storeIssueRequisitions' => $storeIssueRequisitions]);
    }

    public function getGeneralStoreRequisitionDetailsById($requisitionId, Request $request)
    {
        // Fetch requisition with related items
        $requisition = StoreIssueRequisition::with('items.product', 'items.raw_material_item')
            ->where('id', $requisitionId)
            ->first();

        // Fetch goods receiving with related items
        $goodsReceivings = GoodsReceiving::with('items.product', 'items.rawMaterialItem')
            // ->where('supplier_bill_no', $request->supplierBillNo)
            ->where('invoice_id', $request->invoiceId)
            ->first();

        // Check if both exist
        if ($requisition && $goodsReceivings) {
            // Extract items from both
            $requisitionItems = collect($requisition->items); // Convert to collection for easy handling
            $goodsReceivingItems = collect($goodsReceivings->items);

            // Find common items based on product_id or raw_material_item_id
            $commonItems = $requisitionItems->filter(function ($reqItem) use ($goodsReceivingItems) {
                return $goodsReceivingItems->contains(function ($grItem) use ($reqItem) {
                    return ($reqItem->product_id == $grItem->product_id && $reqItem->product_id !== null)
                        || ($reqItem->raw_material_item_id == $grItem->raw_material_item_id && $reqItem->raw_material_item_id !== null);
                });
            });

            // Transform to include only required fields
            $result = $commonItems->map(function ($item) {
                return [
                    'raw_material_item_id' => $item->raw_material_item_id,
                    'product_id' => $item->product_id,
                    'quantity' => $item->quantity,
                    'unit_price' => $item->unit_price,
                    'unit' => $item->unit,
                    'total' => $item->total,
                    'product' => $item->product ? [
                        'id' => $item->product->id,
                        'name' => $item->product->name,
                    ] : null,
                    'raw_material_item' => $item->raw_material_item ? [
                        'id' => $item->raw_material_item->id,
                        'name' => $item->raw_material_item->name,
                    ] : null,
                ];
            });

            // Return only the filtered fields
            return response()->json(['items' => $result->values()]);
        } else {
            return response()->json(['error' => 'Requisition or Goods Receiving not found.'], 404);
        }
    }

    public function getProductionStoreRequisitionDetailsById($requisitionId, Request $request)
    {
        // Fetch requisition with related items
        $requisition = StoreIssueRequisition::with('items.raw_material_item')
            ->where('id', $requisitionId)
            ->first();

        if ($request->batchId && $requisition->batch_id == $request->batchId) {
            // Return only the filtered fields
            return response()->json(['items' => $requisition->items]);
        } else {
            return response()->json(['error' => 'Requisition not found.'], 404);
        }
    }
}
