<?php

namespace App\Http\Controllers\Accounts\Incomes;

use App\Http\Controllers\Controller;
use App\Http\Requests\Income\Customer as Request;
use App\Models\Accounts\Auth\User;
use App\Models\Accounts\Income\Customer;
use App\Models\Accounts\Income\CustomerRelation;
use App\Models\Accounts\Income\Invoice;
use App\Models\Accounts\Income\InvoicePayment;
use App\Models\Accounts\Income\InvoiceStatus;
use App\Models\Accounts\Income\Revenue;
use App\Models\Accounts\Income\Terms;
use App\Models\Accounts\Setting\Currency;
use App\Student;
use App\Utilities\ImportFile;
use App\Utilities\Modules;
use Date;
use Illuminate\Http\Request as FRequest;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;

class CustomerController extends Controller
{

    public $transactions = [];
    public $customer = [];
    private $customer_parent = [];
    private $customer_child  = [];
    
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {


      $customers = Customer::with(['invoice_customer.invoices_total','invoice_customer.payments_total','creditmemo_customer.creditmemo'])->orderBy('created_at','desc')->get()->toArray();
      
              $items = $this->bulidCustomer($customers);
     // dd($customers);
        /*$page = isset(request()->page)?request()->page:1;

        $items = $this->paginate($this->bulidCustomer($customers),$perPage = 25, $page,['path' => 'customers']);
        if(request('page')){

            return view('accounts.incomes.customers.ajaxrender',compact('items'));
        };
        */
        //$items = $customers;



       return view('accounts.incomes.customers.index', compact('items'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {

        $terms = Terms::pluck('name','id');

        $elements =    Customer::select('id','name','parent_id')->get()->toArray();

        $customers  = $this->bulidCustomer($elements);

        $payment_methods = Modules::getPaymentMethods();


        $consultants  = Student::where('status','in_job')->pluck('first_name','user_id');

       
     return view('accounts.incomes.customers.create', compact('terms','customer','payment_methods','customers','consultants'));
    }


    function bulidCustomer(array $elements, $parentId = NULL) {

            $child = array();
        
            foreach ($elements as $element) {
                if ($element['parent_id'] == $parentId) {

                    $children = $this->bulidCustomer($elements, $element['id']);

                        if (!empty($children) > 0 ) {
                            $element['children'] = $children;
                        }

                    $child[] = $element;
                }
            }

        return $child;
    }

    public function show(Customer $customer)
    {
        

        $amounts = [
            'paid' => 0,
            'open' => 0,
            'overdue' => 0,
        ];

        $counts = [
            'invoices' => 0,
            'revenues' => 0,
        ];

        $customer_child = $this->child_customer_id($customer->id);
        array_push($customer_child,$customer->id);
        $invoice = [];
        $payment_array = [];
        $invoice_total_transcation = [];
        $invoice_payments = [];

        foreach ($customer_child as $key => $child) {
            // Handle invoices
            $invoices = Invoice::with(['status', 'payments'])->where('customer_id', $child)->get();
            $counts['invoices'] += $invoices->count();

            $today = \Date::today()->toDateString();

            foreach ($invoices as $item) {   
                $invoice['date']    = $item->invoiced_at;
                $invoice['amount']  = $item->amount;
                $invoice['type']    = 'Invoice';
                $invoice['number']  = $item->invoice_number;
                $invoice['status']  = $item->invoice_status_code;
                $invoice['due_at']  = $item->due_at;
                $invoice['id']      = 'i-'.$item->id;
                $invoice['customer_id']      = $item->customer_id;

                $invoice_total_transcation[] = $invoice;
                $payments = 0;
                foreach ($item->payments as $payment) {
                    $payment_array['date']          = $payment->paid_at;
                    $payment_array['amount']        = $payment->amount;
                    $payment_array['type']          = 'Payment';
                    $payment_array['number']        =  $payment->reference;
                    $payment_array['status']        = '';
                    $payment_array['due_at']        = '';
                    $payment_array['id']            = 'p-'.$payment->id;
                    $payment_array['customer_id']   = $payment->customer_id;

                    $payment->category = $item->category;


                    $invoice_total_transcation[] = $payment_array;

                    $amount = $payment->getConvertedAmount();

                    $amounts['paid'] += $amount;

                    $payments += $amount;
                }
                if ($item->invoice_status_code == 'paid') {
                    continue;
                }
                // Check if it's open or overdue invoice
                if ($item->due_at > $today) {
                    $amounts['open'] += $item->getConvertedAmount() - $payments;
                } else {
                    $amounts['overdue'] += $item->getConvertedAmount() - $payments;
                }
            }
            $transactions = $invoice_total_transcation;
        }


        $customer_name = $this->parent_customer_id($customer->id);

        return view('accounts.incomes.customers.show', compact('customer', 'counts', 'amounts', 'transactions','customer_name'));
    }


    

    protected function addTransactions($items, $type, $category = null)
    {   
            foreach ($items as $item) {
                $data = [
                    'invoiced_at'       => $item->invoiced_at,
                    'type'              => $type,
                    'invoice_number'    => $item->invoice_number,
                    'due_at'            => $item->due_at,
                    'amount'            => $item->amount,
                    'currency_code'     => $item->currency_code,
                    'customer_id'       => $item->customer_id,
                    'id'                => $item->id,
                    'status'            => isset($item->status->code)? $item->status->code :'Closed',
                    'customers'         => isset($item->customer->name)? $item->status->name :'',
                    'address'           =>$item->address,
                ];
               

                $this->transactions[] = (object) $data;
            }
    }
    protected function getTransactions($request)
    {
        // Sort items
        if (isset($request['sort'])) {
            if ($request['order'] == 'asc') {
                $f = 'sortBy';
            } else {
                $f = 'sortByDesc';
            }
            $transactions = collect($this->transactions)->$f($request['sort']);
        } else {
            $transactions = collect($this->transactions)->sortByDesc('paid_at');
        }

        return $transactions;
    }

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

        if($request->subcustomer){
             $request['parent_id'] = $request->parent_id;
             $request['bill_to'] = 'parent';
        }else{
            $request['parent_id']  = null;
            $request['bill_to'] = 'customer';
        } 

        if($request->same_as_billing){
            $request['shipping_address'] = $request->address;
            $request['same_as_billing'] = '1';
        }
        
        $customer = Customer::create($request->all());

        if($request->timesheet && $request->consultant){
            $request['consultant'] = $request->consultant.'-'.'consultant';
            $request['timesheet'] = $request->timesheet;
        }else if(!$request->consultant && $request->timesheet){

             $request['consultant'] = $customer->id.'-'.'customer';
             $request['timesheet'] = $request->timesheet;
        }else{
             $request['consultant'] = null;
             $request['timesheet'] = null;
        }

        $customer->consultant = $request['consultant'];
        $customer->timesheet =  $request['timesheet'];
        $customer->update(); 




        $message = trans('messages.success.added', ['type' => trans_choice('general.customers', 1)]);

        \Session::flash('success',$message);

        return redirect('incomes/customers');
    }

    /**
     * Import the specified resource.
     *
     * @param  ImportFile  $import
     *
     * @return Response
     */
    public function import(ImportFile $import)
    {
      $rows = $import->all();
        foreach ($rows as $row) {
          
            $customer_name =  explode(':',$row['customer']);
            if(count($customer_name) > 1){
                $name = $customer_name[count($customer_name)-1];
                $parent_id = Customer::where('name' , 'like', '%'. $customer_name[count($customer_name)-2])->first()->id;
                $bill_to = 'parent';

            }else{
                $name = $customer_name[0]; 
                $parent_id = ''; 
                $bill_to = 'customer';

            }
            if($row['terms']){
                $term_id = Terms::where('name', 'like' , '%'. $row['terms'])->first();
                if($term_id){
                    $term = $term_id;
                }else{
                    $term_new['name'] = $row['terms'];
                    $term_new['term_days'] = explode(' ',$row['terms'])[1];
                    $term_new['company_id'] = session('company_id');
                    $term = Terms::create($term_new);
                }
            }

            switch ($row->active_status) {
                case 'Active':
                   $enabled = '1';
                break;
                case 'In-Active':
                  $enabled = '0';
                break;
                default:
                    $enabled = '1';
                break;
            }

            $data['name']                   =     $name;
            $data['customer_email']         =     $row['main_email'];
            $data['company']                =     $row['company'];
            $data['net_term']               =     isset($term->id)?$term->id:0;
            $data['tax_number']             =     $row['tax_item'];
            $data['phone']                  =     $row['main_phone']; 
            $data['address']                =     $row['bill_to_1'] . $row['bill_to_2'] . $row['bill_to_3'] . $row['bill_to_4']. $row['bill_to_5'];
            $data['website']                =     isset($row['website'])?$row['website']:'';
            $data['currency_code']          =     'USD';
            $data['payment_method']         =     '2';
            $data['enabled']                =     $enabled;
            $data['parent_id']              =     $parent_id;
            $data['bill_to']                =     $bill_to;
            $data['address']                =     $row['bill_to_1'] . $row['bill_to_2'] . $row['bill_to_3'] . $row['bill_to_4']. $row['bill_to_5']; 
            $data['shipping_address']       =     $row['ship_to_1'].$row['ship_to_2'].$row['ship_to_3'].$row['ship_to_4'].$row['ship_to_5']; 
            $data['company_id'] = session('company_id');
            
            if (empty($data['customer_email'])) {
                $data['customer_email'] = '';
            }
            
            Customer::create($data);
        }

        $message = trans('messages.success.imported', ['type' => trans_choice('general.customers', 2)]);

        \Session::flash('success',$message);
        return redirect('incomes/customers');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  Customer  $customer
     *
     * @return Response
     */
    public function edit(Customer $customer)
    {
        $currencies = Currency::enabled()->pluck('name', 'code');

        $terms = Terms::pluck('name','id');

        $payment_methods = Modules::getPaymentMethods();

        $elements =    Customer::select('id','name','parent_id')->get()->toArray();

        $customers = $this->bulidCustomer($elements);

        $consultants  = Student::where('status','in_job')->pluck('first_name','user_id');
        
        return view('accounts.incomes.customers.edit', compact('customer', 'currencies','terms','payment_methods','customers','consultants'));
    }

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

        if($request->subcustomer){
             $request['parent_id'] = $request->parent_id;
             $request['bill_to'] = 'parent';
        }else{
            $request['parent_id']  = null;
            $request['bill_to'] = 'customer';
        }  
        if($request->timesheet && $request->consultant){
            $request['consultant'] = $request->consultant.'-'.'consultant';
            $request['timesheet'] = $request->timesheet;
        }else if(!$request->consultant && $request->timesheet){
             $request['consultant'] = $customer->id.'-'.'customer';
             $request['timesheet'] = $request->timesheet;
        }else{
             $request['consultant'] = null;
             $request['timesheet'] = null;
        } 
  
        $customer->update($request->all()); 

        $message = trans('messages.success.updated', ['type' => trans_choice('general.customers', 1)]);

        \Session::flash('success',$message);

        return redirect('incomes/customers');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  Customer  $customer
     *
     * @return Response
     */
    public function destroy(Customer $customer)
    {
        $relationships = $this->countRelationships($customer, [
            'invoices' => 'invoices',
            'revenues' => 'revenues',
        ]);

        if (empty($relationships)) {
            $customer->delete();

            $message = trans('messages.success.deleted', ['type' => trans_choice('general.customers', 1)]);

            \Session::flash('success',$message);
        } else {
            $message = trans('messages.warning.deleted', ['name' => $customer->name, 'text' => implode(', ', $relationships)]);

            \Session::flash('warning',$message);
        }

        return redirect('incomes/customers');
    }

    /*
    * Collection Report For A Customer 
    * 
    */
    public function collectioncenter(){

        $date = Date::today()->format('Y-m-d');
        if(request('almost_due_at')){
            $date_1 = $this->date_format_change_unique(request('almost_due_at'));
            $tenthday =  date("Y-m-d", strtotime($date_1[0])); 
        }else{
            $tenth = strtotime("+10 day");
            $tenthday = date('Y-m-d',$tenth);
        }
        $customers = Customer::with(['invoices' => function($q) use($date) {
            $q->whereDate('invoices.due_at', '<=', $date);
            $q->where('invoices.invoice_status_code', '!=', 'paid');   
        }])->get();  

        $customer_almostdue = Customer::with(['invoices' => function($q) use($date , $tenthday) {
            $q->whereDate('invoices.due_at', '>=', $date);
            $q->whereDate('invoices.due_at', '<=', $tenthday);
            $q->where('invoices.invoice_status_code', '!=', 'paid'); 
        }])->get();

       return view('accounts.incomes.customers.collectioncenter',compact('customers','customer_almostdue'));
    }

    public function individualcollectioncenter($id){

        $customer_child = $this->child_customer_id($id);

        $customer_full_details = $this->parent_customer_id($id);


        array_push($customer_child,$id);
         $customers = [];
         $customer_almostdue = [];

        $date = Date::today()->format('Y-m-d');
        if(request('almost_due_at')){
            $date_1 = $this->date_format_change_unique(request('almost_due_at'));
            $tenthday =  date("Y-m-d", strtotime($date_1[0])); 
        }else{
            $tenth = strtotime("+10 day");
            $tenthday = date('Y-m-d',$tenth);
        }

        foreach ($customer_child as $key => $child) {
            $customers[] = Customer::with(['invoices' => function($q) use($date) {
                $q->whereDate('invoices.due_at', '<=', $date);
                $q->where('invoices.invoice_status_code', '!=', 'paid');   
            }])->find($child);

            $customer_almostdue[] = Customer::with(['invoices' => function($q) use($date , $tenthday) {
                $q->whereDate('invoices.due_at', '>=', $date);
                $q->whereDate('invoices.due_at', '<=', $tenthday);
                $q->where('invoices.invoice_status_code', '!=', 'paid'); 
            }])->find($child);
        }



     return view('accounts.incomes.customers.individualcollectioncenter',compact('customers','customer_almostdue','customer_full_details','id'));
    }




    public function currency()
    {
        $customer_id = request('customer_id');

        $customer = Customer::find($customer_id);

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

    public function autocompletecustomer()
    {
        $customer_id = request('customer_id');
        $customer = Customer::with(['terms'])->find($customer_id);
        $full_details = $this->parent_customer_id($customer_id);

        return response()->json(['customer' => $customer ,'full_details' => $full_details]);
    }

    public function customer(Request $request)
    {        
        if(empty($request['customer_email'])){
            $request['customer_email'] =''; 
        }
        if($request['same_as_billing']){
            $request['shipping_address']  = $request['address'];
        }
        if($request['customer_id_save']){
            $request['parent_id'] = $request['customer_id_save'];
            $request['bill_to'] = $request['bill_to'];
        }
        $request['bill_to'] = 'customer';
        $customer = Customer::create($request->all());

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

    public function child_customer_id($id)
    {
        $elements = Customer::with(['childrenRecrusive'])->select('id','name','parent_id')->find($id);
        foreach ($elements->childrenRecrusive as $key => $value) {
                $this->buildChildCustomer($value);
            if(!($value->children->isEmpty())){
                foreach ($value->children as $key => $children) {
                    $this->buildChildCustomer($children);
                }
            }
        }

        return $this->customer_child;
    }

    public function buildChildCustomer($elements)
    {
        array_push($this->customer_child,$elements->id);
    }

    /*public function buildChildCustomer($elements){
        
    }*/


    public function parent_customer_id($id)
    {
        $customer_name = Customer::with(['parentRecrusive' => function($query) {
                        $query->select(['id','name','parent_id']); }
                    ])->select('id','name','parent_id')->find($id);
        $name = '';
        $parent_id_string ='';
        if(!is_null($customer_name->parentRecrusive)) {
            if($customer_name->parentRecrusive->parent_re){
                $name_p = $this->bulidNameCustomer($customer_name->parentRecrusive->parent_re);
                
                foreach (array_reverse($name_p) as $key => $value) {
                   $name .= $value['name'] . ':'; 
                   $parent_id_string .= $value['parent_id'] . ',';
                }
            }
          
            $parent_id_string .= $customer_name->parentRecrusive->id . ',';
            $name .= $customer_name->parentRecrusive->name . ':';
            $parent_id = explode(',', $parent_id_string);
            $parent_re = $parent_id[count($parent_id)-2];

        }

        $name .= $customer_name->name ;
        $parent_one_id = isset($parent_id[0]) ?  $parent_id[0] : '0';
        $parent_id     = isset($parent_re) ? $parent_re : $id ;

        return  response()->json(['full_name'=> $name ,'parent_id' => $parent_id , 'parent_one_id' => $parent_one_id,'parent_id_string'=>$parent_id_string]);
    }
 
    function bulidNameCustomer($elements) {
        if($elements){
            $arrayName = array('name' =>  $elements->name,
                                'parent_id' => $elements->id );
            array_push($this->customer_parent,$arrayName);
            if($elements->parent_re){
            $children = $this->bulidNameCustomer($elements->parent_re);
            }
        }
        return $this->customer_parent;
    }

    /**
     * Generate a pagination collection.
     *
     * @param array|Collection      $items
     * @param int   $perPage
     * @param int   $page
     * @param array $options
     *
     * @return LengthAwarePaginator
     */
    public function paginate($items, $perPage = 25, $page = null, $options = [])
    {
        $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
        $items = $items instanceof Collection ? $items : Collection::make($items);

        return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
    }
}
