<?php

namespace App\Http\Controllers\Admin\Accounting;

use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Accounting\Journal;
use App\Models\Expense;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Helpers\CustomDateFilter;

class ExpenseController extends Controller
{

    function __construct()
    {
        $this->middleware('permission:Expense List', ['only' => ['index']]);
        $this->middleware('permission:Expense Create', ['only' => ['store','create']]);
        $this->middleware('permission:Expense Edit', ['only' => ['store','create']]);
        $this->middleware('permission:Expense Delete', ['only' => ['destroy']]);
    }
    public function getExpense(Request $request){
        $data = Expense::where(function($query) use ($request){
            $query->whereIn('branch_id',Helper::byBranch());
            $query->where('currency_id',Helper::byCurrency());
            if($request->expense_list == 1){
                $query->search($request->search_text);
            } else {
                $chart_of_acc_id = $request->chart_of_acc_id;
                if($chart_of_acc_id!=null){
                    $query->where('expenses.chart_of_acc_id',$chart_of_acc_id);
                }
                $query->where('expenses.invoice_number', 'LIKE',isset($request->invoice_number)? $request->invoice_number:NULL);
                if($request->expense_date) {
                    $query->whereBetween(DB::raw("DATE_FORMAT(expense_date, '%Y-%m-%d')"), $request->expense_date ?? CustomDateFilter::thisMonth());
                }
            }
        })
        ->orderBy('expenses.id','DESC')
        ->orderBy('expenses.expense_date','DESC')
        ->groupby('expenses.parent_id');
        return $data;
    }

    public function index(Request $request)
    {
        $per_page = $request->per_page == null?25:$request->per_page;
        $funGetExpense = $this->getExpense($request)->paginate($per_page);

        $page =  json_encode($funGetExpense);
        $paginate = json_decode($page);
        $data = $funGetExpense->map(function($value){
            return [
                'id'              => $value->id,
                'parent_id'       => $value->parent_id,
                'invoice_number'  => $value->invoice_number,
                'expense_date'    => $value->expense_date,
                'desc'            => $value->desc,
                'debit'           => $value->debit,
                'credit'          => $value->credit,
                'chart_of_acc_id' => Expense::where('parent_id',$value->parent_id)->where('credit',0)->max('chart_of_acc_id'),
                'payment_model_id'=> $value->payment_model_id,
                'chart_code'      => $value->chartOfAcc->chart_code,
                'chart_name'      => $value->chartOfAcc->chart_name,
                'created_by'      => $value->createdBy->name,
                'sub_expense'     => Expense::where('expenses.parent_id',$value->parent_id)->get()->map(function($val){
                    return [
                        'id'         => $val->id,
                        'debit'      => $val->debit,
                        'credit'     => $val->credit,
                        'parent_id'  => $val->parent_id,
                        'chart_code' => $val->chartOfAcc->chart_code,
                        'chart_name' => $val->chartOfAcc->chart_name,
                    ];
                }),
                'sum_debit' => Expense::where('expenses.parent_id',$value->parent_id)->sum('expenses.debit'),
                'sum_credit'=> Expense::where('expenses.parent_id',$value->parent_id)->sum('expenses.credit'),
            ];
        });

        $res = [
            'data'  => $data,
            'links'    => [
                'first'=> $paginate->first_page_url,
                'last' => $paginate->last_page_url,
                'next' => $paginate->next_page_url,
                'prev' => $paginate->prev_page_url,
            ],
            'meta'   => [
                'current_page'  => $funGetExpense->currentPage(),
                'last_page'     => $funGetExpense->lastPage(),
                'per_page'      => $funGetExpense->perPage(),
                'total'         => $funGetExpense->total(),
                'to'            => $paginate->to,
            ],
        ];
        return response()->json($res, 200);
    }

    public function store(Request $request)
    {
        $request->validate([
            'desc'                 => 'required',
            'invoice_number'       => 'required|max:255',
            'expense_date'         => 'required',
            'expense_rows.*.credit'=> 'required',
            'expense_rows.*.debit' => 'required',
            'expense_rows.*.chart_of_acc_id' => 'required',
        ]);
        DB::beginTransaction();
        try {
            $expense = $request->expense_rows;
            $expense_parent_id = Helper::findParentIdExpense();
            $journal_parent_id = Helper::findParentId();
            foreach($expense as $value){

                $expense_credit = new Expense();
                $expense_credit->parent_id  = $expense_parent_id;
                $expense_credit->branch_id  = Auth::user()->branch_id;
                $expense_credit->currency_id  = Auth::user()->currency_id;
                $expense_credit->credit      = $value['credit'];
                $expense_credit->desc       = $request->desc;
                $expense_credit->created_by = Auth::user()->id;
                $expense_credit->invoice_number = $request->invoice_number;
                $expense_credit->chart_of_acc_id = $value['chart_of_acc_id'];
                $expense_credit->expense_date  = $request->expense_date;
                $expense_credit->save();

                $journal_credit = new Journal();
                $journal_credit->parent_id  = $journal_parent_id;
                $journal_credit->branch_id  = Auth::user()->branch_id;
                $journal_credit->currency_id  = Auth::user()->currency_id;
                $journal_credit->credit      = $value['credit'];
                $journal_credit->desc       = $request->desc;
                $journal_credit->created_by = Auth::user()->id;
                $journal_credit->invoice_number = $request->invoice_number;
                $journal_credit->chart_of_acc_id = $value['chart_of_acc_id'];
                $journal_credit->journal_date  = $request->expense_date;
                $journal_credit->payment_model_type  = get_class($expense_credit);
                $journal_credit->payment_model_id  = $expense_credit->id;
                $journal_credit->save();

                $detail_credit = new Expense();
                $detail_credit->parent_id  = $expense_parent_id;
                $detail_credit->branch_id  = Auth::user()->branch_id;
                $detail_credit->currency_id  = Auth::user()->currency_id;
                $detail_credit->debit      = $value['credit'];
                $detail_credit->desc       = $request->desc;
                $detail_credit->created_by = Auth::user()->id;
                $detail_credit->invoice_number = $request->invoice_number;
                $detail_credit->chart_of_acc_id = $request->chart_of_acc_id;
                $detail_credit->expense_date  = $request->expense_date;
                $detail_credit->save();

                $journal_detail_credit = new Journal();
                $journal_detail_credit->parent_id  = $journal_parent_id;
                $journal_detail_credit->branch_id  = Auth::user()->branch_id;
                $journal_detail_credit->currency_id  = Auth::user()->currency_id;
                $journal_detail_credit->debit      = $value['credit'];
                $journal_detail_credit->desc       = $request->desc;
                $journal_detail_credit->created_by = Auth::user()->id;
                $journal_detail_credit->invoice_number = $request->invoice_number;
                $journal_detail_credit->chart_of_acc_id = $request->chart_of_acc_id;
                $journal_detail_credit->journal_date  = $request->expense_date;
                $journal_detail_credit->payment_model_type  = get_class($detail_credit);
                $journal_detail_credit->payment_model_id  = $detail_credit->id;
                $journal_detail_credit->save();
            }
            DB::commit();
            return response()->json(["message" => "$request->invoice_number successfully created."], 200);
        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(["message" => "Something wrong, Please check it !"], 200);
        }
    }

    public function show($id)
    {
        $data = Expense::select(
            'expenses.*',
            DB::raw("CONCAT(chart_of_accounts.chart_code,'-',chart_of_accounts.chart_name) as chart_code_name"),
        )
        ->leftjoin('chart_of_accounts','chart_of_accounts.id','expenses.chart_of_acc_id')
        ->where('expenses.parent_id',$id)
        ->where('expenses.debit',0)
        ->orderBy('expenses.id','ASC')
        ->get();
        return $data;
    }
    
    public function update(Request $request)
    {
        $request->validate([
            'desc'                 => 'required',
            'invoice_number'       => 'required|max:255',
            'expense_date'         => 'required',
            'expense_rows.*.credit'=> 'required',
            'expense_rows.*.debit' => 'required',
            'expense_rows.*.chart_of_acc_id' => 'required',
        ]);
        DB::beginTransaction();
        try {
            $expense = $request->expense_rows;
            foreach($expense as $value) {
                $expense_credit = Expense::where('parent_id',$request->parent_id)->where('id',$request->id)->first();
                $expense_credit->credit          = $value['credit'];
                $expense_credit->desc            = $request->desc;
                $expense_credit->created_by      = Auth::user()->id;
                $expense_credit->invoice_number  = $request->invoice_number;
                $expense_credit->chart_of_acc_id = $value['chart_of_acc_id'];
                $expense_credit->expense_date    = $request->expense_date;
                $expense_credit->update();

                $journal_credit = Journal::where('payment_model_type',get_class($expense_credit))->where('payment_model_id',$expense_credit->id)->first();
                $journal_credit->credit            = $value['credit'];
                $journal_credit->desc              = $request->desc;
                $journal_credit->created_by        = Auth::user()->id;
                $journal_credit->invoice_number    = $request->invoice_number;
                $journal_credit->chart_of_acc_id   = $value['chart_of_acc_id'];
                $journal_credit->journal_date      = $request->expense_date;
                $journal_credit->payment_model_type= get_class($expense_credit);
                $journal_credit->payment_model_id  = $expense_credit->id;
                $journal_credit->update();

                $detail_credit = Expense::where('parent_id',$request->parent_id)->where('id','!=',$request->id)->first();
                $detail_credit->debit          = $value['credit'];
                $detail_credit->desc           = $request->desc;
                $detail_credit->created_by     = Auth::user()->id;
                $detail_credit->invoice_number = $request->invoice_number;
                $detail_credit->chart_of_acc_id= $request->chart_of_acc_id;
                $detail_credit->expense_date   = $request->expense_date;
                $detail_credit->update();

                $journal_detail_credit =Journal::where('payment_model_type',get_class($detail_credit))->where('payment_model_id',$detail_credit->id)->first();
                $journal_detail_credit->debit             = $value['credit'];
                $journal_detail_credit->desc              = $request->desc;
                $journal_detail_credit->created_by        = Auth::user()->id;
                $journal_detail_credit->invoice_number    = $request->invoice_number;
                $journal_detail_credit->chart_of_acc_id   = $request->chart_of_acc_id;
                $journal_detail_credit->journal_date      = $request->expense_date;
                $journal_detail_credit->payment_model_type= get_class($detail_credit);
                $journal_detail_credit->payment_model_id  = $detail_credit->id;
                $journal_detail_credit->update();
            }
            DB::commit();
            $res = [
                "status" => 1,
                "message" => "update successfully."
            ];
        } catch (\Exception $e) {
            DB::rollback();
            $res = [
                'status'  => 0,
                'message' => 'update not success',
                'data'    => $e->getMessage(),
            ];
        }
        return response()->json($res,200);
    }

    public function destroy($id)
    {
        DB::beginTransaction();
        try {

            $expense = Expense::where('parent_id',$id)->get();

            foreach($expense as $key=>$val)
            {
                Journal::where('payment_model_type',get_class($val))->where('payment_model_id',$val->id)->delete();
            }
            Expense::where('parent_id',$id)->delete();
            DB::commit();
            $res = [
                "status" => 1,
                "message" => "delete successfully."
            ];
        } catch (\Exception $e) {
            DB::rollback();
            $res = [
                'status'  => 0,
                'message' => 'delete not success',
                'data'    => $e->getMessage(),
            ];
        }
        return response()->json($res,200);
    }
}