<?php

namespace App;
use Illuminate\Database\Eloquent\Model;
use DB;
use Crypt;
use App\Journal;
use EF;
class Account extends Model
{
    private $generic_condition;
    public function __construct()
    {
       $this->setCondition(['is_recycle' => '0']);
    }

        public function getAccountListByType($type_list = [])
    {
        return Account::where($this->getCondition())->whereIn('type',$type_list)->with(['head'])->orderby('code','asc')->get();
    }

      public function getAccountListByNature($nature_in = [])
    {
         return Account::

            whereHas('head',function($query) use ($nature_in){
            
             $query->whereIn('nature',$nature_in);

         })
        
        ->where($this->getCondition())
        ->orderBy('id','asc')
        ->get();    
    }




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

    public function getCondition()
    {
        return $this->generic_condition;
    }
 
    public function getAllSubheadByNature($current_nature)
    {
        
        $nature = EF::getNatureList();

        $nature_list = [$nature[0],$nature[1],$nature[6],$nature[7]];

        if(in_array($current_nature,$nature_list))
        {
            return Account::where($this->getCondition())->whereHas('head',function($query) use ($nature_list){

                $query->whereNotIn('nature',$nature_list);


            })->orderBy('code','asc')->get();
      

        }
        else
        {
           return Account::where($this->getCondition())->whereHas('head',function($query) use ($nature_list){

                $query->whereIn('nature',$nature_list);
                

            })->orderBy('code','asc')->get();
        }

    }

    public function getSubHeadByHead($id)
    {
        $condition = $this->getCondition();
        $condition += ['head_id'=>$id];

        return Account::where($condition)->get();
    }

       public function getAccountByBillSubCategoryId($bill_subcategory_id)
    {  
        $condition = $this->getCondition();
        $condition += ['bill_subcategory_id'=>$bill_subcategory_id];

        return Account::where($condition)->first();
     } 

     public function isFoundBranchSubhead($branch)
    {
        return Account::where('branch_id',$branch)->count();
    }



    public function getSubHeadByType($type)
    {
        $condition = $this->getCondition();
        $condition += ['type'=>$type];

        return Account::where($condition)->get();
    }

    public function getSubHeadByUserId($user_id,$head_id)
    {
        $condition = $this->getCondition();
        $condition += ['user_id'=> $user_id, 'head_id' => $head_id];

        return Account::where($condition)->first();
    }

     public function getSubHeadByBranchId($branch_id,$head_id)
    {
        $condition = $this->getCondition();
        $condition += ['branch_id'=> $branch_id, 'head_id' => $head_id];

        return Account::where($condition)->first();
    }



    public function getSubHeadById($id)
    {  
        $condition = $this->getCondition();
        $condition += ['id'=>$id];

        return Account::where($condition)->first();
     } 

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

        return Account::where($condition)->with(['head'])->orderBy('code')->get();
     }



     public function getAllSubheadByType($type)
     {
        $type_list = ['General','Cash','Bank'];

        if(in_array($type,['BRV','BPV']))
        {
            $type_list = ['Bank'];
        }
        else if(in_array($type,['CRV','CPV']))
        {
            $type_list = ['Cash'];
        }


        $condition = $this->getCondition();

        return Account::where($condition)->whereIn('type',$type_list)->with(['head'])->orderBy('code')->get();
     }



    public function getAccountById($id)
    {    
        $condition = $this->getCondition();
        $condition  += ['id'=>$id];

        return Account::where($condition)->first();
    } 


    public function getArrayAccountById($id)
    {    
        $condition = $this->getCondition();
        $condition  += ['id'=>$id];

        return Account::where($condition)->get();
    } 


    public function getAccountByBank($bank_id)
    {    
        $condition = $this->getCondition();
        $condition  += ['bank_id'=>$bank_id];

        return Account::where($condition)->distinct('name')->get();
    }
    

//     public function storeSubHead($object)
//     {

//         return DB::transaction(function () use ($object)  {

//             $generate_code = $this->generateSubheadCode($object['head_id']);

//             $subhead                = new Account;

//             $subhead->code          = $generate_code['code'];
           
//             $subhead->name          = $object['name'];
            
//             $subhead->head_id       = $object['head_id'];

//             $subhead->user_id       = $object['user_id'];

//             $subhead->scale_id       = $object['scale_id'];

//             $subhead->designation_id  = $object['designation_id'];

//             if(isset($object['flag']))
//             {
//                 $subhead->flag = $object['flag'];
//             }

//                if(isset($object['bill_subcategory_id']))
//             {
//                 $subhead->bill_subcategory_id = $object['bill_subcategory_id'];

//             }
//             else
//             {
//                  $subhead->bill_subcategory_id = 0;
//             }

//             if(isset($object['branch_id']))
//             {
//                 $subhead->branch_id  = $object['branch_id'];
//             }
//             else
//             {
//                 $subhead->branch_id = 0;
//             }




//             $bank = new Bank;

//             if(isset($object['bank']))
//             {
//                 $curr_bank = $bank->getBankById($object['bank']);

//                 if(isset($curr_bank->id))
//                 {
//                     $subhead->bank_id       = $curr_bank->id;
//                     $subhead->name          = $curr_bank->branch_code.' | '.$curr_bank->bank_name.' | '.$curr_bank->location;
//                     $subhead->type          = 'Bank';

//                     if(isset($object['opening_balance']))
//                     {
//                         $subhead->opening_balance = $object['opening_balance'];
//                     }

//                 }
//                 else
//                 {
//                     $subhead->bank_id         = 0;
//                     $subhead->type            = $object['type'];
//                     $subhead->opening_balance = 0;

//                 }
//             }
//             else
//             {
//                 $subhead->bank_id       = 0;
//                 $subhead->type          = $object['type'];
//             }
            
//             $subhead->save();

//             $old_subhead = Account::find($generate_code['old_account_id']);

//             if(isset($old_subhead->id))
//             {
//                 $old_subhead->is_recycle = '2';

//                 $old_subhead->update();
//             }
// dd($object);

//              if($subhead->opening_balance > 0)
//             {
                
//                 if(isset($object['debit_account']))
//                 {
//                     $subhead->opening_balance_id = $object['debit_account'];
//                 }
//                 else if($object['credit_account'])
//                 {
//                     $subhead->opening_balance_id = $object['credit_account'];
//                 }

//                 $subhead->update();


//                 $this->createBankOpeniningBalance($subhead);
//             }


              
//             return with($subhead);

//         });
//     }

    public function storeSubHead($object)
    {

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

            $generate_code = $this->generateSubheadCode($object['head_id']);

            $subhead                = new Account;

            $subhead->code          = $generate_code['code'];

            $subhead->name          = $object['name'];

            $subhead->head_id       = $object['head_id'];

            $subhead->user_id       = $object['user_id'];

            $subhead->scale_id       = $object['scale_id'];

            $subhead->designation_id  = $object['designation_id'];


            // if(isset(Auth::user()->id))
            // {
            //        $subhead->added_id       = Auth::user()->id;
            // }
            // else
            // {
            //      $subhead->added_id = 0;
            // }



            if(isset($object['flag']))
            {
                $subhead->flag = $object['flag'];
            }

             if(isset($object['branch_id']))
            {
                $subhead->branch_id  = $object['branch_id'];
            }
            else
            {
                $subhead->branch_id = 0;

            }

                if(isset($object['bill_subcategory_id']))
            {
                $subhead->bill_subcategory_id = $object['bill_subcategory_id'];

            }
            else
            {
                 $subhead->bill_subcategory_id = 0;
            }

            $bank = new Bank;

            if(isset($object['bank']))
            {
                $curr_bank = $bank->getBankById($object['bank']);

                if(isset($curr_bank->id))
                {
                    $subhead->bank_id       = $curr_bank->id;
                    $subhead->name          = $curr_bank->branch_code.' | '.$curr_bank->title.' | '.$curr_bank->bank_name.' | '.$curr_bank->location;
                    $subhead->type          = 'Bank';

                    // if(isset($object['opening_balance']))
                    // {
                    //     $subhead->opening_balance = $object['opening_balance'];
                    // }

                }
                else
                {
                    $subhead->bank_id       = 0;
                    $subhead->type          = $object['type'];
                    // $subhead->opening_balance = 0;
                }
            }
            else
            {
                $subhead->bank_id       = 0;
                $subhead->type          = $object['type'];
            }

            if(isset($object['opening_balance'])){

                $subhead->opening_balance = $object['opening_balance'];
            }
            else{
                $subhead->opening_balance = 0;
            }

            $subhead->save();

            $old_subhead = Account::find($generate_code['old_account_id']);

            if(isset($old_subhead->id))
            {
                $old_subhead->is_recycle = '2';

                $old_subhead->update();
            }

            if($subhead->opening_balance > 0)
            {
                

                if(isset($object['debit_account']))
                {
                    $subhead->opening_balance_id = $object['debit_account'];
                }
                else if($object['credit_account'])
                {
                    $subhead->opening_balance_id = $object['credit_account'];
                }

                $subhead->update();


                $this->createBankOpeniningBalance($subhead);
            }

            return with($subhead);

        });
    }

  //   public function createBankOpeniningBalance($subhead)
  //   {
  //       if(isset($subhead->id))
  //       {
  //         // AUTO JV ONLY BACK ACCOUNT CASE
  //          $jv_data['compound_type']            =  "General";
  //          $jv_data['voucher_list']             =  'JV';
  //          $jv_data['date']                     =  $subhead->created_at;
  //          $jv_data['auto_jv']                  =  1;
  //          $jv_data['receipt']                  =  NULL;
  //          $jv_data['branch'][0]                =  $subhead->head->branch_id;
  //          $jv_data['user'][0]                  =  NULL;
  //          $jv_data['booking'][0]               =  NULL;
  //          $jv_data['amount'][0]                =  $subhead->opening_balance;
  //          $jv_data['narration'][0]             =  'Auto Jv Against Account # '.$subhead->code;
  //          $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]          =   NULL;
  //          $jv_data['payment_type'][0]          =   NULL;
  //          $jv_data['payment'][0]               =   0;
  //          $jv_data['generic'][0]               =   NULL;
  //          $jv_data['deposit_no'][0]            =   null;
  //          $jv_data['deposit_date'][0]          =   null; 
  //          $jv_data['debit_subhead'][0]         =   $subhead->id; 
  //          $jv_data['credit_subhead'][0]        =   EF::getBankOpeningAccount()['opening_credit']; 

  //         $payment = new Payment;

  //         $curr_voucher                     = $payment->createVoucher($jv_data);
              
  //         $voucher_data['status']           = 'Approve';

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

  //         $voucher_data['date']             = $subhead->created_at;

  //         $transaction = new Transaction;

  //         $approved_voucher = $transaction->updateStatusByTransaction($voucher_data);
  //       }
  //   }
  //   public function updateSubHead($object)
  //   {
        
  //      return DB::transaction(function () use ($object) {

  //           $journal = new Journal;


  //           $subhead = Account::find($object['subhead_id']);



      
  //           if(isset($subhead->id))
  //           { 
  //             // $subhead->code         = $object['code'];
  //             $subhead->name        = $object['name'];
  //             $subhead->type        = $object['type'];

  //             $bank = new Bank;

  //             $curr_bank = $bank->getBankById($object['bank']);

  //             if(isset($curr_bank->id))
  //             {
  //                $subhead->bank_id       = $curr_bank->id;
  //                $subhead->name          = $curr_bank->branch_code.' | '.$curr_bank->bank_name.' | '.$curr_bank->location;
  //                $subhead->type          = 'Bank';

  //                if(isset($object['opening_balance']))
  //                {
  //                   $subhead->opening_balance = $object['opening_balance'];
  //                }


  //             }
  //             else
  //             {
  //                $subhead->bank_id       = 0;
  //                $subhead->opening_balance = 0;

  //             }

  //             $subhead->update();
                
  //           }

  //           $narration = 'Auto Jv Against Account # '.$subhead->code;

  //           $account_list = [$subhead->id,EF::getBankOpeningAccount()['opening_credit']];

  //           if(isset($subhead->bank->id) && $subhead->opening_balance > 0)
  //           {
                

  //               if($journal->isFoundBankOpeningBalance($account_list,$narration) == 0)
  //               {
  //                   $this->createBankOpeniningBalance($subhead);
  //               }
  //               else
  //               {
  //                  $journal->updateBankOpeningBalance($account_list,$narration,$subhead->opening_balance);
  //               }
  //           }
  //           else
  //           {
  //               $journal->updateBankOpeningBalance($account_list,$narration,$subhead->opening_balance);
  //           }
            
            
  //           return with($subhead);
  //                   });
  //   }

    

  // public function removeSubHead($id)
  //   {

  //       return DB::transaction(function () use ($id) {

  //           $account = Account::find($id);

  //           // $journal = new Journal;

  //           if(isset($account->id) && $account->flag == "0" && $this->countLedgerByAccount($account->id) == 0)
  //           {
  //               $account->is_recycle   = '1';
  //               $account->update();
  //           }


  //           // $narration = 'Auto Jv Against Account # '.$subhead->code;

  //           // $account_list = [$subhead->id,EF::getBankOpeningAccount()['opening_credit']];

  //           // $journal->removeBankOpeningBalance($account_list,$narration);
            
  //           return with($account);
            
  //       });
  //   }
     public function createBankOpeniningBalance($subhead)
    {
        if(isset($subhead->id) && $subhead->opening_balance > 0 && $subhead->opening_balance_id > 0)
        {
           $debit_account  = 0;
           $credit_account = 0;

           $nature = EF::getNatureList();

           if(in_array($subhead->head->nature,[$nature[0],$nature[1],$nature[3],$nature[4]]))
           {
              $debit_account = $subhead->id;

              $credit_account = $subhead->opening_balance_id;
           }
           else
           {
              $debit_account = $subhead->opening_balance_id;

              $credit_account = $subhead->id;
           }

          // AUTO JV ONLY BACK ACCOUNT CASE
           $jv_data['compound_type']            =  "General";
           $jv_data['voucher_list']             =  'JV';
           $jv_data['date']                     =  $subhead->created_at;
           $jv_data['auto_jv']                  =  1;
           $jv_data['receipt']                  =  NULL;
           $jv_data['branch'][0]                =  $subhead->head->branch_id;
           $jv_data['user'][0]                  =  NULL;
           $jv_data['booking'][0]               =  NULL;
           $jv_data['amount'][0]                =  $subhead->opening_balance;
           $jv_data['narration'][0]             =  'Auto Jv Against Account # '.$subhead->code;
           $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]          =   NULL;
           $jv_data['payment_type'][0]          =   NULL;
           $jv_data['payment'][0]               =   0;
           $jv_data['generic'][0]               =   NULL;
           $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']             = $subhead->created_at;

          $transaction = new Transaction;

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

    public function updateSubHead($object)
    {

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

        $journal = new Journal;

            $subhead = Account::find($object['subhead_id']);


            if(isset($subhead->id))
            {
                $narration = 'Auto Jv Against Account # '.$subhead->code;

                $account_list = [$subhead->id,$subhead->opening_balance_id];
                  // $subhead->code         = $object['code'];
                  $subhead->name        = $object['name'];
                  $subhead->type        = $object['type'];

                  $bank = new Bank;

                  $curr_bank = $bank->getBankById($object['bank']);

                      if(isset($curr_bank->id))
                      {
                         $subhead->bank_id       = $curr_bank->id;
                         $subhead->name          = $curr_bank->branch_code.' | '.$curr_bank->bank_name.' | '.$curr_bank->location;
                         $subhead->type          = 'Bank';

                        //  if(isset($object['opening_balance']))
                        //  {
                        //     $subhead->opening_balance = $object['opening_balance'];
                        //  }

                      }
                      else
                      {
                         $subhead->bank_id       = 0;
                         $subhead->opening_balance = 0;
                      }

                    if(isset($object['opening_balance'])){

                        $subhead->opening_balance = $object['opening_balance'];
                    }
                    else{
                        $subhead->opening_balance = 0;
                    }

                   if(isset($object['debit_account']))
                    {
                        $subhead->opening_balance_id = $object['debit_account'];
                    }
                    else if($object['credit_account'])
                    {
                        $subhead->opening_balance_id = $object['credit_account'];
                    }


                $subhead->update();

            }

    
            // if(isset($subhead->bank->id) && $subhead->opening_balance > 0)
            if($subhead->opening_balance > 0 && $subhead->opening_balance_id > 0)
            {
                

                if($journal->isFoundBankOpeningBalance($account_list,$narration) == 0)
                {
                    $this->createBankOpeniningBalance($subhead);
                }
                else
                {
                   $journal->updateBankOpeningBalance($account_list,$narration,$subhead->opening_balance,[$subhead->id,$subhead->opening_balance_id]);
                }

            }
            else 
            {
                $journal->rejectOpeningBalanceVoucher($account_list,$narration);
            }

            return with($subhead);
                    });
    }



    public function removeSubHead($id)
    {

        return DB::transaction(function () use ($id) {

            $account = Account::find($id);

            if(isset($account->id) && $account->flag == "0" && $this->countLedgerByAccount($account->id) == 0)
            {
                $account->is_recycle   = '1';
                $account->update();
            }

            return with($account);

        });
    }
    public function subHeadSeries($head_id)
    {   
        $code = Head::where(['id' => $head_id])->where($this->getCondition())->value('code');
        $head_value=$code;
        if(isset($code))
        {
            $code = Account::where(['head_id' => $head_id])->where($this->getCondition())->max('code');
            if($code==null){
                
                $code=$head_value;
                $code = $code + 1;
            }
            else{
                $code=$code+1;
            }
        }   
        

        return $code;
    }

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

        $condition += ['account_id' => $account];

        return Journal::where($condition)->count();
    }
 
     

    public function head()
    {
       return $this->belongsTo(Head::class,'head_id')->where($this->getCondition())->withDefault();

    }

    public function bank()
    {
       return $this->belongsTo(Bank::class,'bank_id')->where($this->getCondition())->withDefault();
   }

     public function journal()
    {
        return $this->hasMany(Journal::class)->where($this->getCondition());
    }

    public function getRemoveSubheadList($head)
    {
        return Account::where(['is_recycle' => 1, 'head_id' => $head])->orderby('id','asc')->get();
    }

    public function generateSubheadCode($id)
    {
        $data = ['old_account_id' => 0, 'code' => 0];

        // FIRST CHECK OLD 
        $old_subhead_list = $this->getRemoveSubheadList($id);

        foreach ($old_subhead_list as $rows) {
            
            $data['old_account_id'] = $rows->id;

            $data['code']           = $rows->code;

            return $data;
        }
        // END

        $series = 0;

        $condition =['head_id' => $id] + $this->getCondition();

        $code = Account::where($condition)->max('code');


        // if(strlen($code) <= 0)
        // {
        //     $code = Head::where('id',$id)->where($this->getCondition())->max('code');

           
        //     $code = explode('-',$code);

        //     $left_digit  = $code[0];
        //     $right_digit = $code[1]+1;

        //     $code = str_pad(($left_digit),3, '0', STR_PAD_LEFT).'-'.str_pad(($right_digit),2, '0', STR_PAD_LEFT);
        // }
        // else
        // {
        //     $code = explode('-',$code);

        //     $left_digit  = $code[0];
        //     $right_digit = $code[1]+1;

        //     $code = str_pad(($left_digit),3, '0', STR_PAD_LEFT).'-'.str_pad(($right_digit),2, '0', STR_PAD_LEFT);

        // }


        if(strlen($code) > 0)
        {
            $code = explode('-',$code);

            if(isset($code[1]))
            {
                $series = str_pad(($code[1]+1),(2), '0', STR_PAD_LEFT);

                $data['code'] = $code[0].'-'.$series;
            }            
        }
        else
        {
            $head = new Head;

            $curr_head = $head->getHeadById($id);

            if(isset($curr_head->id))
            {
                $series = str_pad((1),2, '0', STR_PAD_LEFT);

                $data['code'] = $curr_head->code.'-'.$series;
            }
        }

        return $data;
    }



    
}
