<?php

namespace Gisplus\Package\EstatechVendor\Models;

use Illuminate\Database\Eloquent\Model;

use Gisplus\Package\EstatechVendor\Models\PurchaseItem;

use DB;

use App\Vendor;

use App\Branch;

use App\User;

use App\Payment;

use App\Transaction;

use App\Journal;


use App\TrackInvoice;


use EF;

class Invoice extends Model
{

   private $generic_condition;

   private $generic_index;

    public function __construct()
    {

       $this->setCondition(['is_recycle' => '0']);

       $this->generic_index = EF::getGenericTableIndex();


    }

    public function setCondition($condition = [])
    {
        $this->generic_condition = $condition;
    }

    public function getCondition()
    {
        return $this->generic_condition;
    }

    public function getInvoiceList()
    {
        $condition = $this->getCondition();

        return  Invoice::where($condition)->orderBy('id','asc')->get();

    }

    public function storeInvoice($object)
    {
        return  DB::transaction(function () use ($object)  {

            $invoice                  = new Invoice;
            $invoice->branch_id       = $object['branch'];
            $invoice->user_id         = $object['user'];
            $invoice->role_id         = EF::getRoleIdByName('Vendor');
            // $invoice->invoice_no      = $object['invoice_no'];
            $invoice->invoice_no      = $this->generateInvocieNo();

            $invoice->due_date        = $object['due_date'];
            $invoice->created_at        = $object['date'];

            $invoice->amount          = array_sum($object['amount']);
            // $invoice->status          = 'Unpaid';
            
            $invoice->save();

           
            $purchase_item = new PurchaseItem;

            $object['invoice'] = $invoice->id;
            
            $purchase_detail = $purchase_item->storePurchaseItem($object);

            $description = $invoice->purchaseItems->pluck('description')->toarray();

            $description = implode(',',$description);

            $invoice->description = $description;

            $invoice->update();
            

            // CREATE AUTO JV FUNCTION

            $account_info = EF::getAccountInfo();

            $debit_account = $account_info['inventory from supplies'];
            $credit_account = $account_info['control account'];


            // if($com->payment_type == "Commission")
            // {
            //     $account_info = EF::getCommissionAccount();

            //     $debit_account  = $account_info['commission_debit'];

            //     $credit_account = $account_info['commission_credit'];


            // }
            // else
            // {
            //     $account_info = EF::getReceivableAccount();

            //     $debit_account  = $account_info['receivable_debit'];

            //     $credit_account = $account_info['receivable_credit'];


            // }

           $jv_data['compound_type']            =  "General";
           $jv_data['voucher_list']             =  'JV';
           $jv_data['date']                     =  $invoice->created_at;
           $jv_data['auto_jv']                  =  1;
           $jv_data['role'][0]                  =  $invoice->role_id;
           $jv_data['receipt']                  =  NULL;
           $jv_data['branch'][0]                =  $invoice->branch_id;
           $jv_data['user'][0]                  =  $invoice->user_id;
           $jv_data['booking'][0]               =  NULL;
           $jv_data['amount'][0]                =  $invoice->amount;
           $jv_data['narration'][0]             =  $invoice->description;
           $jv_data['payment_mode'][0]          =   NULL;
           $jv_data['instrument'][0]            =   NULL;
           $jv_data['instrument_date'][0]       =   NULL;
           $jv_data['drawn'][0]                 =   NULL;
           $jv_data['generic_type'][0]          =   EF::getGenericTableIndex()['Invoice'];
           $jv_data['payment_type'][0]          =   'Pay Invoice AutoJV';
           $jv_data['payment'][0]               =   0;
           $jv_data['generic'][0]               =   $invoice->id;
           $jv_data['deposit_no'][0]            =   null;
           $jv_data['deposit_date'][0]          =   null;
           $jv_data['debit_subhead'][0]         =   $debit_account;
           $jv_data['credit_subhead'][0]        =   $credit_account;

          $payment = new Payment;

          $curr_voucher                     = $payment->createVoucher($jv_data);

          $voucher_data['status']           = 'Approve';

          $voucher_data['transaction_id']   = $curr_voucher->id;

          $voucher_data['date']             = $invoice->created_at;

          $transaction = new Transaction;

          $approved_voucher = $transaction->updateStatusByTransaction($voucher_data);

          $invoice->transaction_id = $curr_voucher->id;

          $invoice->update();

         return with($invoice);


        });
        
    }

    public function updateInvoice($object)
    {
    return DB::transaction(function () use ($object) {
          

        $invoice                  = new Invoice;

        $invoice = $invoice->find($object['invoice']);

        if(isset($invoice->id))
        {
            $invoice->branch_id       = $object['branch'];
           
            $invoice->user_id         = $object['user'];
        
            // $invoice->invoice_no      = $object['invoice_no'];
           
            $invoice->due_date        = $object['due_date'];

            $invoice->amount          = array_sum($object['amount']);

            $invoice->created_at      = $object['date'];
            
            // PURCHASE ITEMS 
            $purchase_item = new PurchaseItem;

            $object['invoice'] = $invoice->id;
            
            $purchase_detail = $purchase_item->updatePurchaseItem($object);
            // END PURCHASE ITEM

            $description = $invoice->purchaseItems->pluck('description')->toarray();

            $description = implode(',',$description);

            $invoice->description = $description;

            $invoice->update();

            // UPDATE DESCRIPTION
            $journal_list = Journal::where('transaction_id',$invoice->transaction_id)->get();

            foreach ($journal_list as $rows) 
            {
               $rows->narration = $invoice->description;

               $rows->update();
            }
            // END DESCRIPTION


            $payment = new Payment;
            $payment->updateAutoJvSidePayment($invoice->id,$this->generic_index['Invoice'],$invoice->amount);

            return with($invoice);

        }


    });
}

    public function removeInvoice($id)
    {
        return DB::transaction(function () use ($id) {
            
            $invoice = Invoice::find($id);

            if(isset($invoice->id))
            {
                $invoice->is_recycle   = '1';

                $invoice->update();

                $purchase_item = new PurchaseItem;

                $purchase_item = $purchase_item->removePurchaseItem($invoice->id);

                $payment = new Payment;

               $payment->removeAutoJvSidePayment($invoice->id,$this->generic_index['Invoice']);

            }

        });
    }

    public function getInvoiceById($id)
    {
        $condition = $this->getCondition();

        $condition  += ['id' => $id];

        return Invoice::where($condition)->with('purchaseItems')->first();
    }

    public function updateInvoiceByPayment($id,$new_amount,$old_amount)
    {

        return \DB::transaction(function () use ($id,$new_amount,$old_amount)  {

        $invoice = Invoice::find($id);

        if(isset($invoice->id))
        {
            // FOR REBACK INSTALLMENT
            if($old_amount > 0)
            {
               $invoice->received_amount -= $old_amount;
            }
            // FOR NEWER INSTALLMENT
            if($new_amount > 0)
            {
               $invoice->received_amount += $new_amount;
            }

            // THIS IF FIND INSALLMENT IS COMPLETED PAID OR NOT
            if($invoice->received_amount >= $invoice->amount)
            {
                $invoice->status = 'Paid';
            }
            else
            {
                $invoice->status = 'Unpaid';
            }

            $invoice->update();

            return with($invoice);
        }

      });
    }

    public function updateUnpaidVendorInvoice($journal_id,$user_id,$branch_id,$amount,$balance)
    {
        return \DB::transaction(function () use ($journal_id,$user_id,$branch_id,$amount,$balance)  {
            $invoice_list = Invoice::where($this->getCondition() + ['user_id' => $user_id, 'branch_id' => $branch_id, 'status' => 'Unpaid'])->get();

               $balance += $amount;
               
                foreach ($invoice_list as $rows) {

                  $req_amount = $rows->amount - $rows->received_amount;
                    if($balance >= $req_amount && $balance > 0)
                    {

                      $rows->received_amount +=  $req_amount;

                      $balance -= $req_amount; 


                      TrackInvoice::insert([
                        'invoice_id' => $rows->id,
                        'journal_id' => $journal_id,
                        'created_at' => date('Y-m-d'),
                        'updated_at' => date('Y-m-d'),
                        'is_recycle' => '0',
                        


                      ]);
                    }
                    else if($req_amount > 0 && $balance > 0)
                    {
                       $rows->received_amount += abs($balance);

                       $balance = 0; 

                       TrackInvoice::insert([
                        'invoice_id' => $rows->id,
                        'journal_id' => $journal_id,
                        'created_at' => date('Y-m-d'),
                        'updated_at' => date('Y-m-d'),
                        'is_recycle' => '0',


                      ]);

                    }

                
                if($rows->received_amount >= $rows->amount)
                {
                  $rows->status = 'Paid';
                }
                else
                {
                  $rows->status = 'Unpaid';
                }

                $rows->update();

            }

        });

    }


    public function updatePaidVendorInvoice($journal_id,$amount)
    {
        return \DB::transaction(function () use ($journal_id,$amount)  {

             $track_invoice = TrackInvoice::where(['journal_id' => $journal_id, 'is_recycle' => '0'])->first();

             if(isset($track_invoice->id))
             {
                 $invoice = new Invoice;

                 $invoice = $invoice->getInvoiceById($track_invoice->invoice_id);

                 if(isset($invoice->id))
                 {
                    $invoice->received_amount -= $amount;

                    if($invoice->received_amount >= $invoice->amount)
                    {
                         $invoice->status = 'Paid';
                    }
                    else
                    {
                        $invoice->status = 'Unpaid';
                    }

                    $invoice->update();
                 }

                 $track_invoice->is_recycle = '1';

                 $track_invoice->update();


             }

        });

    }



    // ELOQUENT RELATIONS
    public function branch()
    {
        return $this->belongsTo(Branch::class,'branch_id')->withDefault();
    }
    public function user()
    {
        return $this->belongsTo(User::class,'user_id')->withDefault();
    }

    public function purchaseItems()
    {
        return $this->hasMany(PurchaseItem::class, 'invoice_id');
    }

    public function generateInvocieNo()
    {
        $count = 0;

        $invoice_no = Invoice::max('invoice_no');

        $invoice_explode = explode('-',$invoice_no);

        if(isset($invoice_explode[0]) && isset($invoice_explode[1]) && $invoice_explode[0] == "PI")
        {
            $count = $invoice_explode[1];
        }

        return  'PI-'.str_pad(($count+1), 2, '0', STR_PAD_LEFT);  
    }
}
