<?php

namespace Modules\Accounting\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
use App\Utils\ModuleUtil;
use App\Utils\TransactionUtil;
use Yajra\DataTables\Facades\DataTables;
use App\Transaction;
use App\TransactionSellLine;
use Modules\Accounting\Entities\AccountingAccount;
use Modules\Accounting\Entities\AccountingAccountsTransaction;
use DB;
use App\TransactionPayment;
use App\PurchaseLine;
use App\BusinessLocation;
use App\Contact;

class TransactionController extends Controller
{
    /**
     * All Utils instance.
     *
     */
    protected $transactionUtil;
    protected $moduleUtil;

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

    /**
     * Display a listing of the resource.
     * @return Response
     */
    public function index()
    {
			$sqlalter="alter table transactions add account_synced integer default 0 ";
			$isexist = DB::select( DB::raw("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='transactions' and column_name='account_synced'"));
			if(empty($isexist)){
				$createTempTables = DB::unprepared(
				DB::raw($sqlalter)
				);
			}
			$sqlalter="alter table transaction_payments add account_synced integer default 0 ";
			$isexist = DB::select( DB::raw("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='transaction_payments' and column_name='account_synced'"));
			if(empty($isexist)){
				$createTempTables = DB::unprepared(
				DB::raw($sqlalter)
				);
			}
        if (request()->ajax()) {

            if(request()->input('datatable') == 'payment'){
				if(request()->input('transaction_type') == 'purchase'){
                return $this->_allPurchasePayments();
				}
                return $this->_allPayments();
            }
            
            if(request()->input('datatable') == 'sell'){
                return $this->_allSales();
            }

            if(request()->input('datatable') == 'purchase'){
                return $this->_allPurchases();
            }
        }

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

        $business_locations = BusinessLocation::forDropdown($business_id);
        $suppliers = Contact::suppliersDropdown($business_id, false);
        $orderStatuses = $this->transactionUtil->orderStatuses();
		$maxselldate=AccountingAccountsTransaction::where('sub_type','sell')->orderBY('id','desc')->limit(1)->first();
		$maxselltxndate=DB::table('transactions')->where('type','sell')->where('status','final')->orderBY('id','desc')->limit(1)->first();
		$maxsellpaydate=AccountingAccountsTransaction::where('sub_type','sell_payment')->orderBY('id','desc')->limit(1)->first();
		$maxpurchasedate=AccountingAccountsTransaction::where('sub_type','purchase')->orderBY('id','desc')->limit(1)->first();
		$maxpurchasetxndate=DB::table('transactions')->where('type','purchase')->where('status','received')->orderBY('id','desc')->limit(1)->first();
		$maxpurchasepaydate=AccountingAccountsTransaction::where('sub_type','purchase_payment')->orderBY('id','desc')->limit(1)->first();

        return view('accounting::transactions.index')
            ->with(compact('business_locations', 'suppliers', 'orderStatuses', 'maxselldate','maxselltxndate', 'maxsellpaydate', 'maxpurchasetxndate', 'maxpurchasedate', 'maxpurchasepaydate'));
    }

    protected function _allSales(){
        $sale_type = 'sell';
        $business_id = request()->session()->get('user.business_id');

        $sells = $this->transactionUtil->getListSells($business_id, $sale_type);
        $sells->groupBy('transactions.id');

        $payment_types = $this->transactionUtil->payment_types(null, true, $business_id);
       // $sales_order_statuses = Transaction::sales_order_statuses();
        $sales_order_statuses = [];

        $datatable = Datatables::of($sells)
                ->addColumn(
                    'action',
                    function ($row) use ($sale_type) {
                        $html = '' ;

                        if (auth()->user()->can("sell.view") || auth()->user()->can("direct_sell.view") || auth()->user()->can("view_own_sell_only")) {
                            $html .= '<a href="#" data-href="' . action([\App\Http\Controllers\SellController::class, 'index'], [$row->id]) . '" class="btn-modal btn btn-info btn-xs" data-container=".view_modal"><i class="fas fa-eye" aria-hidden="true"></i> ' . __("messages.view") . '</a>';
                        }

                        if(auth()->user()->can('accounting.map_transactions')) {
                            //check if mapping already present
                            $is_mapped = AccountingAccountsTransaction::where('transaction_id', $row->id)->exists();

                            if(!$is_mapped){
                                $html .= '<a href="#" 
                                    data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->id . '&type=sell' .'" class="btn-modal btn btn-primary btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.map_transaction') . '</a>';
                            } else {
                                $html .= '<a href="#" 
                                    data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->id . '&type=sell' .'" class="btn-modal btn btn-warning btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.edit_mapping') . '</a>';
                            }
                        }
                        
                        return $html;
                    }
                )
                ->removeColumn('id')
                ->editColumn(
                    'final_total',
                    '<span class="final-total" data-orig-value="{{$final_total}}">@format_currency($final_total)</span>'
                )
                ->editColumn(
                    'tax_amount',
                    '<span class="total-tax" data-orig-value="{{$tax_amount}}">@format_currency($tax_amount)</span>'
                )
                ->editColumn(
                    'total_paid',
                    '<span class="total-paid" data-orig-value="{{$total_paid}}">@format_currency($total_paid)</span>'
                )
                ->editColumn(
                    'total_before_tax',
                    '<span class="total_before_tax" data-orig-value="{{$total_before_tax}}">@format_currency($total_before_tax)</span>'
                )
                ->editColumn(
                    'discount_amount',
                    function ($row) {
                        $discount = !empty($row->discount_amount) ? $row->discount_amount : 0;

                        if (!empty($discount) && $row->discount_type == 'percentage') {
                            $discount = $row->total_before_tax * ($discount / 100);
                        }

                        return '<span class="total-discount" data-orig-value="' . $discount . '">' . $this->transactionUtil->num_f($discount, true) . '</span>';
                    }
                )
                ->editColumn('transaction_date', '{{@format_datetime($transaction_date)}}')
                ->editColumn(
                    'payment_status',
                    function ($row) {
                        $payment_status = Transaction::getPaymentStatus($row);
                        return (string) view('sell.partials.payment_status', ['payment_status' => $payment_status, 'id' => $row->id]);
                    }
                )
                ->addColumn('total_remaining', function ($row) {
                    $total_remaining =  $row->final_total - $row->total_paid;
                    $total_remaining_html = '<span class="payment_due" data-orig-value="' . $total_remaining . '">' . $this->transactionUtil->num_f($total_remaining, true) . '</span>';
                    return $total_remaining_html;
                })
                ->addColumn('total_remaining', function ($row) {
                    $total_remaining =  $row->final_total - $row->total_paid;
                    $total_remaining_html = '<span class="payment_due" data-orig-value="' . $total_remaining . '">' . $this->transactionUtil->num_f($total_remaining, true) . '</span>';
                    return $total_remaining_html;
                })
                ->editColumn('invoice_no', function ($row) {
                    $invoice_no = $row->invoice_no;
                    if (!empty($row->woocommerce_order_id)) {
                        $invoice_no .= ' <i class="fab fa-wordpress text-primary no-print" title="' . __('lang_v1.synced_from_woocommerce') . '"></i>';
                    }
                    if (!empty($row->return_exists)) {
                        $invoice_no .= ' &nbsp;<small class="label bg-red label-round no-print" title="' . __('lang_v1.some_qty_returned_from_sell') .'"><i class="fas fa-undo"></i></small>';
                    }
                    if (!empty($row->is_recurring)) {
                        $invoice_no .= ' &nbsp;<small class="label bg-red label-round no-print" title="' . __('lang_v1.subscribed_invoice') .'"><i class="fas fa-recycle"></i></small>';
                    }

                    if (!empty($row->recur_parent_id)) {
                        $invoice_no .= ' &nbsp;<small class="label bg-info label-round no-print" title="' . __('lang_v1.subscription_invoice') .'"><i class="fas fa-recycle"></i></small>';
                    }

                    if (!empty($row->is_export)) {
                        $invoice_no .= '</br><small class="label label-default no-print" title="' . __('lang_v1.export') .'">'.__('lang_v1.export').'</small>';
                    }

                    return $invoice_no;
                })
                
                ->addColumn('conatct_name', '@if(!empty($supplier_business_name)) {{$supplier_business_name}}, <br> @endif {{$name}}')
                ->editColumn('total_items', '{{@format_quantity($total_items)}}')
                ->filterColumn('conatct_name', function ($query, $keyword) {
                    $query->where( function($q) use($keyword) {
                        $q->where('contacts.name', 'like', "%{$keyword}%")
                        ->orWhere('contacts.supplier_business_name', 'like', "%{$keyword}%");
                    });
                })
                ->addColumn('payment_methods', function ($row) use ($payment_types) {
                    $methods = array_unique($row->payment_lines->pluck('method')->toArray());
                    $count = count($methods);
                    $payment_method = '';
                    if ($count == 1) {
                        $payment_method = $payment_types[$methods[0]] ?? '';
                    } elseif ($count > 1) {
                        $payment_method = __('lang_v1.checkout_multi_pay');
                    }

                    $html = !empty($payment_method) ? '<span class="payment-method" data-orig-value="' . $payment_method . '" data-status-name="' . $payment_method . '">' . $payment_method . '</span>' : '';
                    
                    return $html;
                })
                ->editColumn('status', function($row) use($sales_order_statuses){
                    $status = '';

                    if ($row->type == 'sales_order') {
                        
                            $status = '<span class="label  bg-purple" >' . $row->status . '</span>';
                        
                    }

                    return $status;
                });

            $rawColumns = ['final_total', 'action', 'total_paid', 'total_remaining', 'payment_status', 'invoice_no', 'discount_amount', 'tax_amount', 'total_before_tax', 'shipping_status', 'types_of_service_name', 'payment_methods', 'return_due', 'conatct_name', 'status'];
                
            return $datatable->rawColumns($rawColumns)
                      ->make(true);
    }

    protected function _allPayments(){
        $transaction_type = request()->input('transaction_type');
        $business_id = request()->session()->get('user.business_id');

        $query = TransactionPayment::join(
                        'transactions as T',
                        'transaction_payments.transaction_id',
                        '=',
                        'T.id'
                    )
                    ->leftjoin('accounts as A', 'transaction_payments.account_id', '=', 'A.id')
                    ->where('transaction_payments.business_id', $business_id)
                    ->where('T.type', $transaction_type)
                    ->whereNull('transaction_payments.parent_id')
                    ->where('transaction_payments.method', '!=', 'advance')
                    ->leftjoin('contacts as c', 'transaction_payments.payment_for', '=', 'c.id')
                    ->select([
                        'paid_on',
                        'payment_ref_no',
                        'T.ref_no',
                        'T.invoice_no',
                        'T.type',
                        'T.id as transaction_id',
                        // 'A.name as account_name',
                        // 'A.account_number',
                        'transaction_payments.id as payment_id',
                        'transaction_payments.account_id',
                        'c.name as contact_name',
                        'c.type as contact_type',
                        'transaction_payments.is_advance',
                        'transaction_payments.amount',
                        'transaction_payments.id as transaction_payment_id'
                    ]);
        $qq=$query->get();
		//\Log::emergency('PayTxn: '.json_encode($qq));
        return DataTables::of($query)
                ->editColumn('paid_on', function ($row) {
                    return $this->transactionUtil->format_date($row->paid_on, true);
                })
                ->editColumn('amount', function ($row) {
                    return $this->transactionUtil->num_f($row->amount, true);
                })
                ->addColumn('details', function($row){
                    $details =  '';

                    if ($row->contact_type == 'supplier') {
                        $details = '<b>' . __('role.supplier') . ':</b> ' . $row->contact_name; 
                    } else {
                        $details = '<b>' . __('role.customer') . ':</b> ' . $row->contact_name; 
                    }

                    return $details;
                })
                ->addColumn('action', function ($row) use($transaction_type) {
                    $html = '' ;

                    if(auth()->user()->can('accounting.map_transactions')) {
                        //check if mapping already present
                        $is_mapped = AccountingAccountsTransaction::where('transaction_payment_id', $row->transaction_payment_id)->exists();
                        
                        if($transaction_type == 'purchase'){
                            $type_parameter = 'purchase_payment';
                        } elseif($transaction_type == 'sell'){
                            $type_parameter = 'sell_payment';
                        }

                        if(!$is_mapped){
                            $html .= '<a href="#" 
                                data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->transaction_payment_id . '&type=' . $type_parameter .'" class="btn-modal btn btn-primary btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.map_transaction') . '</a>';
                        } else {
                            $html .= '<a href="#" 
                                data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->transaction_payment_id . '&type='. $type_parameter .'" class="btn-modal btn btn-warning btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.edit_mapping') . '</a>';
                        }
                    }

                    return $html;
                    
                })
                ->addColumn('transaction_number', function ($row) {
                    $html = $row->ref_no;
                    if ($row->type == 'sell') {
                        $html = '<button type="button" class="btn btn-link btn-modal"
                                data-href="' . action([\App\Http\Controllers\SellReturnController::class,'show'], [$row->transaction_id]) .'" data-container=".view_modal">' . $row->invoice_no . '</button>';
                    } elseif ($row->type == 'purchase') {
                        $html = '<button type="button" class="btn btn-link btn-modal"
                                data-href="' . action([\App\Http\Controllers\PurchaseController::class,'show'], [$row->transaction_id]) .'" data-container=".view_modal">' . $row->ref_no . '</button>';
                    }
                    return $html;
                })
                ->editColumn('type', function ($row) {
                    $type = $row->type;
                    if ($row->type == 'sell') {
                        $type = __('sale.sale');
                    } elseif ($row->type == 'purchase') {
                        $type = __('lang_v1.purchase');
                    } elseif ($row->type == 'expense') {
                        $type = __('lang_v1.expense');
                    } elseif($row->is_advance == 1) {
                        $type = __('lang_v1.advance');
                    }
                    return $type;
                })
                // ->filterColumn('account', function ($query, $keyword) {
                //     $query->where('A.name', 'like', ["%{$keyword}%"])
                //         ->orWhere('account_number', 'like', ["%{$keyword}%"]);
                // })
                ->filterColumn('transaction_number', function ($query, $keyword) {
                    $query->where('T.invoice_no', 'like', ["%{$keyword}%"])
                        ->orWhere('T.ref_no', 'like', ["%{$keyword}%"]);
                })
                ->rawColumns(['action', 'transaction_number', 'details'])
                ->make(true);
    }

    protected function _allPurchasePayments(){
        $transaction_type = request()->input('transaction_type');
        $business_id = request()->session()->get('user.business_id');

        $query = TransactionPayment::join(
                        'transactions as T',
                        'transaction_payments.transaction_id',
                        '=',
                        'T.id'
                    )
                    ->leftjoin('accounts as A', 'transaction_payments.account_id', '=', 'A.id')
                    ->where('transaction_payments.business_id', $business_id)
                    ->where('T.type', $transaction_type)
                    //->whereNull('transaction_payments.parent_id')
                    ->where('transaction_payments.method', '!=', 'advance')
                    ->leftjoin('contacts as c', 'transaction_payments.payment_for', '=', 'c.id')
                    ->select([
                        'paid_on',
                        'payment_ref_no',
                        'T.ref_no',
                        'T.invoice_no',
                        'T.type',
                        'T.id as transaction_id',
                        // 'A.name as account_name',
                        // 'A.account_number',
                        'transaction_payments.id as payment_id',
                        'transaction_payments.account_id',
                        'c.name as contact_name',
                        'c.type as contact_type',
                        'transaction_payments.is_advance',
                        'transaction_payments.amount',
                        'transaction_payments.id as transaction_payment_id'
                    ]);
        $qq=$query->get();
		//\Log::emergency('PayTxn: '.json_encode($qq));
        return DataTables::of($query)
                ->editColumn('paid_on', function ($row) {
                    return $this->transactionUtil->format_date($row->paid_on, true);
                })
                ->editColumn('amount', function ($row) {
                    return $this->transactionUtil->num_f($row->amount, true);
                })
                ->addColumn('details', function($row){
                    $details =  '';

                    if ($row->contact_type == 'supplier') {
                        $details = '<b>' . __('role.supplier') . ':</b> ' . $row->contact_name; 
                    } else {
                        $details = '<b>' . __('role.customer') . ':</b> ' . $row->contact_name; 
                    }

                    return $details;
                })
                ->addColumn('action', function ($row) use($transaction_type) {
                    $html = '' ;

                    if(auth()->user()->can('accounting.map_transactions')) {
                        //check if mapping already present
                        $is_mapped = AccountingAccountsTransaction::where('transaction_payment_id', $row->transaction_payment_id)->exists();
                        
                        if($transaction_type == 'purchase'){
                            $type_parameter = 'purchase_payment';
                        } elseif($transaction_type == 'sell'){
                            $type_parameter = 'sell_payment';
                        }

                        if(!$is_mapped){
                            $html .= '<a href="#" 
                                data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->transaction_payment_id . '&type=' . $type_parameter .'" class="btn-modal btn btn-primary btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.map_transaction') . '</a>';
                        } else {
                            $html .= '<a href="#" 
                                data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->transaction_payment_id . '&type='. $type_parameter .'" class="btn-modal btn btn-warning btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.edit_mapping') . '</a>';
                        }
                    }

                    return $html;
                    
                })
                ->addColumn('transaction_number', function ($row) {
                    $html = $row->ref_no;
                    if ($row->type == 'sell') {
                        $html = '<button type="button" class="btn btn-link btn-modal"
                                data-href="' . action([\App\Http\Controllers\SellReturnController::class,'show'], [$row->transaction_id]) .'" data-container=".view_modal">' . $row->invoice_no . '</button>';
                    } elseif ($row->type == 'purchase') {
                        $html = '<button type="button" class="btn btn-link btn-modal"
                                data-href="' . action([\App\Http\Controllers\PurchaseController::class,'show'], [$row->transaction_id]) .'" data-container=".view_modal">' . $row->ref_no . '</button>';
                    }
                    return $html;
                })
                ->editColumn('type', function ($row) {
                    $type = $row->type;
                    if ($row->type == 'sell') {
                        $type = __('sale.sale');
                    } elseif ($row->type == 'purchase') {
                        $type = __('lang_v1.purchase');
                    } elseif ($row->type == 'expense') {
                        $type = __('lang_v1.expense');
                    } elseif($row->is_advance == 1) {
                        $type = __('lang_v1.advance');
                    }
                    return $type;
                })
                // ->filterColumn('account', function ($query, $keyword) {
                //     $query->where('A.name', 'like', ["%{$keyword}%"])
                //         ->orWhere('account_number', 'like', ["%{$keyword}%"]);
                // })
                ->filterColumn('transaction_number', function ($query, $keyword) {
                    $query->where('T.invoice_no', 'like', ["%{$keyword}%"])
                        ->orWhere('T.ref_no', 'like', ["%{$keyword}%"]);
                })
                ->rawColumns(['action', 'transaction_number', 'details'])
                ->make(true);
    }

    protected function _allPurchases(){
        $business_id = request()->session()->get('user.business_id');
        $purchases = $this->transactionUtil->getListPurchases($business_id);

        return Datatables::of($purchases)
                ->addColumn('action', function ($row) {
                    
                    $html = '' ;

                    if (auth()->user()->can("purchase.view")) {
                        $html .= '<a href="#" data-href="' . action([\App\Http\Controllers\PurchaseController::class, 'show'], [$row->id]) . '" class="btn-modal btn btn-info btn-xs" data-container=".view_modal"><i class="fas fa-eye" aria-hidden="true"></i> ' . __("messages.view") . '</a>';
                    }
                    if(auth()->user()->can('accounting.map_transactions')) {
                        //check if mapping already present
                        $is_mapped = AccountingAccountsTransaction::where('transaction_id', $row->id)->exists();

                        if(!$is_mapped){
                            $html .= '<a href="#" 
                                data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->id . '&type=purchase' .'" class="btn-modal btn btn-primary btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.map_transaction') . '</a>';
                        } else {
                            $html .= '<a href="#" 
                                data-href="' . action("\Modules\Accounting\Http\Controllers\TransactionController@map") . '?id=' . $row->id . '&type=purchase' .'" class="btn-modal btn btn-warning btn-xs mt-10" data-container=".view_modal"><i class="fas fa-link"></i> ' . __('accounting::lang.edit_mapping') . '</a>';
                        }
                    }
                    
                    return $html;
                })
                ->removeColumn('id')
                ->editColumn('ref_no', function ($row) {
                    return !empty($row->return_exists) ? $row->ref_no . ' <small class="label bg-red label-round no-print" title="' . __('lang_v1.some_qty_returned') .'"><i class="fas fa-undo"></i></small>' : $row->ref_no;
                })
                ->editColumn(
                    'final_total',
                    '<span class="final_total" data-orig-value="{{$final_total}}">@format_currency($final_total)</span>'
                )
                ->editColumn('transaction_date', '{{@format_datetime($transaction_date)}}')
                ->editColumn('name', '@if(!empty($supplier_business_name)) {{$supplier_business_name}}, <br> @endif {{$name}}')
                ->editColumn(
                    'status',
                    '<span class="label @transaction_status($status) status-label" data-status-name="{{__(\'lang_v1.\' . $status)}}" data-orig-value="{{$status}}">{{__(\'lang_v1.\' . $status)}}
                        </span>'
                )
                ->editColumn(
                    'payment_status',
                    function ($row) {
                        $payment_status = Transaction::getPaymentStatus($row);
                        return (string) view('sell.partials.payment_status', ['payment_status' => $payment_status, 'id' => $row->id, 'for_purchase' => true]);
                    }
                )
                ->addColumn('payment_due', function ($row) {
                    $due = $row->final_total - $row->amount_paid;
                    $due_html = '<strong>' . __('lang_v1.purchase') .':</strong> <span class="payment_due" data-orig-value="' . $due . '">' . $this->transactionUtil->num_f($due, true) . '</span>';

                    if (!empty($row->return_exists)) {
                        $return_due = $row->amount_return - $row->return_paid;
                        $due_html .= '<br><strong>' . __('lang_v1.purchase_return') .':</strong> <span class="purchase_return" data-orig-value="' . $return_due . '">' . $this->transactionUtil->num_f($return_due, true) . '</span>';
                    }
                    return $due_html;
                })
                ->rawColumns(['final_total', 'action', 'payment_due', 'payment_status', 'status', 'ref_no', 'name'])
                ->make(true);
    }

    public function map(Request $request){
		//Mapping Process
		/*
		Make it automatic
		For sales
			Debit Sales Tax Payable with sale tax value
			Debit Accounts Receivables with total sales less tax value
			Credit Sales Account 
		For Sale Payment 
			Debit Cash/Bank
			Credit Accounts Receivables with payment (May proof hard to credit tax payable and may it be passed manually at end of month)
			
		For Purchases
		For Purchase Payment 
		*/
        $business_id = request()->session()->get('user.business_id');

        if (!(auth()->user()->can('superadmin') || 
            $this->moduleUtil->hasThePermissionInSubscription($business_id, 'accounting_module')) || 
            !(auth()->user()->can('accounting.map_transactions')) ) {
            abort(403, 'Unauthorized action.');
        }
   
        if (request()->ajax()) {

            $type = $request->get('type');
            $id = $request->get('id');
            
            if($type == 'sell'){
                $transaction = Transaction::where('id', $id)->where('business_id', $business_id)
                                    ->firstorFail();
                
                //setting defaults
                //if paid - Payment account = Sales
                //Deposit to = Account Receivable
                //Get all payment lines and map for each

                //if not paid - Payment account = Sales
                //Deposit to = Account Receivable

                $existing_payment = AccountingAccountsTransaction::where('transaction_id', $id)
                                        ->where('map_type', 'payment_account')
                                        ->first();
                $existing_deposit = AccountingAccountsTransaction::where('transaction_id', $id)
                                        ->where('map_type', 'deposit_to')
                                        ->first();
                $default_payment_account = !empty($existing_payment) ? AccountingAccount::find($existing_payment->accounting_account_id) : null;
                $default_deposit_to = !empty($existing_deposit) ? AccountingAccount::find($existing_deposit->accounting_account_id) : null;

                return view('accounting::transactions.map')
                        ->with(compact('transaction', 'type', 'default_payment_account', 'default_deposit_to'));
            } elseif(in_array($type, ['purchase_payment', 'sell_payment'])){
                $transaction_payment = TransactionPayment::where('id', $id)->where('business_id', $business_id)
                                    ->firstorFail();
                
                $existing_payment = AccountingAccountsTransaction::where('transaction_payment_id', $id)
                                    ->where('map_type', 'payment_account')
                                    ->first();
                $existing_deposit = AccountingAccountsTransaction::where('transaction_payment_id', $id)
                                    ->where('map_type', 'deposit_to')
                                    ->first();
                $default_payment_account = !empty($existing_payment) ? AccountingAccount::find($existing_payment->accounting_account_id) : null;
                $default_deposit_to = !empty($existing_deposit) ? AccountingAccount::find($existing_deposit->accounting_account_id) : null;

                return view('accounting::transactions.map')
                            ->with(compact('transaction_payment', 'type', 'default_payment_account', 'default_deposit_to'));
            } elseif($type == 'purchase'){
                $transaction = Transaction::where('id', $id)->where('business_id', $business_id)
                                    ->firstorFail();
                
                //setting defaults
                //if paid - Payment account = Sales
                //Deposit to = Account Receivable
                //Get all payment lines and map for each

                //if not paid - Payment account = Sales
                //Deposit to = Account Receivable

                $existing_payment = AccountingAccountsTransaction::where('transaction_id', $id)
                                        ->where('map_type', 'payment_account')
                                        ->first();
                $existing_deposit = AccountingAccountsTransaction::where('transaction_id', $id)
                                        ->where('map_type', 'deposit_to')
                                        ->first();
                $default_payment_account = !empty($existing_payment) ? AccountingAccount::find($existing_payment->accounting_account_id) : null;
                $default_deposit_to = !empty($existing_deposit) ? AccountingAccount::find($existing_deposit->accounting_account_id) : null;

                return view('accounting::transactions.map')
                        ->with(compact('transaction', 'type', 'default_payment_account', 'default_deposit_to'));
            }
        }
    }

    public function autoMap(Request $request,$type){
        $business_id = request()->session()->get('user.business_id');

        if (request()->ajax()) { 
            
                return view('accounting::transactions.autoMap')
                        ->with(compact('type'));
        }
    }

    public function saveMap(Request $request){
        $business_id = request()->session()->get('user.business_id');
        
        if (!(auth()->user()->can('superadmin') || 
            $this->moduleUtil->hasThePermissionInSubscription($business_id, 'accounting_module')) || 
            !(auth()->user()->can('accounting.map_transactions')) ) {
            abort(403, 'Unauthorized action.');
        }

        try {
            if (request()->ajax()) {
                DB::beginTransaction();

                $type = $request->get('type');
                $id = $request->get('id');
                $user_id = request()->session()->get('user.id');

                $deposit_to = $request->get('deposit_to');
                $payment_account = $request->get('payment_account');

                if($type == 'sell'){
                    $transaction = Transaction::where('business_id', $business_id)->where('id', $id)->firstorFail();

                    //$payment_account will increase = sales = credit
                    $payment_data = [
                            'accounting_account_id'=> $payment_account, 
                            'transaction_id' => $id,
                            'transaction_payment_id' => null,
                            'amount' => $transaction->final_total,
                            'type' => 'credit',
                            'sub_type' => $type,
                            'map_type' => 'payment_account',
                            'created_by' => $user_id,
                            'operation_date' => \Carbon::now(),
                        ];

                    //Deposit to will increase = debit
                    $deposit_data = [
                            'accounting_account_id'=> $deposit_to, 
                            'transaction_id' => $id,
                            'transaction_payment_id' => null,
                            'amount' => $transaction->final_total,
                            'type' => 'debit',
                            'sub_type' => $type,
                            'map_type' => 'deposit_to',
                            'created_by' => $user_id,
                            'operation_date' => \Carbon::now(),
                        ];
                    
						$transaction->account_synced=1;
						$transaction->save();
                } elseif(in_array($type, ['purchase_payment', 'sell_payment'])){
                    $transaction_payment = TransactionPayment::where('id', $id)->where('business_id', $business_id)
                                    ->firstorFail();

                    //$payment_account will increase = sales = credit
                    $payment_data = [
                        'accounting_account_id'=> $payment_account,
                        'transaction_id' => null,
                        'transaction_payment_id' => $id,
                        'amount' => $transaction_payment->amount,
                        'type' => 'credit',
                        'sub_type' => $type,
                        'map_type' => 'payment_account',
                        'created_by' => $user_id,
                        'operation_date' => \Carbon::now(),
                    ];

                    //Deposit to will increase = debit
                    $deposit_data = [
                            'accounting_account_id'=> $deposit_to,
                            'transaction_id' => null,
                            'transaction_payment_id' => $id,
                            'amount' => $transaction_payment->amount,
                            'type' => 'debit',
                            'sub_type' => $type,
                            'map_type' => 'deposit_to',
                            'created_by' => $user_id,
                            'operation_date' => \Carbon::now(),
                        ];
						$transaction_payment->account_synced=1;
						$transaction_payment->save();
                }elseif($type == 'purchase'){
                    $transaction = Transaction::where('business_id', $business_id)->where('id', $id)->firstorFail();

                    //$payment_account will increase = sales = credit
                    $payment_data = [
                            'accounting_account_id'=> $payment_account, 
                            'transaction_id' => $id,
                            'transaction_payment_id' => null,
                            'amount' => $transaction->final_total,
                            'type' => 'credit',
                            'sub_type' => $type,
                            'map_type' => 'payment_account',
                            'created_by' => $user_id,
                            'operation_date' => \Carbon::now(),
                        ];

                    //Deposit to will increase = debit
                    $deposit_data = [
                            'accounting_account_id'=> $deposit_to, 
                            'transaction_id' => $id,
                            'transaction_payment_id' => null,
                            'amount' => $transaction->final_total,
                            'type' => 'debit',
                            'sub_type' => $type,
                            'map_type' => 'deposit_to',
                            'created_by' => $user_id,
                            'operation_date' => \Carbon::now(),
                        ];
						$transaction->account_synced=1;
						$transaction->save();
                    
                }

                AccountingAccountsTransaction::updateOrCreateMapTransaction($payment_data);
                AccountingAccountsTransaction::updateOrCreateMapTransaction($deposit_data);
                
                DB::commit();

                $output = ['success' => true,
                            'msg' => __("lang_v1.updated_success")
                        ];
            }
        } catch (\Exception $e) {
            print_r($e->getMessage());exit;
            DB::rollBack();

            \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());

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

        return $output;
    }

    public function saveAutoMap(Request $request){
        $business_id = request()->session()->get('user.business_id');
		$type=$request->input('type'); 
		//Mapping Process
		/*
		Make it automatic
		For sales
			Debit Accounts Receivables with total sales 
			Credit Sales Account Less tax value
			Credit Tax Account
		For Sale Payment 
			Debit Cash/Bank
			Credit Accounts Receivables with payment (May proof hard to credit tax payable and may it be passed manually at end of month)
			
		For Purchases
			Debit Purchases Account less tax
			Debit Purchase Tax Payable with Purchase tax value
			Credit Accounts payable with total 
		For Purchase Payment
			Debit Accounts Payable
			Credit Cash/Bank
		*/
        
        try {
            if (request()->ajax()) {
                DB::beginTransaction();
                $id = 0;
                $user_id = request()->session()->get('user.id');
				\Log::emergency('Type sent: '.$type);
                if($type == 'sell'){
					//Delete where non existent
					$nonexistenttxns=DB::table('accounting_accounts_transactions')->where('sub_type','sell')
									->whereNotIn('transaction_id',function($query){
										$query->select('id')->from('transactions')->where('type','sell');
									})->delete();
					//Insert where not exist	
                    $transactions = Transaction::where('business_id', $business_id)
									->where('account_synced','=', '0')
									->where('type','=', 'sell')
									->where('is_quotation','=', '0')
									->where('status','=', 'final')
									->whereNotIn('id',function($query){
										$query->select('transaction_id')->from('accounting_accounts_transactions')->where('sub_type','sell');
									})
									->orderBY('id','asc')->limit(5000)->get(); 
									
					foreach($transactions as $rec){
						$transaction=Transaction::find($rec->id);
					//\Log::emergency('payment_data'.json_encode($payment_data)); 
						//Get Sell Lines 
						$txnselllines=TransactionSellLine::where('transaction_id',$transaction->id)->whereNull('parent_sell_line_id')->select('unit_price',
								'quantity',
								'unit_price_inc_tax',
								DB::raw("quantity*unit_price as beforetax"),
								DB::raw("quantity*(unit_price_inc_tax-unit_price) as taxamount"),
								)
								->get();
					$beforetax=0;
					$taxtotal=0;
						foreach($txnselllines as $selline){
							$beforetax=$beforetax+$selline->beforetax;
							$taxtotal=$taxtotal+$selline->taxamount;
						}
						//Credit Sales Account Less Tax
						$payment_data = [
								'accounting_account_id'=> 22,//sales account is id 22 
								'transaction_id' => $transaction->id,
								'transaction_payment_id' => null,
								'amount' => $transaction->final_total-$taxtotal,
								'type' => 'credit',
								'sub_type' => $type,
								'map_type' => 'payment_account',
								'created_by' => $user_id,
								'operation_date' => $transaction->transaction_date,
							];
						//Credit Sales Tax
						$deposited_data= [
								'accounting_account_id'=> 86,//default id for sales tax 
								'transaction_id' => $transaction->id,
								'transaction_payment_id' => null,
								'amount' => $taxtotal,
								'type' => 'credit',
								'sub_type' => $type,
								'map_type' => 'payment_account',
								'created_by' => $user_id,
								'operation_date' =>  $transaction->transaction_date,
							];
						//Debit Account Receivables
						$deposit_data = [
								'accounting_account_id'=> 88,//default id for Account Receivables 
								'transaction_id' => $transaction->id,
								'transaction_payment_id' => null,
								'amount' => $transaction->final_total,
								'type' => 'debit',
								'sub_type' => $type,
								'map_type' => 'deposit_to',
								'created_by' => $user_id,
								'operation_date' => $transaction->transaction_date,
							]; 
						//\Log::emergency('deposit_data'.json_encode($deposit_data)); 
						//\Log::emergency('deposited_data'.json_encode($deposited_data));
						$txn=AccountingAccountsTransaction::create($payment_data); 
						$txn=AccountingAccountsTransaction::create($deposit_data);
						$txn=AccountingAccountsTransaction::create($deposited_data);
							
							$transaction->account_synced=1;
							$transaction->save();
					}
                    //$transaction = Transaction::where('business_id', $business_id)->where('id', $id)->firstorFail();
                    
                }elseif($type == 'purchase'){
					//Delete where non existent
					$nonexistenttxns=DB::table('accounting_accounts_transactions')->where('sub_type','purchase')
									->whereNotIn('transaction_id',function($query){
										$query->select('id')->from('transactions')->where('type','purchase');
									})->delete();
					//Insert where not exist	
                    $transactions = Transaction::where('business_id', $business_id)
									->where('account_synced','=', '0')
									->where('type','=', 'purchase')
									->where('status','=', 'received')
									->whereNotIn('id',function($query){
										$query->select('transaction_id')->from('accounting_accounts_transactions')->where('sub_type','purchase');
									})
									->orderBY('id','asc')->limit(5000)->get();
					foreach($transactions as $rec){
						$transaction=Transaction::find($rec->id);
						//Credit Accounts payable
						$payment_data = [
								'accounting_account_id'=> 1,//sales account is id 22 
								'transaction_id' => $transaction->id,
								'transaction_payment_id' => null,
								'amount' => $transaction->final_total,
								'type' => 'credit',
								'sub_type' => $type,
								'map_type' => 'payment_account',
								'created_by' => $user_id,
								'operation_date' => $transaction->transaction_date,
							];
						//Get purchase Lines 
						$txnselllines=PurchaseLine::where('transaction_id',$transaction->id)
								->select('purchase_price',
								'quantity',
								'purchase_price_inc_tax',
								DB::raw("quantity*purchase_price as beforetax"),
								DB::raw("quantity*(purchase_price_inc_tax-purchase_price) as taxamount"),
								)
								->get();
					$beforetax=0;
					$taxtotal=0;
						foreach($txnselllines as $selline){
							$beforetax=$beforetax+$selline->beforetax;
							$taxtotal=$taxtotal+$selline->taxamount;
						}
						/*
						Debit Purchases Account less tax
						Debit Purchase Tax Payable with Purchase tax value
						*/
						$deposit_data = [
								'accounting_account_id'=> 28,//default id for purchases
								'transaction_id' => $transaction->id,
								'transaction_payment_id' => null,
								'amount' => $beforetax,
								'type' => 'debit',
								'sub_type' => $type,
								'map_type' => 'deposit_to',
								'created_by' => $user_id,
								'operation_date' => $transaction->transaction_date,
							]; 
						//\Log::emergency('payment_data'.json_encode($payment_data)); 
						//\Log::emergency('deposit_data'.json_encode($deposit_data)); 
						//Debit Sales Tax
						
						$deposited_data= [
								'accounting_account_id'=> 86,//default id for VAT tax 
								'transaction_id' => $transaction->id,
								'transaction_payment_id' => null,
								'amount' => $taxtotal,
								'type' => 'debit',
								'sub_type' => $type,
								'map_type' => 'deposit_to',
								'created_by' => $user_id,
								'operation_date' =>  $transaction->transaction_date,
							];
						//\Log::emergency('deposited_data'.json_encode($deposited_data));
						$txn=AccountingAccountsTransaction::create($payment_data); 
						$txn=AccountingAccountsTransaction::create($deposit_data);
						$txn=AccountingAccountsTransaction::create($deposited_data);
							
							$transaction->account_synced=1;
							$transaction->save();
						//\Log::emergency('almost committing');
					}
                    
                }elseif($type == 'sell_payment'){
					//Delete where non existent
					$nonexistenttxns=DB::table('accounting_accounts_transactions')->where('sub_type','sell_payment')
									->whereNotIn('transaction_payment_id',function($query){
										$query->select('transaction_payments.id')->from('transaction_payments')
											->join('transactions as txn','txn.id','=','transaction_payments.transaction_id')
											->where('txn.type','=','sell');
									})->delete();
				//\Log::emergency('Type sentagd: '.$type);
					//Insert where not exist	
						//\Log::emergency('sell_payment here');
                    $transaction_payment = TransactionPayment::join('transactions as txn','txn.id','=','transaction_payments.transaction_id')
						//->whereNotNull('transaction_id')
						->where('transaction_payments.account_synced','=', '0')
						->where('txn.type','=','sell')
						->where('txn.business_id', $business_id)
						->whereNotIn('transaction_payments.id',function($query){
							$query->select('transaction_payment_id')->from('accounting_accounts_transactions')->where('sub_type','sell_payment');
						})
						->select('transaction_payments.id')
						->orderBY('transaction_payments.id','asc')->limit(5000)
						->get(); 
						\Log::emergency('transaction_payment'.json_encode($transaction_payment));
					foreach($transaction_payment as $rec){
						$transaction=TransactionPayment::find($rec->id);
						//\Log::emergency('transaction'.json_encode($transaction));
						//Credit Accounts Receivable
						$payment_data = [
								'accounting_account_id'=> 88,//sales account is id 22 
								'transaction_id' => null,
								'transaction_payment_id' => $transaction->id,
								'amount' => $transaction->amount,
								'type' => 'credit',
								'sub_type' => $type,
								'map_type' => 'payment_account',
								'created_by' => $user_id,
								'operation_date' => $transaction->paid_on,
							];
						//debit Cash or bank //Loop through method
						$accid=75;//Cash and cash equivalent
						if(!empty($transaction->account_id)){
							$checkaccount=DB::table('accounts')->find($transaction->account_id);
							if($checkaccount){
								$accountingrec=AccountingAccount::where('account_primary_type','=','asset')->where('name','=',$checkaccount->name)->first();
								if($accountingrec){
									$accid=$accountingrec->id;
								}
							}
						}
						$deposit_data = [
								'accounting_account_id'=> $accid,
								'transaction_id' => null,
								'transaction_payment_id' => $transaction->id,
								'amount' => $transaction->amount,
								'type' => 'debit',
								'sub_type' => $type,
								'map_type' => 'deposit_to',
								'created_by' => $user_id,
								'operation_date' => $transaction->paid_on,
							];
						$txn=AccountingAccountsTransaction::create($payment_data); 
						$txn=AccountingAccountsTransaction::create($deposit_data);
							
							$transaction->account_synced=1;
							$transaction->save();
						
					}
					
				}elseif($type == 'purchase_payment'){
					/*
					Debit Accounts Payable
					Credit Cash/Bank
					*/
						//\Log::emergency('purchase_payment here');
					//Delete where non existent
					$nonexistenttxns=DB::table('accounting_accounts_transactions')->where('sub_type','purchase_payment')
									->whereNotIn('transaction_payment_id',function($query){
										$query->select('transaction_payments.id')->from('transaction_payments')
											->join('transactions as txn','txn.id','=','transaction_payments.transaction_id')
											->where('txn.type','=','purchase');
									})->delete();
					//Insert where not exist	
                    $transaction_payment = TransactionPayment::join('transactions as txn','txn.id','=','transaction_payments.transaction_id')
						//->whereNotNull('transaction_id')
						->where('transaction_payments.account_synced','=', '0')
						->where('txn.type','=','purchase')
						->where('txn.business_id', $business_id)
						->whereNotIn('transaction_payments.id',function($query){
							$query->select('transaction_payment_id')->from('accounting_accounts_transactions')->where('sub_type','purchase_payment');
						})
						->select('transaction_payments.id')
						->orderBY('transaction_payments.id','asc')->limit(5000)
						->get(); 
						\Log::emergency('transaction_payment'.json_encode($transaction_payment));
					foreach($transaction_payment as $rec){
						$transaction=TransactionPayment::find($rec->id);
						//\Log::emergency('transaction'.json_encode($transaction));
						//debit Accounts payable
						$deposit_data = [
								'accounting_account_id'=> 1,//sales account is id 22 
								'transaction_id' => null,
								'transaction_payment_id' => $transaction->id,
								'amount' => $transaction->amount,
								'type' => 'debit',
								'sub_type' => $type,
								'map_type' => 'deposit_to',
								'created_by' => $user_id,
								'operation_date' => $transaction->paid_on,
							];
						//cred Cash or bank //Loop through method
						$accid=75;//Cash and cash equivalent
						if(!empty($transaction->account_id)){
							$checkaccount=DB::table('accounts')->find($transaction->account_id);
							if($checkaccount){
								$accountingrec=AccountingAccount::where('account_primary_type','=','asset')->where('name','=',$checkaccount->name)->first();
								if($accountingrec){
									$accid=$accountingrec->id;
								}
							}
						}elseif(!empty($transaction->parent_id)){
							$checkaccount=DB::table('accounts')->find($transaction->parent_id);
							if($checkaccount){
								$accountingrec=AccountingAccount::where('account_primary_type','=','asset')->where('name','=',$checkaccount->name)->first();
								if($accountingrec){
									$accid=$accountingrec->id;
								}
							}
						}
						$payment_data = [
								'accounting_account_id'=> $accid,
								'transaction_id' => null,
								'transaction_payment_id' => $transaction->id,
								'amount' => $transaction->amount,
								'type' => 'credit',
								'sub_type' => $type,
								'map_type' => 'payment_account',
								'created_by' => $user_id,
								'operation_date' => $transaction->paid_on,
							];
						$txn=AccountingAccountsTransaction::create($payment_data); 
						$txn=AccountingAccountsTransaction::create($deposit_data);
							
							$transaction->account_synced=1;
							$transaction->save();
						
					}
					
				}
                
				DB::commit();

                $output = ['success' => true,
                            'msg' =>'Automatic Mapping Successfully done '
                        ];
            }
        } catch (\Exception $e) {
            print_r($e->getMessage());exit;
            DB::rollBack();

            \Log::emergency("File:" . $e->getFile(). "Line:" . $e->getLine(). "Message:" . $e->getMessage());

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

        return $output;
    }


    /**
     * Show the form for creating a new resource.
     * @return Response
     */
    public function create()
    {
        return view('accounting::create');
    }

    /**
     * Store a newly created resource in storage.
     * @param Request $request
     * @return Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Show the specified resource.
     * @param int $id
     * @return Response
     */
    public function show($id)
    {
        return view('accounting::show');
    }

    /**
     * Show the form for editing the specified resource.
     * @param int $id
     * @return Response
     */
    public function edit($id)
    {
        return view('accounting::edit');
    }

    /**
     * Update the specified resource in storage.
     * @param Request $request
     * @param int $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Response
     */
    public function destroy($id)
    {
        //
    }
}
