<?php

class InstallmentController extends \BaseController {

	/**
	 * Display a listing of the resource.
	 * GET /installment
	 *
	 * @return Response
	 */
	public function index()
	{
        $installments = Installment::customers()
                                    ->selectCustomer();
        $name = Input::get('name');
        $pattern = "%".$name."%";
        if (!empty($name)) {
        	$installments->filterCustomer($pattern);
        }
        if (!empty(Input::get('invoice_id'))) {
            $installments->where('installments.id', Input::get('invoice_id'));
        }
        if (!empty(Input::get("loan_type")) && Input::get("loan_type") != "all") {
            $installments->where("installments.loan_type", Input::get("loan_type"));
        }
        if (!empty(Input::get("status")) && Input::get("status") != "all") {
            $installments->where("installments.status", Input::get("status"));
        }
        if (!empty(Input::get('start_date')) && !empty(Input::get('end_date'))) {
            $start = new \Carbon\Carbon(Input::get('start_date'));
        	$end = new \Carbon\Carbon(Input::get('end_date'));
        	$end->addHours(23)->addMinutes(59)->addSeconds(59);

            $installments->byLoanDate([$start, $end]);
        }
        if (!empty(Input::get('paginate'))) {
            $installments = Input::get('paginate') == 'all' ? $installments->get() : $installments->paginate(Input::get('paginate'));
        } else {
            $installments = $installments->paginate(10);
        }
		return View::make('installments.index')
                    ->withInstallments($installments);
	}

	/**
	 * Show the form for creating a new resource.
	 * GET /installment/create
	 *
	 * @return Response
	 */
	public function create()
	{
        $customers = Customer::getFullName()->lists('full_name', 'id');
        $customers['none']	= trans('installments.customer');
				return View::make('installments.form')
                    ->withCustomers($customers);
	}

	/**
	 * Store a newly created resource in storage.
	 * POST /installment
	 *
	 * @return Response
	 */
	public function store()
	{
		$data = Input::except(['_token', 'submit']);
        $rules = [
           'type_of_product' => 'required',
           'product_name' => 'required',
           'model' => 'required',
           'imie' => 'required|unique:installments,imie',
           'rate' =>  "required",
           'total_price'  =>  "required",
           'duration'     =>  "required",
           'in_date'    =>  "required|regex:/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}$/",
        ];
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return Response::json([
                'success'   =>  false,
                'errors'    =>  $validator->getMessageBag()->toArray()
            ], 400);
        }
        if ($data['deposit'] > $data['total_price']) {
          return Response::json([
                'success'   =>  false,
                'errors'    =>  ['deposit' => trans('installments.deposit_error') ]
            ], 400);
        }
        $success = false;
        DB::beginTransaction();
        try {
            $data['user_id'] = Auth::user()->id;
            if (!empty($data['in_date'])) {
            $data['in_date']  = Carbon\Carbon::createFromFormat("d/m/Y", $data['in_date']);
            } else {
                $data['in_date'] = null;
            }
            // return ['error' => true, 'message' => $data];
            $installment = Installment::create($data);
            $profit = Profit::addExpense($installment);
            // Find principle vale
            for ($i=1; $i <= $installment->duration ; $i++) {
                $t_payment = $i == 1 ? $installment->getPayFirstMonth() : $installment->getMonthlyPayment();
                $p = $installment->getMonthlyPriciple();
                $payment = Payment::create([
                    'installment_id'   =>  $installment->id,
                    'payment_date'   =>  add_loan_months($installment->in_date, $i),
                    'amount'   => $t_payment,
                    'term_id' => $i,
                    'interest'  =>  $t_payment - $p,
                    'principal' => $p  
                ]);
                if ($payment) {
                    $success = true;
                }
            }
            if ($success) {
                DB::commit();
                return [
                    'error' => false, 
                    'message' => trans('messages.success-to-create'), 
                    'title' => trans('installments.msg.title')
                ];
            }
        } catch (Exception $e) {
            $success = false;
            DB::rollback();
            return ['error' => true, 'message' => $e->getMessage()];
        }
	}

	/**
	 * Display the specified resource.
	 * GET /installment/{id}
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function show($id)
	{
        $installment = Installment::byId($id);
        if (empty($installment)) return Redirect::route('installments.index');
        if ($installment->loan_type == "emi") return Redirect::route("emiloans.show", $installment->id);
        $numberOfM = Payment::where('installment_id', $id)->where('is_paid', false)->count();
        $termPaid = Payment::paidTime($id);
        $payments = Payment::where('installment_id', $id)->get();
        $payOffDay = Payment::orderBy('payment_date', 'DESC')->where('installment_id', $id)->first();
        return View::make('installments.show', compact('installment'))
        			->with('termPaid', $termPaid)
        			->withPayments($payments)
                    ->with('numbers', $numberOfM)
        			->with('payOffDay', $payOffDay);
	}

	/**
	 * Show the form for editing the specified resource.
	 * GET /installment/{id}/edit
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function edit($id)
	{
		$installment = Installment::find($id);
        return View::make('loan_customers.inc.form_ajax', compact('installment'));
	}

	/**
	 * Update the specified resource in storage.
	 * PUT /installment/{id}
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function update($id)
	{
        $data = Input::except(['_token', 'submit']);
        $installment = Installment::find($id);
        $rules = [
           'type_of_product' => 'required',
           'product_name' => 'required',
           'model' => 'required',
           'imie' => 'required|unique:installments,imie,'. $installment->id,
           'rate' =>  "required",
           'total_price'  =>  "required",
           'duration'     =>  "required",
           'in_date'  =>  "required"
        ];
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return Response::json([
                'success'   =>  false,
                'errors'    =>  $validator->getMessageBag()->toArray()
            ], 400);
        }
        if ($data['deposit'] > $data['total_price']) {
            return Response::json([
                'success'   =>  false,
                'errors'    =>  ['deposit' => trans('installments.deposit_error') ]
            ], 400);
        }
        $success = false;
        DB::beginTransaction();

        try {

        if ($installment->total_price != $data['total_price']
            || $installment->rate != $data['rate']
            || $installment->deposit != $data['deposit']
            || $installment->duration != $data['duration']
            || $installment->in_date != $data['in_date']
        ) {
            if (!empty($data['in_date'])) {
                $data['in_date']  = Carbon\Carbon::createFromFormat("d/m/Y", $data['in_date']);
            } else {
                $data['in_date'] = null;
            }
            $payments = Payment::where('installment_id', $id)->delete();
            $paymentIds = Payment::where('installment_id', $id)->pluck("id");
            ReceiptIncome::whereIn('payment_id', $paymentIds)->delete();
            $installment->update($data);
            $updated = Installment::find($id);
            $profit = Profit::addExpense($updated);
            for ($i=1; $i <= $updated->duration ; $i++) {
                $t_payment = $i == 1 ? $installment->getPayFirstMonth() : $installment->getMonthlyPayment();
                $p = $installment->getMonthlyPriciple();
                $payment = Payment::create([
                    'installment_id'    =>  $updated->id,
                    'payment_date'      =>  add_loan_months($updated->in_date, $i),
                    'amount'   =>  $t_payment,
                    'term_id' =>  $i,
                    'interest'  =>  $t_payment - $p,
                    'principal' => $p  
                ]);
                if ($payment) {
                    $success = true;
                }
            }
            if ($success) {
                DB::commit();
                return [
                    'error' => false,
                    'message' =>  trans('messages.success-to-update')
                ];
            }

        } else {
            if (!empty($data['in_date'])) {
                $data['in_date']  = Carbon\Carbon::createFromFormat("d/m/Y", $data['in_date']);
            } else {
                $data['in_date'] = null;
            }
            $updated = $installment->update($data);
            $profit = Profit::addExpense($updated);
            DB::commit();
            return [
                'error' => false,
                'message' =>  trans('messages.success-to-update')
            ];
        }

        } catch (Exception $e) {
            DB::rollback();
            return [
                'error' => true, 
                'message' => trans('messages.fail-to-update'),
                'error_msg' => $e->getMessage()
            ];
        }

	}

	/**
	 * Remove the specified resource from storage.
	 * DELETE /installment/{id}
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function destroy($id)
	{ 
        DB::beginTransaction();
        try {
            $installment = Installment::where('id', $id)->first();
            $profit      = Profit::where('installment_id', $id)->delete();
            if ($installment) {
                $payments = Payment::where('installment_id', $id)->get();
                if (count($payments) > 0) {
                    foreach($payments as $pay) {
                        ReceiptIncome::where('payment_id', $pay->id)->delete();
                        $pay->delete();
                    }
                }
                $installment->delete();
                DB::commit();
                return [
                    'error' => false, 
                    'message' => trans('messages.success-to-delete')
                ];
            } else {
                DB::rollback();
                return [
                    'error' => true, 
                    'message' => trans('messages.fail-to-delete')
                ];
            }
        } catch (Exception $e) {
            
            DB::rollback();
            return [
                'error' => true, 
                'message' => trans('messages.fail-to-delete'),
                'msg' => $e->getMessage()
            ];
        }
	}

    public function getLatePayments()
    {
        $latePayments = Payment::latePayment();
        return View::make('installments.late')->with('latePayments', $latePayments);
    }

    public function payment()
    {
        $data = Input::all();
        $rules = [
           'receipt_id' => 'required|unique:receipt_incomes',
           'payment_name' => 'required',
           'recieve_amount'   =>  'required'
        ];

        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return Response::json([
                'success'   =>  false,
                'errors'    =>  $validator->getMessageBag()->toArray()
            ], 400);
        }
        if ($data['recieve_amount'] < $data['payment_amount']) {
          return Response::json([
                'success'   =>  false,
                'errors'    =>  ['recieve_amount' => trans('installments.total_payment_amount', ['attribute' => money($data['payment_amount'])]) ]
            ], 400);
        }
        DB::beginTransaction();
        try {
            $data['payment_date']  = Carbon\Carbon::createFromFormat("d/m/Y", $data['payment_date']);

            // create new receipt income for new payment
            $receipt = new ReceiptIncome;
            $receipt->receipt_id      = $data['receipt_id'];
            $receipt->payment_name    = $data['payment_name'];
            $receipt->total_amount    = $data['payment_amount'];
            $receipt->recieve_amount  = $data['recieve_amount'];
            $receipt->total_as_letter = $data['total_as_letter'];
            $receipt->in_digit_of     = $data['in_digit_of'];
            $receipt->with_doc        = $data['with_doc'];
            $receipt->payment_id        = $data['payment_id'];
            $receipt->user_id         = Auth::user()->id;
            $receipt->save();
            // find and update existing payment
            $paymenId = Input::get('payment_id');
            $payment = Payment::find($paymenId);
            $payment->fee_date = $data['payment_date'];
            $payment->is_paid = true;
            //check late number of late day and calculate total amount of fee
            $payment->late_day = $payment->lateDay();
            $payment->fee_late = $data['late_amount'];
            $payment->receipt_id = $receipt->id;
            //New income
            $income = new Profit;
            $income->amount = $data['late_amount'] > 0 ? $data['payment_amount'] + $data['late_amount'] : $data['payment_amount'];
            $income->user_id = Auth::user()->id;
            $income->type = 'income';
            $income->description = "ប្រាក់បង់ប្រចាំខែ ប័ណ្ណចំណូលលេខ" . $data['receipt_id'];
            $income->receipt_id = $receipt->id;
            $income->created_at = $data['payment_date'];
            $income->updated_at = $data['payment_date'];
            $income->save();

            $installment = Installment::find($payment->installment_id);
            $paymentPrincipal = $payment->principal ? $payment->principal : $installment->getMonthlyPriciple();
            $payment->save();

            $P = Profit::addPrincipal([
                'amount' => $paymentPrincipal,
                'receipt_id' => $receipt->id,
                'payment_date' => $data['payment_date']
            ]);

            // count times of payment
            // if the last payment update
            // installment status to complete
            // update installment status
            $paidTime = Payment::where('is_paid', true)->where('installment_id', $payment->installment_id)->count();
            if ($paidTime == $installment->duration) {
                $installment->paid_off_date = Carbon\Carbon::now();
                $installment->status = "completed";
            } else {
                $installment->status = "proccessing";
            }
            if ($payment->save() && $installment->save()) {
                DB::commit();
                return ['error' => false, 'message' => trans('installments.msg.payment_success')];
            }

        } catch (Exception $e) {
            DB::rollback();
            return [
                'error' => true, 
                'message' => 'installments.msg.fail_payment',
                'error_mesage'  =>  $e->getMessage()
            ];
        }
    }


    /**
     * Print Installment loan
     */
    public function printInstallment($id)
    {
        $installment = Installment::join('loan_customers as lc', 'installments.customer_id', '=', 'lc.id')
                           ->join('users as u', 'u.id', '=', 'installments.user_id')
                           ->select(
                            'installments.*',
                            'u.first_name',
                            'u.last_name',
                            'lc.full_name_kh',
                            'lc.full_name_en',
                            'lc.gender',
                            'lc.tel'
                            )->where('installments.id', $id)->first();
        if (empty($installment)) return ['No Installment loan for print'];
        $termPaid = Payment::paidTime($id);
        $payments = Payment::where('installment_id', $id)->get();
        $payOffDay = Payment::orderBy('payment_date', 'DESC')->where('installment_id', $id)->first();
        $printType = "installment_print";
        if (!empty(Request::get('type')) && Request::get("type") == "detail") {
            $printType = "print_v2";
        }
        if (!empty(Request::get('type')) && Request::get("type") == "emi") {
            $printType = "emi_print";
        }
        return View::make('installments.inc.'.$printType, compact('installment'))
        			->with('termPaid', $termPaid)
        			->withPayments($payments)
        			->with('payOffDay', $payOffDay);
    }


    /**
     * Paid All remain payments
     */
    public function returnAll()
    {
        $data = Input::all();
        $rules = [
           'receipt_id' => 'required|unique:receipt_incomes',
           'payment_name' => 'required',
           'recieve_amount'   =>  'required',
            'payment_date' => 'required'
        ];

        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return Response::json([
                'success'   =>  false,
                'errors'    =>  $validator->getMessageBag()->toArray()
            ], 400);
        }
        if ($data['recieve_amount'] < $data['payment_amount']) {
            return Response::json([
                'success'   =>  false,
                'errors'    =>  ['recieve_amount' => trans('installments.total_payment_amount', ['attribute' => money($data['payment_amount'])]) ]
            ], 400);
        }
        DB::beginTransaction();
        try {
            // create new receipt income for new payment
            $data['payment_date']  = Carbon\Carbon::createFromFormat("d/m/Y", $data['payment_date']);
            $receipt = new ReceiptIncome;
            $receipt->receipt_id      = $data['receipt_id'];
            $receipt->payment_name    = $data['payment_name'];
            $receipt->total_amount    = $data['payment_amount'];
            $receipt->recieve_amount  = $data['recieve_amount'];
            $receipt->total_as_letter = $data['total_as_letter'];
            $receipt->in_digit_of     = $data['in_digit_of'];
            $receipt->with_doc        = $data['with_doc'];
            $receipt->user_id         = Auth::user()->id;
            $receipt->created_at = $data['payment_date'];
            $receipt->updated_at = $data['payment_date'];
            $receipt->save();

            // find and update existing payment
            $paymenId = Input::get('payment_id');
            $payment = Payment::find($paymenId);
            $payment->fee_date = $data['payment_date'];
            $payment->is_paid = true;
            //check late number of late day and calculate total amount of fee
            $payment->late_day = $payment->lateDay();
            $payment->fee_late = $data['late_amount'];
            $payment->is_paid_all = true;
            $payment->receipt_id = $receipt->id;
            $payment->save();
            //New income 
            $income = new Profit;
            $income->amount = $data['late_amount'] > 0 ? $data['payment_amount'] + $data['late_amount'] : $data['payment_amount'];
            $income->user_id = Auth::user()->id;
            $income->type = 'income';
            $income->description = "ប្រាក់បង់ផ្តាច់ ប័ណ្ណចំណូលលេខ" . $data['receipt_id'];
            $income->receipt_id = $receipt->id;
            $income->created_at = $data['payment_date'];
            $income->updated_at = $data['payment_date'];
            $income->save();

            $installment = Installment::find($payment->installment_id);
            $installment->status = "completed";
            $installment->paid_off_date = $data['payment_date'];
            $installment->paid_off_amount = $data['payment_amount'];
            if ($payment->save() && $installment->save()){
                DB::commit();
                return [
                    'error' => false, 
                    'message' => trans('installments.msg.payment_success'), 
                    'title' => trans('installments.msg.title')
                ];
            }

        } catch (Exception $e) {
            DB::rollback();
            return [
                'error' => true, 
                'message' => trans('installments.msg.fail_payment'), 
                'title' => trans('installments.msg.title'),
                'error_msg' =>  $e->getMessage()
            ];
        }
    }

    /**
     * Load Payment for via Ajax
     */
    public function formPayment($id)
    {
        $payment = Payment::find($id);
        return View::make('installments.inc.form_payment', [
            'payment' =>  $payment,
            'type' => 0
        ]);
    }

    /**
     * Form pay all remain payments
     */
    public function formPaymentAll($id) 
    {
        $payment = Payment::find($id);
        $installment = Installment::find($payment->installment_id);
        $termPaid = Payment::paidTime($payment->installment_id);
        $rate = $installment->getRate3Moths($termPaid) - $installment->addFirstMonth();
        $totalPayment = ($installment->getRemainPrinciple($termPaid) +$installment->getRate3Moths($termPaid));
        return View::make('installments.inc.form_payment_all', [
            'payment' =>  $payment, 
            'totalPayment'  => $totalPayment,
        ]);
    }

    /**
     * Display payment history
     */
    public function paymentHistory($id)
    {
        $receipt = ReceiptIncome::join('users', 'users.id', '=', 'receipt_incomes.user_id')
                              ->join('payments', 'payments.receipt_id', '=', 'receipt_incomes.id')
                              ->select('users.first_name', 'users.last_name', 'receipt_incomes.*', 'payments.late_day', 'payments.fee_late', 'payments.fee_date')
                              ->where('payments.id', $id)->first();
        return View::make('installments.inc.table_payment_history', ['receipt' => $receipt]);
    }

    /**
     * Get Expese and Income
     */
    public function expenseAndIncome()
    {
        return View::make('reports.expense_income');
    }

}