<?php



namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Payment;
use App\Models\AgainstPayment;
use App\Models\Invoice;
use App\Models\Bill;
use App\Models\CreditNote;
use App\Models\DebitNote;
use App\Models\Transaction;
use App\Service\ActivityService;
use App\Service\PaymentEntryService;
use App\Service\SequenceService;
use App\Service\StaticMaster;
use App\Service\AccountsTransactionService;
use App\Service\TransactionService;
use Auth;
use Log;

class PaymentController extends Controller

{
    public function recordPayment(Request $request){

        $user=Auth::user();

        // Validate Item  
        $validator=validator($request->all(),[
            // 'amount'=>'required',
            'transaction_date'=>'required',
            'fy'=>'required',
            'payment_mode'=>'required'
        ]);

        //Inout 1 = payment rec , 2= payment made

        if ($validator->fails()) { 

            return [
                'success' => false, 
                'message' => $validator->errors()->first()
            ];

        } else {

            $obj['payment_id']=$request['payment_id'];

            $obj['customer_id']=$request['customer_id']??0;

            $obj['vendor_id']=$request['vendor_id']??0;

            $obj['display_name']=$request['display_name'];

            $obj['debit']=$request['debit']??0;  //Received

            $obj['credit']=$request['credit']??0; //Given

            $obj['bank_charges']=$request['bank_charges']??0;

            $obj['transaction_date']=$request['transaction_date'];

            $obj['posting_date']=$request['posting_date'];

            $obj['currency']=$request['currency']??null;

            $obj['currency_symbol']=$request['currency_symbol']??null;

            $obj['exchange_rate']=$request['exchange_rate']??0.00;

            $obj['fy']=$request['fy'];

            $obj['payment_mode']=$request['payment_mode']??0;  //mode of payment

            $obj['to_acc']=$request['to_acc']??0;  // Deposite to Account

            $obj['from_acc']=$request['from_acc']??0;  //Made From Account

            $obj['tax_deducted']=$request['tax_deducted']??0;   //0 for no and 1 for yes

            $obj['tax_acc_id']=$request['tax_acc_id'];

            $obj['entity_type']=$request['entity_type']??$request['transaction_type']??0;

            $obj['transaction_id']=$request['transaction_id']??0;

            $obj['reference']=$request['reference'];

            $obj['customer_note']=$request['customer_note'];

            $obj['upload_image']=$request['upload_image'];

            $obj['amt_refunded']=$request['amt_refunded']??0;

            $obj['amt_excess']=$request['amt_excess']??0;

            $obj['terms_and_condition']=$request['terms_and_condition'];

            // Creating Invoices And Bills Payments Services

            $payment_entry=new PaymentEntryService;

            if($request['id']>0){

                try{

                    $payment=Payment::findOrFail($request['id']);

                    $payment->update($obj);

                    AgainstPayment::where('payment_id',$request['id'])->delete();

                    $payment_entry->createupdate($request,$payment);

                    // Creating Activities

                    $activity=new ActivityService;

                    $activity->activityCreateUpdate('Payments',$payment['id'],'Updated');


                } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {

                    // Return error message in JSON if ID not found
                    return response()->json(['message' => 'Invalid Id to update '], 404);
                }

            }else{

                $module='';

                if($request['debit']>0){
                    // Payment Rec. Sequence Update
                    $module='payment_receipt';

                    $obj['transaction_type']=StaticMaster::$PAYMENTS_RECEIVED;
                }

                if($request['credit']>0){
                    // Payment Made Sequence Update
                    $module='payment_made';

                    $obj['transaction_type']=StaticMaster::$PAYMENTS_MADE;
                }

                $payment=Payment::create($obj);

                // Creating Activities

                $activity=new ActivityService;
                $activity->activityCreateUpdate('Payments',$payment['id'],'Created');

                // Creating Against Payment Entries 
                $payment_entry->createupdate($request,$payment);

                // Update Sequence Number
                $sequence=new SequenceService;
                $sequence->updateSequence($module);

            }             

            $response=[
                'success'=>true,
                'message'=>"Payment has been added.",
                'payment'=>$payment
            ];

            return response()->json($response);

        }

    }


    public function paymentList(Request $request){

        $user=Auth::user();

        $validator=validator($request->all(),[
            'fy'=>'required',
            'inout'=>'required'
        ]);

        if ($validator->fails()) { 
            return [
                'success' => false, 
                'message' => $validator->errors()->first()
            ];
        } else {

            $payments = Payment::where('organisation_id',$user['active_organisation'])

                ->with('entries','entries.invoice','entries.bill','customer','vendor','to_acc:id,account_name',
                'pay_mode:id,account_name')

                ->where('fy',$request['fy'])

                ->where('rolledback',0);

            if ($request['inout']==1) {

                $payments=$payments->where('debit','!=',0);

            }else{

                $payments=$payments->where('credit','!=',0);
            }

            if($request['search']!=null && $request['search']!=''){

                $payments = $payments->where(function ($query) use ($request) {
                    
                    $query->where('payment_id', 'LIKE', '%' . $request['search'] . '%')

                        ->orWhere('debit', 'LIKE', '%' . $request['search'] . '%')

                        ->orWhere('credit', 'LIKE', '%' . $request['search'] . '%')

                        ->orWhere('payment_mode', $request['search'])

                        ->orWhereHas('customer',function($q) use ($request){
                            $q->where('display_name','LIKE','%'.$request['search'].'%');
                        })

                        ->orWhereHas('pay_mode',function($q) use ($request){
                            $q->where('account_name','LIKE','%'.$request['search'].'%');
                        })

                        ->orWhereHas('vendor',function($q) use ($request){
                            $q->where('display_name','LIKE','%'.$request['search'].'%');
                        });
                });

            }
                // get alphabetically data by customer_name

            if ($request['customer_id']!='' && $request['customer_id']!=null && isset($request['customer_id'])) {
                $payments=$payments->where('customer_id',$request['customer_id']);
            }

            if ($request['payment_mode']!=0 && $request['payment_mode']!=null && isset($request['payment_mode'])) {
                $payments=$payments->where('payment_mode',$request['payment_mode']);
            }

            if ($request['vendor_id']!='' && $request['vendor_id']!=null && isset($request['vendor_id'])) {
                $payments=$payments->where('vendor_id',$request['vendor_id']);
            }
    
            if ($request['customer_name']!='' && isset($request['customer_name'])) {
                $payments=$payments->orderBy('name');
            }

            //status filter

            if ($request['status']!='' && isset($request['status'])) {

                $payments=$payments->where('status',$request['status']);
            }
                // get custom_date data by transaction_date

            if ($request['custom_date']!='' && isset($request['custom_date'])) {

                $customDate = $request->custom_date;

                $payments = $payments->whereDate('transaction_date', $customDate);

            }
                // get last modified data by updated_at

            if ($request['updated_at']!='' && isset($request['updated_at'])) {

                $payments=$payments->orderBy('updated_at');

            }
                // get fromDate toDate data by created_at

            if ($request['from_date']!='' && isset($request['to_date'])) {

                $fromDate = $request->from_date;

                $toDate = $request->to_date;
                // 'fromDate' and 'toDate'

                $payments = $payments->whereBetween('transaction_date', [$fromDate, $toDate]);

            }

            $count=$payments->count();

            if(isset($request['sort_by']) && $request['sort_by']!='' && $request['sort_by']!=null){
                
                $sort_order=$request['sort_order']==1?'asc':'desc';

                $payments = $payments->orderby($request['sort_by'],$sort_order);

            }else{
                $payments = $payments->orderby('id','desc');
            }
        

            $payments=$payments->skip($request['noofrec']*($request['currentpage']-1))->take($request['noofrec']??100)

                ->get();


            $response=[

                'message'=>'Payments List Fetched Successfully',

                'count'=>$count,

                'payments'=>$payments,

                'success'=>true

            ];

            return response()->json($response,200);  

        }

    }


    public function paymentDetails(Request $request){

        $user=Auth::user();
        
        
        $validator=validator($request->all(),[
            'id'=>'required'
        ]);

        if ($validator->fails()) { 
            return [
                'success' => false, 
                'message' => $validator->errors()->first()
            ];
        } else {

            try{
                
                $payments = Payment::where('organisation_id',$user['active_organisation'])

                    ->with('entries','entries.invoice','entries.bill','customer','vendor',
                        'to_acc:id,account_name','from_acc:id,account_name','collected_by')
                    ->where('rolledback',0)
                    ->where('id',$request['id'])
                    ->first();

                if ($payments->entity_type == StaticMaster::$SALE_TRANSACTION_TYPE) {
                    $payments->load('invoice');
                } elseif ($payments->entity_type == StaticMaster::$PURCAHSE_TRANSACTION_TYPE) {
                    $payments->load('bill');
                } elseif ($payments->entity_type == StaticMaster::$CREDIT_NOTE) {
                    $payments->load('credit_note');
                } elseif ($payments->entity_type == StaticMaster::$DEBIT_NOTE) {
                    $payments->load('debit_note');
                } elseif ($payments->entity_type == StaticMaster::$EXPENSE) {
                    $payments->load('expense');
                }

                $transactionTypes = [
                    StaticMaster::$BILL_PAYMENT,
                    StaticMaster::$INVOICE_PAYMENT,
                    StaticMaster::$PAYMENTS_MADE,
                    StaticMaster::$PAYMENTS_RECEIVED
                    // StaticMaster::$DEBIT_NOTE_PAYMENT,
                    // StaticMaster::$CREDIT_NOTE_PAYMENT,
                ];

                $transaction=Transaction::where('transaction_id',$request['id'])
                    ->where('is_disabled',0)
                    ->whereIn('transaction_type', $transactionTypes)
                    ->with('account:id,account_name,account_code')
                    ->get();

                $response=[
                    'message'=>"Payments details fetch successfully",
                    'success'=>true,
                    'payment'=>$payments,
                    'transaction'=>$transaction
                ];

                return response()->json($response);
            }

            catch(Exception $e){
                return [
                    'success' => false, 
                    'message' => $e->getMessage()
                ];
            }

        }
    }


    // public function approvePayment(Request $request){

    //     $validator=Validator::make($request->all(),[
    //         'id'=>'required'
    //     ]);

    //     if ($validator->fails()) {

    //         # code...
    //         $response=[ 

    //             'success'=>false,

    //             'message'=>$validator->errors()->first()
    //         ];

    //         return response()->json($response);    

    //     }
    //     else{

    //         try{

    //             $transaction = Payment::findOrFail($request->invoice_id);

    //             $transaction['is_approved']=1;
    //             $transaction['status']=1;

    //             $transaction->update();  

    //         } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {

    //             // Return error message in JSON if ID not found
    //             return response()->json(['message' => 'Invalid Id to update '], 404);

    //         }

    //     }

    //     $response=[ 
    //         'success'=>true,
    //         'message'=>'Payment Approved Successfully'
    //     ];

    //     return response()->json($response);

    // }

    public function destroy(Request $request){

        $user=Auth::user();

       
        $validator=validator($request->all(),[
            'id'=>'required'
        ]);

        if ($validator->fails()) { 
            return [
                'success' => false, 
                'message' => $validator->errors()->first()
            ];
        } else {

            try{

                $transaction = Payment::where('id',$request['id'])
                    ->where('organisation_id',$user['active_organisation'])->first();

                if($transaction!=null){

                    if($transaction['is_approved']==0){

                        $transaction['rolledback']=1;

                        $transaction->update(); 

                        $response=[ 

                            'success'=>true,
                
                            'message'=>'Payment Deleted Successfully'
                
                        ];
                        
                        return response()->json($response);

                    }else{

                        $response=[ 

                            'success'=>false,
                
                            'message'=>'Payment is Approved You can not delete'
                
                        ];
                        
                        return response()->json($response);
                    }

                }else{
                    $response=[ 

                        'success'=>false,
            
                        'message'=>'Invalid Id to update'
            
                    ];
                    
                    return response()->json($response);
                }

                // $stockEntryService = new StockEntryService;

                // $stockEntryService->saveStockEntries( $transaction,$entity,2);

            } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {

                // Return error message in JSON if ID not found

                return response()->json(['message' => 'Invalid Id to update '], 404);

            }

        }

    }


    public function statusPayment(Request $request){
        // Validate Item
        $status_change='';

        $validator=validator($request->all(),[

            'id'=>'required',
            'status'=>'required'

        ]);

        if ($validator->fails()) { 

            return [

                'success' => false, 

                'message' => $validator->errors()->first()

            ];

        } else {
            $transaction = Payment::findOrFail($request->id);

            $transaction['status']=$request['status'];

            if($request['status']==1){

                $status_change='Approved';
                $transaction['is_approved']=1;  

                 //Update the Credit note balance of amount paid
                if($transaction['entity_type']==StaticMaster::$CREDIT_NOTE){
                    Log::info('credit_note Payment Adjustment'.$transaction['amount']);
                    $credit_note=CreditNote::where('id',$transaction['transaction_id'])->first();
                    if(isset($credit_note)){
                        Log::info('credit_note Payment Adjustment'.$transaction['amount']);
                        // Updating the Amount Paid
                        $credit_note['amount_paid']=$credit_note['amount_paid']+$transaction['credit']??0;
                        $credit_note->update();
                    }
                }
                 //Update the Debit note balance of amount paid
                if($transaction['entity_type']==StaticMaster::$DEBIT_NOTE){
                    Log::info('debit_note Payment Adjustment'.$transaction['amount']);
                    $debit_note=DebitNote::where('id',$transaction['transaction_id'])->first();
                    if(isset($debit_note)){
                        Log::info('credit_note Payment Adjustment'.$transaction['amount']);
                        // Updating the Amount Rec.
                        $debit_note['amount_paid']=$debit_note['amount_paid']+$transaction['debit']??0;
                        $debit_note->update();
                    }
                }

                // Creating Accounting Entries for the Payment
                $account_transaction_service=new AccountsTransactionService;
                $account_transaction_service->payment_account_transaction($transaction);

            }
            if($request['status']==2){
                $status_change='Declined';
                $transaction['is_approved']=0;
            }
            if($request['status']==0){
                $status_change='Draft';
            }

            $transaction->update();  

            $response=[ 
                'success'=>true,
                'message'=>'Payment '.$status_change.' Updated Successfully'
            ];

            return response()->json($response);

        }
    }

}

