<?php

namespace App\Http\Controllers;

use App\Models\Item;
use App\Models\Purchase;
use App\Models\PurchaseItem;
use App\Models\SerialNumber;
use App\Models\Payment;
use App\Models\Expense;
use App\Models\ExpenseHead;
use App\Models\Banking;
use App\Models\BankTransfar;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Http\Request;
use Yajra\Datatables\Datatables;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class SerialNumberController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $purchaseId=Session::get('purchaseId');
        $item_id=Session::get('item_id');

        $data=[
            'serialNumbers'=>SerialNumber::where('purchase_id',$purchaseId)
                                         ->where('item_id',$item_id)
                                         ->paginate(100),
            'purchase_id'=>$purchaseId,
            'item_id'=>$item_id,
        ];

        Session::put('purchaseId',$purchaseId);
        Session::put('item_id',$item_id);
        return view('purchase.all_serial_number',$data);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // dd($request->all());
        if($request->showAllOrNot==1){
            $data=[
                'serialNumbers'=>SerialNumber::where('purchase_id',$request->purchase_id)
                                             ->where('item_id',$request->item_id)
                                             ->paginate(100),
                'purchase_id'=>$request->purchase_id,
                'item_id'=>$request->item_id,
            ];

            Session::put('purchaseId',$request->purchase_id);
            Session::put('item_id',$request->item_id);
            return view('purchase.all_serial_number',$data);

        }else{

            $check= SerialNumber::where('serial_no',$request->serial_number)->where('item_id',$request->item_id)->first();
            $checkNumber= SerialNumber::where('item_id',$request->item_id)->where('purchase_id',$request->purchase_id)->count();
            $purchaseNumber=PurchaseItem::where('purchase_id',$request->purchase_id)
                                        ->where('item_id',$request->item_id)
                                        ->first();
            // dd($check);
            if($purchaseNumber){
                if($checkNumber >= $purchaseNumber->quantity)
                {
                    Toastr::error("All Serial No add for this Purchase");
                    return back();
                }else{
                    if($check)
                    {
                         Toastr::info("Serial No Allready Add ");
                        return back();

                    }else{

                        $serialNumber = new SerialNumber();
                        $serialNumber->purchase_id = $request->purchase_id;
                        $serialNumber->item_id = $request->item_id;
                        $serialNumber->serial_no = $request->serial_number;
                        $serialNumber->status = 'notused';
                        $serialNumber->save();
                        Toastr::success("Serial No Add Successfull");
                         return back();


                    }
                }


            }else{
                if($check)
                {
                     Toastr::info("Serial No Allready Add ");
                    return back();

                }else{

                    $serialNumber = new SerialNumber();
                    $serialNumber->purchase_id = $request->purchase_id;
                    $serialNumber->item_id = $request->item_id;
                    $serialNumber->serial_no = $request->serial_number;
                    $serialNumber->status = 'notused';
                    $serialNumber->save();
                    Toastr::success("Serial No Add Successfull");
                     return back();


                }
            }
        }

    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\SerialNumber  $serialNumber
     * @return \Illuminate\Http\Response
     */
    public function show(SerialNumber $serialNumber)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\SerialNumber  $serialNumber
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        dd($id);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\SerialNumber  $serialNumber
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, SerialNumber $serialNumber)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\SerialNumber  $serialNumber
     * @return \Illuminate\Http\Response
     */
    public function destroy(SerialNumber $serialNumber)
    {
        //
    }

    public function addSerial(Request $request)
    {
        //   dd($request->all());
         $check= SerialNumber::where('item_id',$request->productId)->where('serial_no',$request->data)->first();
         $checkNumber= SerialNumber::where('item_id',$request->productId)->where('purchase_id',$request->purchaseId)->count();
         $purchaseNumber=PurchaseItem::where('purchase_id',$request->purchaseId)
                                     ->where('item_id',$request->productId)
                                     ->first();
        // dd($check);
         if($purchaseNumber){
             if($checkNumber >= $purchaseNumber->quantity)
             {
                //  Toastr::info("All Serial No add for this Purchase");
                 return 3;
             }else{
                 if($check)
                 {
                    return 2;

                 }else{

                     $serialNumber = new SerialNumber();
                     $serialNumber->purchase_id = $request->purchaseId;
                     $serialNumber->item_id = $request->productId;
                     $serialNumber->serial_no = $request->data;
                     $serialNumber->status = 'notused';
                     $serialNumber->save();
                    //  Toastr::info("Serial No Add Successfull");
                     return 1;

                 }
             }


         }else{
             if($check)
             {
                //   Toastr::info("Serial No Allready Add ");
                 return 2;

             }else{

                 $serialNumber = new SerialNumber();
                 $serialNumber->purchase_id = $request->purchaseId;
                 $serialNumber->item_id = $request->productId;
                 $serialNumber->serial_no = $request->data;
                 $serialNumber->status = 'notused';
                 $serialNumber->save();
                //  Toastr::info("Serial No Add Successfull");
                  return 1;


             }
         }

    }

    public function allSerial(Request $request)
    {
        $data=[
            'serials'=>SerialNumber::where('item_id',$request->productId)->where('purchase_id',$request->purchaseId)->orderBy('updated_at', 'desc')->take(15)->get(),
        ];
        // dd($data);

        // return $data;
        return view('purchase.show_table',$data);
    }

    public function editSerialNo(Request $request)
    {
        $serialNumber = SerialNumber::find($request->id);
        $check_serialNumber = SerialNumber::where('item_id',$request->productId)->where('serial_no',$request->data)->first();
        if($serialNumber->status=="used"){
            $data=[
                "result"=>3,
                "value"=>$request->data
            ];
            return $data;
        }else{

            if($check_serialNumber){

                if($serialNumber->id == $check_serialNumber->id)
                {
                    $data=[
                        "result"=>1,
                        "value"=>$request->data
                    ];
                    return $data;
                }else{
                    $data=[
                        "result"=>2,
                        "value"=>$request->data
                    ];
                    return $data;
                }
            }else{
                $serialNumber->serial_no=$request->data;
                $serialNumber->save();
                $data=[
                    "result"=>1,
                    "value"=>$request->data
                ];
                return $data;
            }
        }
    }

    public function serialNoDelete(Request $request)
    {
        $serialNumber= SerialNumber::find($request->id);
        if($serialNumber->status=="used"){
            return 2;
        }else{

            SerialNumber::where('id',$request->id)->delete();
            return 1;
        }
    }

    public function showAllSerialNo($id)
    {
        dd('comes');
        // $data=[
        //     'serialNumbers'=>SerialNumber::where('purchase_id',$purchase_id)
        //                                  ->where('item_id',$item_id)
        //                                  ->paginate(100),
        //     'purchase_id'=>$purchase_id,
        //     'item_id'=>$item_id,
        // ];
        // return view('purchase.all_serial_number',$data);
    }

    public function getSerialNumber(Request $request){
        $serialNumbers=SerialNumber::where('purchase_id',$request->purchaseId)
                                             ->where('item_id',$request->itemId)
                                             ->get();
        // dd($serialNumbers);
        return DataTables::of($serialNumbers)
            ->make(true);
    }

    public function approvePurchase($id)
    {
        $purchase=Purchase::with('items', 'payment_new')->find($id);
        DB::beginTransaction();

        try {
            $check=0;
            foreach($purchase->items as $key=>$item){
                $qty = $item->quantity;
                $product=Item::find($item->item_id);
                $serialNumber= SerialNumber::where('purchase_id',$purchase->id)->where('item_id',$item->item_id )->count();
                if($qty!=$serialNumber && $product->serial_number=="enable"){
                    $itemName=Item::find($item->item_id);
                    Toastr::error("Please Add All serial Number for {$itemName->name}");
                    return back();
                }
            }

            $purchase->approve_status="yes";
            $purchase->approved_id=auth()->user()->id;
            $purchase->save();

            // Handle expense creation and bank withdrawal on approval for cheque payments
            if ($purchase->payment_method == "Cheque" && $purchase->payment_new) {
                $payment = $purchase->payment_new;

                // Find or create Purchase expense head
                $expense_head = ExpenseHead::where('name', "Purchase")->first();
                if ($expense_head == null) {
                    $expense_head = new ExpenseHead();
                    $expense_head->name = "Purchase";
                    $expense_head->save();
                }

                // Check if expense already exists for this purchase
                $existingExpense = Expense::where('invoice_number', $purchase->invoice_number)->first();

                // Get bank account ID from payment
                $bankAccount = null;
                if (!empty($payment->bank_account_id)) {
                    $bankAccount = Banking::find($payment->bank_account_id);
                } elseif ($payment->account_number) {
                    // Fallback: try to find by account number if bank_account_id is not set
                    $bankAccount = Banking::where('account_no', $payment->account_number)->first();
                }

                if (!$existingExpense) {
                    // Create expense entry
                    $expense = new Expense();
                    $note = "Purchase [Invoice: " . $purchase->invoice_number . "] approved by " . Auth::user()->name;
                    $expense->name = "Purchase";
                    $expense->invoice_number = $purchase->invoice_number;
                    $expense->date = Carbon::parse(now());
                    $expense->amount = $purchase->paid;
                    $expense->description = $note;
                    $expense->expenseHead = $expense_head->id;
                    $expense->created_by = Auth::id();
                    $expense->status = "approved";
                    $expense->bank_account_id = $bankAccount ? $bankAccount->id : null;
                    $expense->save();

                    // Check bank balance and withdraw only if bank account is found
                    if ($bankAccount) {
                        $total_deposit = BankTransfar::where('account_id', $bankAccount->id)->sum('diposit_amount');
                        $total_withdrawal = BankTransfar::where('account_id', $bankAccount->id)->sum('withdraw_amount');
                        $balance = $bankAccount->opening_balance + $total_deposit - $total_withdrawal;

                        if ($purchase->paid > $balance) {
                            DB::rollBack();
                            Toastr::error('Withdraw Amount is greater than Bank Balance', 'Error');
                            return back();
                        }

                        // Check if withdrawal already exists for this purchase
                        $existingWithdrawal = BankTransfar::where('description', 'like', '%Purchase [ID:' . $purchase->id . ']%')
                            ->whereNotNull('withdraw_amount')
                            ->first();

                        if (!$existingWithdrawal) {
                            // Withdraw from bank account
                            $bankWithdrawal = new BankTransfar();
                            $bankWithdrawal->account_id = $bankAccount->id;
                            $bankWithdrawal->check_no = $payment->cheque_number;
                            $bankWithdrawal->withdraw_amount = $purchase->paid;
                            $bankWithdrawal->description = 'Purchase [ID:' . $purchase->id . ']: Invoice ' . $purchase->invoice_number . ' - ' . $note;
                            $bankWithdrawal->by = Auth::user()->name ?? 'System';
                            $bankWithdrawal->save();
                        }
                    }
                } else {
                    // Update existing expense (in case purchase was updated and re-approved)
                    $note = "Purchase [Invoice: " . $purchase->invoice_number . "] approved by " . Auth::user()->name;
                    $existingExpense->amount = $purchase->paid;
                    $existingExpense->bank_account_id = $bankAccount ? $bankAccount->id : null;
                    $existingExpense->description = $note;
                    $existingExpense->save();

                    // Handle bank withdrawal update
                    $existingWithdrawal = BankTransfar::where('description', 'like', '%Purchase [ID:' . $purchase->id . ']%')
                        ->whereNotNull('withdraw_amount')
                        ->first();

                    if ($bankAccount) {
                        $total_deposit = BankTransfar::where('account_id', $bankAccount->id)->sum('diposit_amount');
                        $total_withdrawal = BankTransfar::where('account_id', $bankAccount->id)->sum('withdraw_amount');

                        // If updating existing withdrawal on the same account, exclude it from balance calculation
                        if ($existingWithdrawal && $existingWithdrawal->account_id == $bankAccount->id) {
                            $total_withdrawal -= $existingWithdrawal->withdraw_amount;
                        }

                        $balance = $bankAccount->opening_balance + $total_deposit - $total_withdrawal;

                        if ($purchase->paid > $balance) {
                            DB::rollBack();
                            Toastr::error('Withdraw Amount is greater than Bank Balance', 'Error');
                            return back();
                        }

                        // Handle account change: if existing withdrawal is on a different account, delete it first
                        if ($existingWithdrawal && $existingWithdrawal->account_id != $bankAccount->id) {
                            $existingWithdrawal->delete();
                            $existingWithdrawal = null;
                        }

                        // Update or create withdrawal
                        if ($existingWithdrawal) {
                            // Update existing withdrawal
                            $existingWithdrawal->account_id = $bankAccount->id;
                            $existingWithdrawal->withdraw_amount = $purchase->paid;
                            $existingWithdrawal->check_no = $payment->cheque_number;
                            $existingWithdrawal->description = 'Purchase [ID:' . $purchase->id . ']: Invoice ' . $purchase->invoice_number . ' - ' . $note;
                            $existingWithdrawal->by = Auth::user()->name ?? 'System';
                            $existingWithdrawal->save();
                        } else {
                            // Create new withdrawal
                            $bankWithdrawal = new BankTransfar();
                            $bankWithdrawal->account_id = $bankAccount->id;
                            $bankWithdrawal->check_no = $payment->cheque_number;
                            $bankWithdrawal->withdraw_amount = $purchase->paid;
                            $bankWithdrawal->description = 'Purchase [ID:' . $purchase->id . ']: Invoice ' . $purchase->invoice_number . ' - ' . $note;
                            $bankWithdrawal->by = Auth::user()->name ?? 'System';
                            $bankWithdrawal->save();
                        }
                    } else {
                        // If bank account is removed, delete withdrawal
                        if ($existingWithdrawal) {
                            $existingWithdrawal->delete();
                        }
                    }
                }
            }

            DB::commit();
            Toastr::success("Purchase Approve Successfull");
            return back();
        } catch(\Exception $e){
            DB::rollback();
            Toastr::error("Some Problem Happen");
            return back();
        }
    }


    public function serialNoShowAll($id)
    {
        $data=[
            'serialNumbers'=>SerialNumber::where('item_id',$id)->paginate('100'),
        ];
        return view('item.serial_number',$data);
    }

    public function allSerialNumber($purchase_id,$item_id)
    {
        dd('comes');
        $data=[];
        return view('purchase.all_serial_number',$data);
    }


}
