<?php

namespace App\Http\Controllers;

use App\Contact, 
    App\Product, 
    App\Variation,
    App\TaxRate, 
    App\Transaction, 
    App\PurchaseLine,
    App\BusinessLocation,
    App\Business,
    App\CustomerGroup;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Yajra\DataTables\Facades\DataTables;
use Validator;

use App\Utils\ProductUtil;
use App\Utils\TransactionUtil,
    App\Utils\BusinessUtil;

class PurchaseController extends Controller
{
    /**
     * All Utils instance.
     *
     */
    protected $productUtil;
    protected $transactionUtil;

    /**
     * Constructor
     *
     * @param ProductUtils $product
     * @return void
     */
    public function __construct(ProductUtil $productUtil, TransactionUtil $transactionUtil,
                                BusinessUtil $businessUtil)
    {
        $this->productUtil = $productUtil;
        $this->transactionUtil = $transactionUtil;
        $this->businessUtil = $businessUtil;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        if ( !auth()->user()->can('purchase.view') && !auth()->user()->can('purchase.create')) {
            abort(403, 'Unauthorized action.');
        }

        if (request()->ajax()) {
            $business_id = request()->session()->get('user.business_id');

            $purchases = Transaction::leftJoin('contacts', 'transactions.contact_id', '=', 'contacts.id')
                    ->join('business_locations AS BS', 
                        'transactions.location_id', '=', 'BS.id')
                    ->leftJoin('transaction_payments AS TP', 
                        'transactions.id', '=', 'TP.transaction_id')
                    ->where('transactions.business_id', $business_id)
                    ->where('transactions.type', 'purchase')
                    ->select( 'transactions.id', 'document', 'transaction_date', 'ref_no', 'contacts.name', 'status', 
                        'payment_status', 'final_total', 'BS.name as location_name',
                        DB::raw('SUM(TP.amount) as amount_paid'))
                    ->groupBy('transactions.id');

            $permitted_locations = auth()->user()->permitted_locations();
            if($permitted_locations != 'all'){
                $purchases->whereIn('transactions.location_id', $permitted_locations);
            }
            
            if(!empty(request()->supplier_id)){
                $supplier_id = request()->supplier_id;
                $purchases->where('contacts.id', $supplier_id);
            }
            if(!empty(request()->start_date) && !empty(request()->end_date)){
                $start = request()->start_date;
                $end =  request()->end_date;
                $purchases->whereDate( 'transaction_date', '>=', $start )
                            ->whereDate( 'transaction_date', '<=', $end );
            }
            return Datatables::of($purchases)
                ->addColumn('action', function($row){
                    $html = '<div class="btn-group">
                            <button type="button" class="btn btn-info dropdown-toggle btn-xs" 
                                data-toggle="dropdown" aria-expanded="false">' . 
                                __("messages.actions") . 
                                '<span class="caret"></span><span class="sr-only">Toggle Dropdown
                                </span>
                            </button>
                            <ul class="dropdown-menu dropdown-menu-right" role="menu">';
                    if(auth()->user()->can("purchase.view") ){
                        $html .= '<li><a href="#" data-href="' . action('PurchaseController@show', [$row->id]) . '" class="btn-modal" data-container=".view_modal"><i class="fa fa-eye" aria-hidden="true"></i>' . __("messages.view") . '</a></li>';
                    }
                    if(auth()->user()->can("purchase.view") ){
                        $html .= '<li><a href="#" class="print-invoice" data-href="' . action('PurchaseController@printInvoice', [$row->id]) . '"><i class="fa fa-print" aria-hidden="true"></i>'. __("messages.print") .'</a></li>';
                    }
                    if(auth()->user()->can("purchase.update") ){
                        $html .= '<li><a href="' . action('PurchaseController@edit', [$row->id]) . '"><i class="glyphicon glyphicon-edit"></i>' . __("messages.edit") . '</a></li>';
                    }
                    if(auth()->user()->can("purchase.delete") ){
                        $html .= '<li><a href="' . action('PurchaseController@destroy', [$row->id]) . '" class="delete-purchase"><i class="fa fa-trash"></i>' . __("messages.delete") . '</a></li>';
                    }

                    $html .= '<li><a href="' . action('LabelsController@show') . '?purchase_id=' . $row->id . '" data-toggle="tooltip" title="Print Barcode/Label"><i class="fa fa-barcode"></i>' . __('barcode.labels') . '</a></li>';

                    if(auth()->user()->can("purchase.view") && !empty($row->document)){
                        $document_name = !empty(explode("_", $row->document, 2)[1]) ? explode("_", $row->document, 2)[1] : $row->document ;
                        $html .= '<li><a href="' . url( 'storage/documents/' . $row->document ) .'" download="' . $document_name . '"><i class="fa fa-download" aria-hidden="true"></i>' . __("purchase.download_document") . '</a></li>';
                    }
                                        
                    if(auth()->user()->can("purchase.create") ){
                        $html .= '<li class="divider"></li>';
                        if($row->payment_status != 'paid'){
                            $html .= '<li><a href="' . action('TransactionPaymentController@addPayment', [$row->id]) . '" class="add_payment_modal"><i class="fa fa-money" aria-hidden="true"></i>' . __("purchase.add_payment") . '</a></li>';
                        }
                        $html .= '<li><a href="' . action('TransactionPaymentController@show', [$row->id]) . 
                        '" class="view_payment_modal"><i class="fa fa-money" aria-hidden="true" ></i>' . __("purchase.view_payments") . '</a></li>';
                    }

                    $html .=  '</ul></div>';
                    return $html;
                })
                ->removeColumn('id')
                ->editColumn('final_total',
                    '<span class="display_currency" data-currency_symbol="true">{{$final_total}}</span>'
                    )
                ->editColumn('transaction_date', '{{@format_date($transaction_date)}}')
                ->editColumn('status', 
                    '<span class="label @transaction_status($status)">{{__(\'lang_v1.\' . $status)}}
                        </span>'
                    )
                ->editColumn('payment_status', 
                        '<a href="{{ action("TransactionPaymentController@show", [$id])}}" class="view_payment_modal"><span class="label @payment_status($payment_status)">{{__(\'lang_v1.\' . $payment_status)}}
                        </span></a>'
                    )
                ->addColumn('payment_due', function($row){
                    $due = $row->final_total - $row->amount_paid;
                    return '<span class="display_currency" data-currency_symbol="true">' . $due . '</span>';
                })
                ->setRowAttr([
                    'data-href' => function($row) {
                        if(auth()->user()->can("purchase.view") ){
                            return  action('PurchaseController@show', [$row->id]) ;
                        } else {
                            return '';
                        }
                }])
                ->rawColumns(['final_total', 'action', 'payment_due', 'payment_status', 'status'])
                ->make(true);
        }
        return view ('purchase.index');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        if (!auth()->user()->can('purchase.create') ) {
            abort(403, 'Unauthorized action.');
        }

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

        $taxes = TaxRate::where('business_id', $business_id)
                            ->get();
        $orderStatuses = $this->productUtil->orderStatuses();
        $business_locations = BusinessLocation::forDropdown($business_id);

        $currency_details = $this->transactionUtil->purchaseCurrencyDetails($business_id);

        $default_purchase_status = null;
        if(request()->session()->get('business.enable_purchase_status') != 1){
            $default_purchase_status = 'received';
        }

        $types = array();
        if( auth()->user()->can('supplier.create') ){
            $types['supplier'] = __('report.supplier');
        }
        if( auth()->user()->can('customer.create') ){
            $types['customer'] = __('report.customer');
        }
        if (auth()->user()->can('supplier.create') && auth()->user()->can('customer.create')) {
            $types['both'] = __('lang_v1.both_supplier_customer');
        }
        $customer_groups = CustomerGroup::forDropdown($business_id);

        $business_details = $this->businessUtil->getDetails($business_id);
        $shortcuts = json_decode($business_details->keyboard_shortcuts, true);
        return view ('purchase.create')
            ->with(compact('taxes', 'orderStatuses', 'business_locations', 'currency_details', 'default_purchase_status', 'customer_groups', 'types', 'shortcuts'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        if ( !auth()->user()->can('purchase.create') ) {
            abort(403, 'Unauthorized action.');
        } 

        try {
            $transaction_data = $request->only([ 'ref_no', 'status', 'contact_id', 'transaction_date', 'total_before_tax', 'location_id','discount_type', 'discount_amount','tax_id', 'tax_amount', 'shipping_details', 'shipping_charges', 'final_total', 'additional_notes', 'exchange_rate']);

            $exchange_rate = $transaction_data['exchange_rate'];

            //Reverse exchange rate and save it.
            //$transaction_data['exchange_rate'] = $transaction_data['exchange_rate'];

            //TODO: Check for "Undefined index: total_before_tax" issue
            //Adding temporary fix by validating
            $request->validate([
                'status' => 'required',
                'contact_id' => 'required',
                'transaction_date' => 'required',
                'total_before_tax' => 'required',
                'location_id' => 'required',
                'final_total' => 'required',
                'document' => 'file|max:'. (config('constants.document_size_limit') / 1000)
            ]);

            $business_id = $request->session()->get('user.business_id');
            $user_id = $request->session()->get('user.id');
            $enable_product_editing = $request->session()->get('business.enable_editing_product_from_purchase');

            //Update business exchange rate.
            Business::update_business($business_id, ['p_exchange_rate' => ($transaction_data['exchange_rate'])]);

            $currency_details = $this->transactionUtil->purchaseCurrencyDetails($business_id);

            //unformat input values
            $transaction_data['total_before_tax'] = $this->productUtil->num_uf($transaction_data['total_before_tax'], $currency_details)*$exchange_rate;

            // If discount type is fixed them multiply by exchange rate, else don't
            if($transaction_data['discount_type'] == 'fixed'){
                $transaction_data['discount_amount'] = $this->productUtil->num_uf($transaction_data['discount_amount'], $currency_details)*$exchange_rate;
            } elseif($transaction_data['discount_type'] == 'percentage') {
                $transaction_data['discount_amount'] = $this->productUtil->num_uf($transaction_data['discount_amount'], $currency_details);
            } else{
                $transaction_data['discount_amount'] = 0;
            }

            $transaction_data['tax_amount'] = $this->productUtil->num_uf($transaction_data['tax_amount'], $currency_details)*$exchange_rate;
            $transaction_data['shipping_charges'] = $this->productUtil->num_uf($transaction_data['shipping_charges'], $currency_details)*$exchange_rate;
            $transaction_data['final_total'] = $this->productUtil->num_uf($transaction_data['final_total'], $currency_details)*$exchange_rate;

            $transaction_data['business_id'] = $business_id;
            $transaction_data['created_by'] = $user_id;
            $transaction_data['type'] = 'purchase';
            $transaction_data['payment_status'] = 'due';
            $transaction_data['transaction_date'] = $this->productUtil->uf_date($transaction_data['transaction_date']);

            //upload document
            if ($request->hasFile('document') && $request->file('document')->isValid()) {
                if( $request->document->getSize() <= config('constants.document_size_limit')){
                    $new_file_name = time() . '_' . $request->document->getClientOriginalName();
                    $path = $request->document->storeAs('public/documents', $new_file_name);
                    $transaction_data['document'] = str_replace('public/documents/', '', $path);
                }
            }
            
            DB::beginTransaction();

            //Update reference count
            $ref_count = $this->productUtil->setAndGetReferenceCount($transaction_data['type']);
            //Generate reference number
            if(empty($transaction_data['ref_no'])){
                $transaction_data['ref_no'] = $this->productUtil->generateReferenceNumber($transaction_data['type'], $ref_count);
            }

            $transaction = Transaction::create($transaction_data);
            
            $purchase_lines = array();
            $purchases = $request->input('purchases');
            foreach( $purchases as $purchase ){
                $new_purchase_line = array(
                'product_id' => $purchase['product_id'],
                'variation_id' => $purchase['variation_id'],
                'quantity'=> $this->productUtil->num_uf($purchase['quantity'], $currency_details),
                'pp_without_discount' => $this->productUtil->num_uf($purchase['pp_without_discount'], $currency_details)*$exchange_rate,
                'discount_percent' => $this->productUtil->num_uf($purchase['discount_percent'], $currency_details),
                'purchase_price' => $this->productUtil->num_uf($purchase['purchase_price'], $currency_details)*$exchange_rate,
                'item_tax'=>$this->productUtil->num_uf($purchase['item_tax'], $currency_details)*$exchange_rate,
                'tax_id' => $purchase['purchase_line_tax_id'],
                'purchase_price_inc_tax' => $this->productUtil->num_uf($purchase['purchase_price_inc_tax'], $currency_details)*$exchange_rate,
                'lot_number' => !empty($purchase['lot_number']) ? $purchase['lot_number'] : null
                );

                if(!empty($purchase['mfg_date'])){
                    $new_purchase_line['mfg_date'] = $this->productUtil->uf_date($purchase['mfg_date']);
                }
                if(!empty($purchase['exp_date'])){
                    $new_purchase_line['exp_date'] =$this->productUtil->uf_date($purchase['exp_date']);
                }

                $purchase_lines[] = $new_purchase_line;

                //Edit product price
                if($enable_product_editing == 1){
                    //Default selling price is in base currency so no need to multiply with exchange rate.
                    $new_purchase_line['default_sell_price'] = $this->productUtil->num_uf($purchase['default_sell_price'], $currency_details);
                    $this->productUtil->updateProductFromPurchase($new_purchase_line);
                }

                // Update quantity only if status is "received"
                if( $transaction_data['status'] == 'received' ){
                    $this->productUtil->updateProductQuantity($transaction_data['location_id'], $purchase['product_id'], $purchase['variation_id'], $purchase['quantity']);
                }
            }

            if(!empty($purchase_lines)){
                $transaction->purchase_lines()->createMany($purchase_lines);
            }
            
            DB::commit();
            
            $output = array('success' => 1, 
                            'msg' => __('purchase.purchase_add_success')
                        );
            
        } catch(\Exception $e){
            DB::rollBack();
            \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());
            
            $output = array('success' => 0, 
                            'msg' => __('messages.something_went_wrong')
                        );
        }

        return redirect('purchases')->with('status', $output);
        
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        if (!auth()->user()->can('purchase.view')) {
            abort(403, 'Unauthorized action.');
        } 

        $business_id = request()->session()->get('user.business_id');
        $taxes = TaxRate::where('business_id', $business_id)
                            ->pluck('name', 'id');
        $purchase = Transaction::where( 'business_id', $business_id)
                                ->where('id', $id)
                                ->with( 'contact', 'purchase_lines', 
                                    'purchase_lines.product', 
                                    'purchase_lines.variations', 
                                    'purchase_lines.variations.product_variation', 
                                    'location', 'payment_lines')
                                ->first();

        return view ('purchase.show')
                ->with(compact('taxes', 'purchase'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        if (!auth()->user()->can('purchase.update')) {
            abort(403, 'Unauthorized action.');
        } 

        //Check if the transaction can be edited or not.
        $edit_days = request()->session()->get('business.transaction_edit_days');
        if(!$this->transactionUtil->canBeEdited($id, $edit_days)){
            return back()
                ->with('status', ['success' => 0, 
                    'msg' => __('messages.transaction_edit_not_allowed', ['days' => $edit_days])]
                );
        }
        
        $business_id = request()->session()->get('user.business_id');

        $business = Business::find($business_id);

        $currency_details = $this->transactionUtil->purchaseCurrencyDetails($business_id);

        $taxes = TaxRate::where('business_id', $business_id)
                            ->get();
        $purchase = Transaction::where( 'business_id', $business_id)
                                ->where('id', $id)
                                ->with( 'contact', 'purchase_lines','purchase_lines.product','purchase_lines.product.unit', 'purchase_lines.variations', 'purchase_lines.variations.product_variation', 
                                    'location')
                                ->first();
        $taxes = TaxRate::where('business_id', $business_id)
                            ->get(); 
        $orderStatuses = $this->productUtil->orderStatuses();

        $business_locations = BusinessLocation::forDropdown($business_id);

        $default_purchase_status = null;
        if(request()->session()->get('business.enable_purchase_status') != 1){
            $default_purchase_status = 'received';
        }

        $types = array();
        if( auth()->user()->can('supplier.create') ){
            $types['supplier'] = __('report.supplier');
        }
        if( auth()->user()->can('customer.create') ){
            $types['customer'] = __('report.customer');
        }
        if (auth()->user()->can('supplier.create') && auth()->user()->can('customer.create')) {
            $types['both'] = __('lang_v1.both_supplier_customer');
        }
        $customer_groups = CustomerGroup::forDropdown($business_id);

        $business_details = $this->businessUtil->getDetails($business_id);
        $shortcuts = json_decode($business_details->keyboard_shortcuts, true);

        return view ('purchase.edit')
            ->with(compact('taxes', 'purchase', 'taxes', 'orderStatuses', 
                'business_locations', 'business', 'currency_details', 'default_purchase_status', 'customer_groups', 'types', 'shortcuts'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        if (!auth()->user()->can('purchase.update')) {
            abort(403, 'Unauthorized action.');
        } 

        try {

            $transaction = Transaction::findOrFail($id);

            //Validate document size
            $request->validate([
                'document' => 'file|max:'. (config('constants.document_size_limit') / 1000)
            ]);

            $transaction = Transaction::findOrFail( $id );
            $before_status = $transaction->status;
            $business_id = request()->session()->get('user.business_id');
            $enable_product_editing = $request->session()->get('business.enable_editing_product_from_purchase');

            $currency_details = $this->transactionUtil->purchaseCurrencyDetails($business_id);

            $update_data = $request->only([ 'ref_no', 'status', 'contact_id', 
                            'transaction_date', 'total_before_tax', 
                            'discount_type', 'discount_amount', 'tax_id', 
                            'tax_amount', 'shipping_details', 
                            'shipping_charges', 'final_total', 
                            'additional_notes', 'exchange_rate']);

            $exchange_rate = $update_data['exchange_rate'];

            //Reverse exchage rate and save
            //$update_data['exchange_rate'] = number_format(1 / $update_data['exchange_rate'], 2);

            $update_data['transaction_date'] = $this->productUtil->uf_date($update_data['transaction_date']);

            //unformat input values
            $update_data['total_before_tax'] = $this->productUtil->num_uf($update_data['total_before_tax'], $currency_details) * $exchange_rate;

            // If discount type is fixed them multiply by exchange rate, else don't
            if($update_data['discount_type'] == 'fixed'){
                $update_data['discount_amount'] = $this->productUtil->num_uf($update_data['discount_amount'], $currency_details) * $exchange_rate;
            } elseif($update_data['discount_type'] == 'percentage') {
                $update_data['discount_amount'] = $this->productUtil->num_uf($update_data['discount_amount'], $currency_details);
            } else {
                $update_data['discount_amount'] = 0;
            }

            $update_data['tax_amount'] = $this->productUtil->num_uf($update_data['tax_amount'], $currency_details) * $exchange_rate;
            $update_data['shipping_charges'] = $this->productUtil->num_uf($update_data['shipping_charges'], $currency_details) * $exchange_rate;
            $update_data['final_total'] = $this->productUtil->num_uf($update_data['final_total'], $currency_details) * $exchange_rate;
            //unformat input values ends

            //upload document
            if ($request->hasFile('document') && $request->file('document')->isValid()) {
                if( $request->document->getSize() <= config('constants.document_size_limit')){
                    $new_file_name = time() . '_' . $request->document->getClientOriginalName();
                    $path = $request->document->storeAs('public/documents', $new_file_name);
                    $update_data['document'] = str_replace('public/documents/', '', $path);
                }
            }

            DB::beginTransaction();

            //update transaction
            $transaction->update($update_data);

            //Update transaction payment status
            $this->transactionUtil->updatePaymentStatus($transaction->id);

            $purchases = $request->input('purchases');

            $updated_purchase_lines = array();

            $updated_purchase_line_ids = [0];

            //P => R (All items quantity update)
            //R => P (Existing minus)
            //R => R (Exisitng quantity update, New product add, minus deleted products)

            foreach ($purchases as $purchase) {
                //update existing purchase line
                if (isset($purchase['purchase_line_id'])) {

                    $purchase_line = PurchaseLine::findOrFail( $purchase['purchase_line_id'] );
                    $updated_purchase_line_ids[] = $purchase_line->id;
                    
                    //Update quantity for existing products
                    if($before_status == 'received' && $transaction->status == 'received'){
                     //if status received update existing quantity
                        $this->productUtil->updateProductQuantity($transaction->location_id, $purchase['product_id'], $purchase['variation_id'], $purchase['quantity'], $purchase_line->quantity, $currency_details);

                    } elseif ($before_status == 'received' && $transaction->status != 'received'){
                        //decrease quantity only if status changed from received to not received
                            $this->productUtil->decreaseProductQuantity($purchase['product_id'], 
                                $purchase['variation_id'], $transaction->location_id,  $purchase_line->quantity );
                    } elseif ($before_status != 'received' && $transaction->status == 'received') {
                        $this->productUtil->updateProductQuantity($transaction->location_id, $purchase['product_id'], $purchase['variation_id'], $purchase['quantity'], 0, $currency_details);
                    }

                } else { 
                    //create newly added purchase lines
                    $purchase_line = new PurchaseLine();
                    $purchase_line->product_id = $purchase['product_id'];
                    $purchase_line->variation_id = $purchase['variation_id'];

                    //Increase quantity only if status is received
                    if($transaction->status == 'received'){
                        $this->productUtil->updateProductQuantity($transaction->location_id, $purchase['product_id'], $purchase['variation_id'], $purchase['quantity'], 0, $currency_details);
                    }
                }

                $purchase_line->quantity = $this->productUtil->num_uf($purchase['quantity'], $currency_details);
                $purchase_line->pp_without_discount = $this->productUtil->num_uf($purchase['pp_without_discount'], $currency_details)*$exchange_rate;
                $purchase_line->discount_percent = $this->productUtil->num_uf($purchase['discount_percent'], $currency_details);
                $purchase_line->purchase_price = $this->productUtil->num_uf($purchase['purchase_price'], $currency_details)*$exchange_rate;
                $purchase_line->purchase_price_inc_tax = $this->productUtil->num_uf($purchase['purchase_price_inc_tax'], $currency_details)*$exchange_rate;
                $purchase_line->item_tax = $this->productUtil->num_uf($purchase['item_tax'], $currency_details)*$exchange_rate;
                $purchase_line->tax_id = $purchase['purchase_line_tax_id'];
                $purchase_line->lot_number = !empty($purchase['lot_number']) ? $purchase['lot_number'] : null;
                $purchase_line->mfg_date = !empty($purchase['mfg_date']) ? $this->productUtil->uf_date($purchase['mfg_date']) : null;
                $purchase_line->exp_date = !empty($purchase['exp_date']) ? $this->productUtil->uf_date($purchase['exp_date']) : null;
                
                $updated_purchase_lines[] = $purchase_line;

                //Edit product price
                if($enable_product_editing == 1){
                    $variation_data['default_sell_price'] = $this->productUtil->num_uf($purchase['default_sell_price'], $currency_details);
                    $variation_data['pp_without_discount'] = $this->productUtil->num_uf($purchase['pp_without_discount'], $currency_details)*$exchange_rate;
                    $variation_data['variation_id'] = $purchase_line->variation_id;
                    $variation_data['purchase_price'] = $purchase_line->purchase_price; 
                     
                    $this->productUtil->updateProductFromPurchase($variation_data);
                }
            }

            //unset deleted purchase lines
            $delete_purchase_line_ids = array();
            if (!empty( $updated_purchase_line_ids )) {

                $delete_purchase_lines = PurchaseLine::where('transaction_id', $transaction->id)
                            ->whereNotIn('id', $updated_purchase_line_ids)
                            ->get();

                if($delete_purchase_lines->count()){
                    
                    foreach ($delete_purchase_lines as $delete_purchase_line) {
                        $delete_purchase_line_ids[] = $delete_purchase_line->id;

                        //decrease deleted only if previous status was received
                        if( $before_status == 'received' ){
                            $this->productUtil->decreaseProductQuantity(
                                $delete_purchase_line->product_id, $delete_purchase_line->variation_id, 
                                $transaction->location_id, $delete_purchase_line->quantity);
                        }
                    }
                    //Delete deleted purchase lines
                    PurchaseLine::where('transaction_id', $transaction->id)
                                ->whereIn('id', $delete_purchase_line_ids)
                                ->delete();
                }                
            }

            //update purchase lines
            if (!empty( $updated_purchase_lines )) {
                $transaction->purchase_lines()->saveMany($updated_purchase_lines);
            }

            //Update mapping of purchase & Sell.
            $this->transactionUtil->adjustMappingPurchaseSellAfterEditingPurchase($before_status,  $transaction, $delete_purchase_lines);

            DB::commit();

            $output = array('success' => 1, 
                            'msg' => __('purchase.purchase_update_success')
                        );
             
        } catch (\Exception $e) {
            DB::rollBack();
            \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());
            
            $output = array('success' => 0, 
                            'msg' => $e->getMessage()
                        );
            return back()->with('status', $output);
        } 

        return redirect('purchases')->with('status', $output);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        if (!auth()->user()->can('purchase.delete')) {
            abort(403, 'Unauthorized action.');
        } 

        try {
            if (request()->ajax()) {
                $business_id = request()->session()->get('user.business_id');

                $transaction = Transaction::where('id', $id)
                                            ->where('business_id', $business_id)
                                            ->with(['purchase_lines'])
                                            ->first();
                $delete_purchase_lines = $transaction->purchase_lines;
                DB::beginTransaction();

                $transaction_status = $transaction->status;
                if( $transaction_status != 'received'){
                    $transaction->delete();
                } else {

                    //Delete purchase lines first
                    $delete_purchase_line_ids = array();
                    foreach ($delete_purchase_lines as $purchase_line) {
                        $delete_purchase_line_ids[] = $purchase_line->id;
                        $this->productUtil->decreaseProductQuantity(
                                $purchase_line->product_id, $purchase_line->variation_id, 
                                $transaction->location_id, $purchase_line->quantity);
                        
                    }
                    PurchaseLine::where('transaction_id', $transaction->id)
                                ->whereIn('id', $delete_purchase_line_ids)
                                ->delete();

                    //Update mapping of purchase & Sell.
                    $this->transactionUtil->adjustMappingPurchaseSellAfterEditingPurchase($transaction_status,  $transaction, $delete_purchase_lines);
                    }

                    //Delete Transaction
                    $transaction->delete();

                DB::commit();

                $output = array('success' => true, 
                            'msg' => __('lang_v1.purchase_delete_success')
                        );

            }
        } catch (\Exception $e) {
            DB::rollBack();
            \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());
            
            $output = array('success' => false, 
                            'msg' => $e->getMessage()
                        );
        }

        return $output;
    }
    
    /**
     * Retrieves supliers list.
     *
     * @return \Illuminate\Http\Response
     */
    public function getSuppliers()
    {
        if (request()->ajax()) {
            $term = request()->q;
            if(empty($term)){
                return json_encode([]);
            }

            $business_id = request()->session()->get('user.business_id');
            $suppliers = Contact::where( 'business_id', $business_id)
                                ->where(function ($query) use ($term) {
                                    $query->where('name', 'like', '%' . $term .'%')
                                        ->orWhere('supplier_business_name', 'like', '%' . $term .'%');
                                })
                                ->select('id', 'name as text', 'supplier_business_name as business_name')
                                ->onlySuppliers()
                                ->get();
            return json_encode($suppliers);
        }
    }

    /**
     * Retrieves products list.
     *
     * @return \Illuminate\Http\Response
     */
    public function getProducts()
    {
        if (request()->ajax()) {
            $term = request()->term;

            $check_enable_stock = true;
            if(isset(request()->check_enable_stock)){
                $check_enable_stock = filter_var(request()->check_enable_stock, FILTER_VALIDATE_BOOLEAN);
            }

            if(empty($term)){
                return json_encode([]);
            }

            $business_id = request()->session()->get('user.business_id');
            $q = Product::leftJoin('variations', 'products.id', 
                '=', 'variations.product_id')
                ->where(function($query) use ($term)
                {
                    $query->where('products.name', 'like', '%' . $term .'%');
                    $query->orWhere('sku', 'like', '%' . $term .'%');
                    $query->orWhere('sub_sku', 'like', '%' . $term .'%');
                })
                ->where('business_id', $business_id)
                ->whereNull('variations.deleted_at')
                ->select( 'products.id as product_id', 'products.name', 
                    'products.type',
                    // 'products.sku as sku',
                    'variations.id as variation_id', 
                    'variations.name as variation',
                    'variations.sub_sku as sub_sku'
                    )
                ->groupBy('variation_id');

            if($check_enable_stock){
                $q->where('enable_stock', 1);
            }
            $products = $q->get();
                
            $products_array = array();
            foreach ($products as $product) {
                $products_array[$product->product_id]['name'] = $product->name;
                $products_array[$product->product_id]['sku'] = $product->sub_sku;
                $products_array[$product->product_id]['type'] = $product->type;
                $products_array[$product->product_id]['variations'][] 
                = array( 
                        'variation_id' => $product->variation_id,
                        'variation_name' => $product->variation,
                        'sub_sku' => $product->sub_sku
                        );
            }

            $result = array();
            $i = 1;
            $no_of_records = $products->count();
            if(!empty( $products_array )){
                foreach ($products_array as $key => $value) {

                    if( $no_of_records > 1 && $value['type'] != 'single'){
                        $result[] = array( 'id' => $i, 
                                    'text' => $value['name'] . ' - ' . $value['sku'], 
                                    'variation_id' => 0,
                                    'product_id' => $key
                                );
                    }
                    $name = $value['name'];
                    foreach ($value['variations'] as $variation) {
                        $text = $name;
                        if( $value['type'] == 'variable' ){
                            $text = $text . ' (' . $variation['variation_name'] . ')';
                        }
                        $i++;
                        $result[] = array( 'id' => $i, 
                                            'text' => $text . ' - ' . $variation['sub_sku'], 
                                            'product_id' => $key ,
                                            'variation_id' => $variation['variation_id'],
                                        );
                    }
                    $i++;
                }
            }
            
            return json_encode($result);
        }
    }
    
    /**
     * Retrieves products list.
     *
     * @return \Illuminate\Http\Response
     */
    public function getPurchaseEntryRow( Request $request )
    {
        if (request()->ajax()) {
            $product_id = $request->input('product_id');
            $variation_id = $request->input('variation_id');
            $business_id = request()->session()->get('user.business_id');

            $hide_tax = 'hide';
            if($request->session()->get('business.enable_inline_tax') == 1){
                $hide_tax = '';
            }

            $currency_details = $this->transactionUtil->purchaseCurrencyDetails($business_id);

            if(!empty($product_id)){
                $row_count = $request->input('row_count');
                $product = Product::where('id', $product_id)
                                    ->with(['unit'])
                                    ->first();

                $query = Variation::where('product_id', $product_id)
                                        ->with(['product_variation']);
                if( $variation_id !== '0'){
                    $query->where('id', $variation_id);
                }

                $variations =  $query->get();
                
                $taxes = TaxRate::where('business_id', $business_id)
                            ->get();

                return view ('purchase.partials.purchase_entry_row')
                    ->with( compact( 'product', 'variations', 'row_count', 
                        'variation_id', 'taxes', 'currency_details', 'hide_tax' ) );
            }
        }
    }
    
    /**
     * Checks if ref_number and supplier combination already exists.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function checkRefNumber(Request $request)
    {
        $business_id = $request->session()->get('user.business_id');
        $contact_id = $request->input('contact_id');
        $ref_no = $request->input('ref_no');
        $purchase_id = $request->input('purchase_id');

        $count = 0;
        if(!empty($contact_id) && !empty($ref_no) ){
            //check in transactions table
            $query = Transaction::where('business_id', $business_id)
                            ->where('ref_no', $ref_no)
                            ->where('contact_id', $contact_id);
            if(!empty($purchase_id)){
               $query->where('id', '!=', $purchase_id);
            }
            $count = $query->count();
        }
        if($count == 0){
            echo "true";exit;
        }else{
            echo "false";exit;
        }
    }

    /**
     * Checks if ref_number and supplier combination already exists.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function printInvoice($id){
        try {

            $business_id = request()->session()->get('user.business_id');
            $taxes = TaxRate::where('business_id', $business_id)
                                ->pluck('name', 'id');
            $purchase = Transaction::where( 'business_id', $business_id)
                                    ->where('id', $id)
                                    ->with( 'contact', 'purchase_lines', 
                                        'purchase_lines.product', 
                                        'purchase_lines.variations', 
                                        'purchase_lines.variations.product_variation', 
                                        'location', 'payment_lines')
                                    ->first();

            $output = ['success' => 1, 'receipt' => []];
            $output['receipt']['html_content'] = view('purchase.partials.show_details', compact('taxes', 'purchase'))->render();
            
        } catch(\Exception $e){
            \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());
            
            $output = array('success' => 0, 
                            'msg' => __('messages.something_went_wrong')
                        );
        }

        return $output;
    }
}
