<?php

namespace App\Http\Controllers;

use App\Models\Account;
use App\Models\AccountingGroup;
use App\Models\AccountTransaction;
use App\Models\AcReceipt;
use App\Models\AcReceiptDetail;
use App\Models\IpdAdmission;
use App\Models\MenuModelPermission;
use App\Models\OpdBookings;
use App\Models\SaleInvoice;
use App\Models\Sales\SaleReturns;
use App\Models\VoucherCollection;
use App\Models\VoucherCollectionDetail;
use App\Models\VoucherMaster;
use App\Models\VoucherType;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use App\Traits\TransactionSummeryTrait;
use App\Traits\AcReceiptAndTransactionAllTrait;

class BillCollectionController extends Controller
{
    use TransactionSummeryTrait,AcReceiptAndTransactionAllTrait;

    public function collection($id,$voucher_type,$payment_type='')
    {
        $data = [];
        if($voucher_type=="pathology")
        {
            $moduleCode = 'PATHOLOGY';
            $slip_url   = 'pathology-invoice';
        }
        elseif($voucher_type=="ipd-invoice"){
            $moduleCode = 'IPD_INVOICE';
            $slip_url   = 'ipd-invoice';
        }
        elseif($voucher_type=="sales"){
            $moduleCode = 'SALES';
            $slip_url   = 'sale-invoice';
        }
        else
        {
            $moduleCode = 'OPD_BOOKING';
            $slip_url   = 'opd-bookings.slip';
        }

        if($voucher_type=="opd-booking" || $payment_type=="advance")
        {
            $sale_invoice = OpdBookings::select(['id',
                                                 'patient_id',
                                                'total_billing as billing_amount',
                                                'special_discount as discount_amount',
                                                'amount_recieved as received_amount',
                                                'booking_no as voucher_type_invoice_no',
                                                'due_balance_amount as due_amount',
                                                'booking_date_time as invoice_date'])
                                                ->with('getPatient')->find($id);
            $AcReceipt = AcReceipt::select(['id', 'voucher_id'])
            ->with(['accountReceiptReceivedAmount'])
            ->where(['module_code' => 'OPD_BOOKING', 'voucher_id' => $id])
            ->get();
        }
        if ($voucher_type == "ipd-invoice") {
            $IpdAdmission = IpdAdmission::find($id);
            $sale_invoice = SaleInvoice::where('id', $IpdAdmission->sale_invoice_id)
                ->first();
            if (!$sale_invoice) {
                // If $sale_invoice is null, redirect back
                return redirect()->back()->with('error', 'Please add the first bill before collecting.');
            }
            $AcReceipt = AcReceipt::select(['id', 'voucher_id'])
                ->with(['accountReceiptReceivedAmount' => function ($query) {
                    $query->sum('amount');
                }])
                ->where(['module_code' => 'OPD_BOOKING', 'voucher_id' => $id])
                ->get();

            $id = $IpdAdmission->sale_invoice_id;
            $sale_invoice->id = $id;
        }
        elseif($voucher_type=="pathology")
        {
            $sale_invoice = SaleInvoice::with('getPatient')->find($id);
            $AcReceipt = AcReceipt::select(['id', 'voucher_id'])
            ->with(['accountReceiptReceivedAmount' => function ($query) {
                $query->sum('amount');
            }])
            ->where(['module_code' => 'OPD_BOOKING', 'voucher_id' => $id])
            ->get();
        }
        elseif($voucher_type=="sales")
        {
            $sale_invoice = SaleInvoice::with('getPatient')->find($id);
            $AcReceipt = AcReceipt::select(['id', 'voucher_id'])
            ->with(['accountReceiptReceivedAmount' => function ($query) {
                $query->sum('amount');
            }])
            ->where(['module_code' => 'OPD_BOOKING', 'voucher_id' => $id])
            ->get();
        }

        $creditTransaction = $debitTransaction = [];
        $creditTransaction = [];

        $accounting_group = Account::select([ 'id', 'name', 'account_category_id','accounting_group_id'])
            ->with('chart_of_account_sub_type')
            ->where(function ($query) {
                $query->whereHas('chart_of_account_sub_type', function ($accounting_group) {
                    $accounting_group->where('is_payment_mode', '1');
                });
            })
            ->get();

        $accounting_tds = Account::select(['id', 'name', 'account_category_id','accounting_group_id'])
                            ->where('code','TDS_RECEIVABLE')->first();
        $accounting_expenses = AccountingGroup::whereIN('code',['INDIRECT_EXPENSES'])->with('chart_of_expanses')->get();
        $financialYears = \Session::get('financialyear');
        $redirect = 'lab-billings';
        $returnTransactionSummery  = [];
        if($voucher_type!="opd-booking" || $payment_type!="advance")
        {
            $sale_return_invoice = SaleReturns::select('id')
            ->where('voucher_type_code', 'SALE_RETURN')
            ->where('voucher_type_id',$sale_invoice->id)
            ->first();
            if(isset($sale_return_invoice))
            {
                $returnTransactionSummery = $this->ReturnTransactionSummery($sale_return_invoice->id, 'SALE_RETURN');
            }
        }

        // dd($moduleCode);
        $transactionSummery = $this->TransactionSummery($id,$moduleCode);
        $transactionHistory = $this->transactionHistory($id,$moduleCode);
        $companyDateFormate = phpToJsDateFormat($this->companyDateFormate());

        return view('bill-collection.collect', compact([
            'data',
            'sale_invoice',
            'accounting_group',
            'creditTransaction',
            'debitTransaction',
            'financialYears',
            'redirect',
            'voucher_type',
            'payment_type',
            'moduleCode',
            'slip_url',
            'id',
            'accounting_tds',
            'accounting_expenses',
            'AcReceipt',
            'transactionSummery',
            'transactionHistory',
            'returnTransactionSummery',
            'companyDateFormate'
        ]));
    }


    public function collectionCreate(Request $request, $id = '',$voucher_type,$payment_type='')
    {

        if($voucher_type=='pathology')
        {
            $menuCode          = 'PATHOLOGY';
            $voucher_type_code = 'PATHOLOGY';
            $settlementstatus  = 'Yes';
            $advanceReceived   = 'No';

        }
        elseif($voucher_type=="ipd-invoice"){
                $menuCode          = 'IPD_INVOICE';
                $voucher_type_code = 'IPD_INVOICE';
                $settlementstatus  = 'Yes';
                $advanceReceived   = 'No';
        }
        elseif($voucher_type=="sales"){
            $menuCode          = 'SALES';
            $voucher_type_code = 'SALES';
            $settlementstatus  = 'Yes';
            $advanceReceived   = 'No';
        }
        elseif($voucher_type=='opd-booking'){
            $menuCode          = 'OPD_BOOKING';
            $voucher_type_code = 'OPD_BOOKING';
            if(isset($payment_type) && $payment_type=='advance')
            {
                $settlementstatus  = 'No';
                $advanceReceived   = 'Yes';
            }
            else
            {
                $settlementstatus  = 'Yes';
                $advanceReceived   = 'No';
            }
        }

        $voucher_master = VoucherMaster::with('voucherSeries')->where('voucher_code', 'RECEIPT')->where(['status' => 1])->first();
        // $voucher_type   = VoucherType::with('voucherSeries')->where('code', 'RECEIPT')->where(['status' => 1])->first();

        # last voucher count for main invoice number
        $voucher_count      = AcReceipt::select('last_voucher_count')->orderBy('created_at', 'DESC')->first();
        $last_voucher_count = isset($voucher_count) && isset($voucher_count->last_voucher_count) ? $voucher_count->last_voucher_count + 1 : ($voucher_master->voucherSeries->start_from + 1 ?? 1);

        $main_invoice_no = $this->generateCode(
            $last_voucher_count,
            ($voucher_master->voucherSeries->prefix ?? 'RV'),
            ($voucher_master->voucherSeries->postfix ?? ''),
            ($voucher_master->voucherSeries->separator ?? '-'),
            ($voucher_master->voucherSeries->length ?? 5)
        );

        # last voucher count for main voucher type invoice number
        $voucher_type_last_count      = AcReceipt::select('last_voucher_type_count')->orderBy('created_at', 'DESC')->first();
        $voucher_type_count = isset($voucher_type_last_count) && isset($voucher_type_last_count->last_voucher_type_count) ? $voucher_type_last_count->last_voucher_type_count + 1 : ($voucher_type->voucherSeries->start_from + 1 ?? 1);

        $voucher_type_invoice_no = $this->generateCode(
            $voucher_type_count,
            ($voucher_type->voucherSeries->prefix ?? 'RV'),
            ($voucher_type->voucherSeries->postfix ?? ''),
            ($voucher_type->voucherSeries->separator ?? '-'),
            ($voucher_type->voucherSeries->length ?? 5)
        );

        $module      = MenuModelPermission::where('code',$menuCode)->first();
        $module_id   = $module->id ?? '';
        $module_code = $module->code ?? '';
         /*********************  Spacial Discount Store Calculation ***********************/
        $discount['mode_id']= $request->discount_account_id??'';
        $discount['amount'] = $request->special_discount??'';
         /********************* End Spacial Discount Store Calculation ***********************/

        /*********************  Round Off Store Calculation ***********************/
        $roundOff['mode_id']= $request->round_off_account_id??'';
        $roundOff['amount'] = $request->round_off_amount??'';
        /********************* End  Round Off Store Calculation ***********************/
        if ($request->total_amount > 0) {
            $transactions_no = $this->generateRandomCode();

            $receiptId = $this->createAcReceiptAndTransaction(
                $request->payment_mode_id ?? '',
                $request->account_id,
                $request->total_amount,
                $transaction->id ?? '',
                $id,
                $menuCode,
                $request->payment_mode,
                'received',
                $discount,
                $roundOff
            );
        }


        if(isset($payment_type) && $payment_type=='advance')
        {
            $sale_invoice = OpdBookings::find($id);

            if ($sale_invoice) {
                $received_amount = $sale_invoice->amount_recieved+$request->total_amount;
                $due = $sale_invoice->total_billing - $sale_invoice->special_discount - $received_amount;

                $sale_invoice->update([
                    'due_balance_amount' => $due,
                    'amount_recieved'    => $received_amount,
                ]);
            }
        }
        else
        {
            if($voucher_type=='opd-booking')
            {
                $sale_invoice = OpdBookings::find($id);
                if ($sale_invoice) {
                    $received_amount = $sale_invoice->amount_recieved+$request->total_amount;
                    $due = $sale_invoice->total_billing - $sale_invoice->special_discount - $received_amount;

                    $sale_invoice->update([
                        'due_balance_amount' => $due,
                        'amount_recieved'    => $received_amount,
                    ]);
                }
            }
            $sale_invoice = SaleInvoice::find($id);

            if ($sale_invoice) {
                $received_amount = $sale_invoice->received_amount+$request->total_amount;
                $due = $sale_invoice->billing_amount - $sale_invoice->discount_amount - $received_amount;

                $sale_invoice->update([
                    'due_amount'      => $due,
                    'received_amount' => $received_amount,
                ]);
            }
        }
        \Session::put('redirect', $request->redirect ?? 'receipt');
        $params = [];
        if(isset($receiptId)){
            $params['id'] = $receiptId??'';
        }
        

        if ($voucher_type == 'ipd-invoice') {
            $params['redirect'] = 'ipd-admissions';
        }
        if(isset($request->redirect))
        {
            $params['redirect'] = $request->redirect;
        }
        return redirect()->route('print-receipt-voucher', $params)->with('success', 'Collection Updated Successfully');
    }


    public function collectionEdit(Request $request,$id,$voucher_type,$payment_type='')
    {
        $data = AcReceipt::with('accountReceiptTransaction')->find($id);
        if($voucher_type=="pathology" || $voucher_type=="PATHOLOGY")
        {
            $voucher_type = "pathology";
            $moduleCode   = 'PATHOLOGY';
            $slip_url     = 'pathology-invoice';
        }
        elseif($voucher_type=="ipd-invoice"){
            $moduleCode = 'IPD_INVOICE';
            $slip_url   = 'ipd-invoice';
        }
        elseif($voucher_type=="sales"){
            $moduleCode = 'SALES';
            $slip_url   = 'sale-invoice';
        }
        else
        {
            $moduleCode = 'OPD_BOOKING';
            $slip_url   = 'opd-bookings.slip';
        }
        if($voucher_type=="opd-booking" || $payment_type=="advance")
        {
            $sale_invoice = OpdBookings::select(['id',
                                                 'patient_id',
                                                'total_billing as billing_amount',
                                                'special_discount as discount_amount',
                                                'amount_recieved as received_amount',
                                                'booking_no as main_invoice_no',
                                                'due_balance_amount as due_amount',
                                                'booking_date_time as invoice_date'])
                                                ->with('getPatient')->find($data->voucher_id);
        }
        elseif($voucher_type=="ipd-invoice")
        {

            $sale_invoice = SaleInvoice::where('id', '=', $data->voucher_id)
            ->where('invoice_type', '=', 'ipd-billings')->with('getPatient')->first();
        }
        elseif($voucher_type=="pathology")
        {
            $sale_invoice = SaleInvoice::with('getPatient')->find($data->voucher_id);
        }
        elseif($voucher_type=="sales")
        {
            $sale_invoice = SaleInvoice::with('getPatient')->find($data->voucher_id);
        }

        $creditTransaction = $debitTransaction = [];

        $creditTransaction = [];



        $accounting_group = Account::select([ 'id', 'name', 'account_category_id','accounting_group_id'])
            ->with('chart_of_account_sub_type')
            ->where(function ($query) {
                $query->whereHas('chart_of_account_sub_type', function ($accounting_group) {
                    $accounting_group->where('is_payment_mode', '1');
                });
            })
            ->get();

        $accounting_tds = Account::select(['id', 'name', 'account_category_id','accounting_group_id'])
                            ->where('code','TDS_RECEIVABLE')->first();
        $accounting_expenses = AccountingGroup::whereIN('code',['INDIRECT_EXPENSES'])->with('chart_of_expanses')->get();
        $financialYears = \Session::get('financialyear');
        $redirect = $request->redirect??'lab-billings';
        $transactionSummery = $this->TransactionSummery($data->voucher_id,$moduleCode);
        $transactionHistory = $this->transactionHistory($data->voucher_id,$moduleCode);

        $returnTransactionSummery  = [];
        if($voucher_type!="opd-booking" || $payment_type!="advance")
        {
            $sale_return_invoice = SaleReturns::select('id')
            ->where('voucher_type_code', 'SALE_RETURN')
            ->where('voucher_type_id',$sale_invoice->id)
            ->first();
            if(isset($sale_return_invoice))
            {
                $returnTransactionSummery = $this->ReturnTransactionSummery($sale_return_invoice->id, 'SALE_RETURN');
            }
        }
        $companyDateFormate = phpToJsDateFormat($this->companyDateFormate());
        return view('bill-collection.update', compact([
            'data',
            'sale_invoice',
            'accounting_group',
            'creditTransaction',
            'debitTransaction',
            'financialYears',
            'redirect',
            'voucher_type',
            'payment_type',
            'moduleCode',
            'slip_url',
            'id',
            'accounting_tds',
            'accounting_expenses',
            'transactionSummery',
            'transactionHistory',
            'returnTransactionSummery',
            'companyDateFormate'
        ]));

    }
    public function collectionUpdate(Request $request, $id,$voucher_type)
    {
        if($voucher_type=='pathology')
        {
            $menuCode          = 'PATHOLOGY';
            $voucher_type_code = 'PATHOLOGY';

        }
        elseif($voucher_type=="ipd-invoice"){
                $menuCode          = 'IPD_INVOICE';
                $voucher_type_code = 'IPD_INVOICE';
        }
        elseif($voucher_type=='opd-booking')
        {
            $menuCode          = 'OPD_BOOKING';
            $voucher_type_code = 'OPD_BOOKING';
        }
        elseif($voucher_type=='sales')
        {
            $menuCode          = 'SALES';
            $voucher_type_code = 'SALES';
        }

        $receiptVoucher = AcReceipt::find($id);

        if (!$receiptVoucher) {
            return redirect()->back()->with('error', 'Invalid Receipt Id!');
        }

        $item = [
            'receipt_date'      => date('Y-m-d', strtotime($request->receipt_date)),
            'remarks'           => $request->remarks,
            'financial_year_id' => $request->financial_year_id,
        ];

        $receiptVoucher->update($item);
        $item1 = [
           'amount' => $request->received_amount,
        ];

        $acDEBITReceiptTransaction = AcReceiptDetail::where([
                'transaction_type' => 'CREDIT',
                'voucher_id'       => $id ?? '',
                'voucher_type'     => $menuCode,
                'account_id'       => $request->account_id ?? '',
            ])->first();

        $acDEBITReceiptTransaction->update($item1);

        $voucher_collection = VoucherCollection::where([
            'money_receipt_id'  => $receiptVoucher->id,
        ])->first();

        $voucher_master = VoucherMaster::select('id')
            ->with('voucherSeries')
            ->where('voucher_code', 'RECEIPT')
            ->where(['status' => 1])
            ->first();

        $voucher_collection->update(['updated_by' => Auth::user()->id]);
        $moduleReceipt = MenuModelPermission::where('code', $menuCode)->first();
        $transaction   = AccountTransaction::where([
                    'module_code'       => $menuCode,
                    'voucher_id'        => $id,
                    // 'voucher_type'      => $voucher_type_code, // SALE, PURCHASE, PAYMENT
                    'transaction_type'  => 'DEBIT',
                ])
                ->first();
                

        $transactions_no = $transaction->transactions_no;
        if (isset($request->payment_mode) && count($request->payment_mode) > 0) {
            foreach ($request->payment_mode as $key => $item) {
                if ($item['amount'] > 0) {
                    if(isset($item['last_id']) && $item['last_id']!='')
                    {
                        $item1 = [
                            'transaction_mode_id'    => $item['transaction_mode_id'] ?? '',
                            'payment_mode_id'        => $item['mode_id'] ?? '',
                            'amount'                 => $item['amount'],
                            'account_id'             => $item['mode_id'] ?? '',
                            'transaction_date'       => date('Y-m-d', strtotime($request->receipt_date)),
                            'transaction_referrence' => $item['transaction_referrence'],
                            'transactions_status'    => true
                         ];

                         $acReceiptTransaction = AcReceiptDetail::updateOrCreate([
                             'id'         => $item['last_id'],
                             'voucher_id' => $id
                         ], $item1);

                         $transactions = AccountTransaction::updateTransaction([
                             'module_code'      => $menuCode,
                             'voucher_id'       => $id,
                             'account_id'       => $item['mode_id']??'',
                             'voucher_type'     => 'RECEIPT', // SALE, PURCHASE, PAYMENT
                             'transaction_type' => 'DEBIT',
                         ],[
                             'transaction_date'  => date('Y-m-d', strtotime($request->receipt_date)),
                             'amount'            => $item['amount'],
                         ]);

                         AccountTransaction::updateTransaction([
                             'module_code'      => $menuCode,
                             'voucher_type'     => 'RECEIPT', // SALE, PURCHASE, PAYMENT
                             'voucher_id'       => $id,
                             'account_id'       => $request->account_id,
                             'transaction_type' => 'CREDIT',
                         ],[
                             'transaction_date'  => date('Y-m-d', strtotime($request->receipt_date)),
                             'amount'            => $item['amount']
                         ]);

                    }
                    else
                    {
                        $acReceiptTransaction = AcReceiptDetail::create([
                            'payment_mode_id'     => $item['mode_id'] ?? '',
                            'voucher_master_id'   => ($voucher_master->id  ?? ''),
                            'voucher_id'          => ($id ?? ''),
                            'voucher_type'        => ($acDEBITReceiptTransaction->voucher_type ?? ''),
                            'module_id'           => ($moduleReceipt->id ?? ''),
                            'account_id'          => $item['mode_id'] ?? '',
                            'transaction_type'    => 'DEBIT',
                            'details_narration'   => "",
                            'amount'              => ($item['amount'] ?? ''),
                            'transaction_referrence' => $item['transaction_referrence'] ?? '',
                            'transaction_mode_id'    => $item['transaction_mode_id'] ?? '',
                            'created_by'          => Auth::id() ?? '',
                            'company_id'          => Auth::user()->company_id ?? '',
                            'transactions_status' => true,
                            'transaction_date'    => date('Y-m-d', strtotime($request->receipt_date)),

                        ]);

                        $transactionsData = $this->generateTransactionNumber();

                         AccountTransaction::createTransaction([
                             'transactions_no'   => $transactionsData['transactions_no']??'',
                             'transaction_date'  => date('Y-m-d'),
                             'module_code'       => $menuCode,
                             'voucher_id'        => $id,
                             'voucher_type'      => ($voucher_type_code ?? ''),
                             'account_id'        => $item['mode_id']  ?? '',
                             'transaction_type'  => 'DEBIT',
                             'details_narration' => '',
                             'amount'            => $item['amount'],
                             'voucher_sub_id'    => $acReceiptTransaction->id,
                             'last_id'           => $transactionsData['last_count']??''
                         ]);

                         $transactionsData = $this->generateTransactionNumber();
                         AccountTransaction::createTransaction([
                             'transactions_no'   => $transactionsData['transactions_no']??'',
                             'transaction_date'  => date('Y-m-d'),
                             'module_code'       => $menuCode,
                             'voucher_id'        => $id,
                             'voucher_type'      => ($voucher_type_code ?? ''),
                             'account_id'        => $request->account_id,
                             'transaction_type'  => 'CREDIT',
                             'details_narration' => '',
                             'amount'            => $item['amount'],
                             'voucher_sub_id'    => $acReceiptTransaction->id,
                             'last_id'           => $transactionsData['last_count']??''
                         ]);
                         //dd($transaction);
                         $voucher_collection_detail = VoucherCollectionDetail::create([
                             'voucher_collection_id' => $voucher_collection->id,
                             'transaction_id'        => $transaction->id??'',
                         ]);
                    }
                } else if(isset($item['last_id']) && $item['last_id']!='') {
                     $acReceiptTransaction = AcReceiptDetail::where([
                         'id'         => $item['last_id'],
                         'voucher_id' => $id
                     ])->delete();

                     $transaction = AccountTransaction::where([
                         'module_code'      => $menuCode,
                         'voucher_id'       => $id,
                         'account_id'       => $item['mode_id']??'',
                         'voucher_type'     => 'RECEIPT', // SALE, PURCHASE, PAYMENT
                         'transaction_type' => 'DEBIT',
                     ])->delete();

                     AccountTransaction::where([
                         'module_code'      => $menuCode,
                         'voucher_type'     => 'RECEIPT', // SALE, PURCHASE, PAYMENT
                         'voucher_id'       => $id,
                         'account_id'       => $request->account_id,
                         'transaction_type' => 'CREDIT',
                     ])->delete();
                }
            }
        }
        if($request->redirect=='sale-edit-cart-billing')
        {
            return redirect('sale-edit-cart-billing/'.$receiptVoucher->voucher_id)->with('success', 'Collection Updated Successfully');
        }
        return redirect()->route('print-receipt-voucher',$receiptVoucher->id)->with('success', 'Collection Updated Successfully');
    }


    public function collectionList($invoice_id,$module_code,Request $request)
    {
        $moduleCode = $module_code;
        $transactionSummery = $this->TransactionSummery($invoice_id, $moduleCode);
        $transactionHistory = $this->transactionHistory($invoice_id, $moduleCode);


        if($module_code=="OPD_BOOKING"){
            $sale_invoice = OpdBookings::select(['id','booking_no as voucher_type_invoice_no','created_at as invoice_date'])->find($invoice_id);
        }
        else
        {
            $sale_invoice = SaleInvoice::with('getPatient')->find($invoice_id);
        }
       
        $voucherType = VoucherType::select(['name','code'])->where('code',$moduleCode)->first();
        $data = AcReceipt::with('accountReceiptDetail')->where('voucher_id',$invoice_id)->where('module_code',$moduleCode)->latest()->get();

        if (!$sale_invoice && !$data && !$voucherType) {
            return redirect()->url($request->redirect)->with('error', 'Record Not Found!');
        }

        return view('bill-collection.collection-list', compact([
            'sale_invoice',
            'transactionSummery',
            'transactionHistory',
            'data',
            'voucherType',
        ]));
    }
}
