<?php

namespace App\Http\Controllers;

use App\Models\Chiffeur;
use App\Models\Sale;
use App\Models\Societe;
use App\Models\User;
use App\Models\UserWarehouse;
use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Models\Role;
use App\Models\Vehicule;
use App\Models\Voyage;
use App\Models\Warehouse;
use App\utils\helpers;
use Carbon\Carbon;
use DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ExpensesController extends BaseController
{

    //-------------- Show All  Expenses -----------\\

    public function index(request $request)
    {
        $this->authorizeForUser($request->user('api'), 'view', Expense::class);

        // How many items do you want to display.
        $perPage = $request->limit;
        $pageStart = \Request::get('page', 1);
        // Start displaying items from this number;
        $offSet = ((int)$pageStart * (int)$perPage) - (int)$perPage;
        $order = $request->SortField;
        $dir = $request->SortType;
        $helpers = new helpers();
        $role = Auth::user()->roles()->first();
        $view_records = Role::findOrFail($role->id)->inRole('record_view');
        // Filter fields With Params to retrieve
        $columns = array(0 => 'Ref', 1 => 'warehouse_id', 2 => 'date', 3 => 'expense_category_id');
        $param = array(0 => 'like', 1 => '=', 2 => '=', 3 => '=');
        $data = array();

        $from = $request->from;
        $to = $request->to;
        $society = $request->society;
        $vehicule = $request->vehicule;
        $chiffeur = $request->chiffeur;
        $num_facture = $request->num_facture;
        $sale = $request->sale;

        // Check If User Has Permission View  All Records
        $Expenses = Expense::with('expense_category', 'warehouse', 'societe', 'vehicule', 'chiffeur', 'sale')
            ->where('deleted_at', '=', null)
            ->where(function ($query) use ($view_records) {
                if (!$view_records) {
                    return $query->where('user_id', '=', Auth::user()->id);
                }
            })
            ->when($from && $to, function ($query) use ($from, $to) {
                return $query->whereBetween('date', [$from, $to]);
            })
            ->when($request->filled('society'), function ($query) use ($society) {
                return $query->whereHas('societe', function ($query) use ($society) {
                    $query->where('societes.id', $society);
                });
            })
            ->when($request->filled('vehicule'), function ($query) use ($vehicule) {
                return $query->whereHas('vehicule', function ($query) use ($vehicule) {
                    $query->where('vehicules.id', $vehicule);
                });
            })
            ->when($request->filled('chiffeur'), function ($query) use ($chiffeur) {
                return $query->whereHas('chiffeur', function ($query) use ($chiffeur) {
                    $query->where('chiffeurs.id', $chiffeur);
                });
            })
            ->when($request->filled('num_facture'), function ($query) use ($num_facture) {
                return $query->where('num_facture', 'Like', '%' . $num_facture . '%');
            })
            ->when($request->filled('sale'), function ($query) use ($sale) {
                return $query->whereHas('sale', function ($query) use ($sale) {
                    $query->where('sales.id', $sale);
                });
            });

        //Multiple Filter
        $Filtred = $helpers->filter($Expenses, $columns, $param, $request)
            //Search With Multiple Param
            ->where(function ($query) use ($request) {
                return $query->when($request->filled('search'), function ($query) use ($request) {
                    return $query->where('Ref', 'LIKE', "%{$request->search}%")
                        ->orWhere('date', 'LIKE', "%{$request->search}%")
                        ->orWhere('details', 'LIKE', "%{$request->search}%")
                        ->orWhere(function ($query) use ($request) {
                            return $query->whereHas('expense_category', function ($q) use ($request) {
                                $q->where('name', 'LIKE', "%{$request->search}%");
                            });
                        })
                        ->orWhere(function ($query) use ($request) {
                            return $query->whereHas('warehouse', function ($q) use ($request) {
                                $q->where('name', 'LIKE', "%{$request->search}%");
                            });
                        });
                });
            });
        $totalRows = $Filtred->count();
        if ($perPage == "-1") {
            $perPage = $totalRows;
        }
        $Expenses = $Filtred->offset($offSet)
            ->limit($perPage)
            ->orderBy($order, $dir)
            ->get();

        foreach ($Expenses as $Expense) {

            $item['id'] = $Expense->id;
            $item['societe_name'] = $Expense->societe->name;
            $item['source'] = $Expense->source;
            $item['attached'] = $Expense->chiffeur != null ? $Expense->chiffeur->firstname . ' ' . $Expense->chiffeur->lastname : ($Expense->sale != null ? $Expense->sale->Ref : '_');
            $item['date'] = $Expense->date;
            $item['Ref'] = $Expense->Ref;
            $item['details'] = $Expense->details;
            $item['amount'] = $Expense->amount;
            $item['warehouse_name'] = $Expense['warehouse']->name;
            $item['category_name'] = $Expense['expense_category']->name;
            $item['facturation'] = $Expense->facturation == true ? 'Facturé' : 'Non facturé';
            $item['num_facture'] = $Expense->num_facture;
            $data[] = $item;
        }

        $Expenses_category = ExpenseCategory::where('deleted_at', '=', null)->get(['id', 'name']);

        //get warehouses assigned to user
        $user_auth = auth()->user();
        if ($user_auth->is_all_warehouses) {
            $warehouses = Warehouse::where('deleted_at', '=', null)->get(['id', 'name']);
        } else {
            $warehouses_id = UserWarehouse::where('user_id', $user_auth->id)->pluck('warehouse_id')->toArray();
            $warehouses = Warehouse::where('deleted_at', '=', null)->whereIn('id', $warehouses_id)->get(['id', 'name']);
        }


        $dataWithFooter = [
            'amount' => round($Filtred->sum('amount'), 2, PHP_ROUND_HALF_DOWN),
        ];
        $dataWithFooter['children'] = $data;
        $dataWithFooter =  [$dataWithFooter];

        $societes = Societe::where('deleted_at', '=', null)->get(['id', 'name']);
        $vehicules = Vehicule::where('deleted_at', '=', null)->get(['id', 'matricule']);
        $chiffeurs = Chiffeur::where('deleted_at', '=', null)->get(['id', 'firstname', 'lastname']);
        $sales = Sale::where('deleted_at', '=', null)->get(['id', 'Ref']);

        return response()->json([
            'expenses' => $dataWithFooter,
            'Expenses_category' => $Expenses_category,
            'warehouses' => $warehouses,
            'totalRows' => $totalRows,

            'societies' => $societes,
            'vehicules' => $vehicules,
            'chiffeurs' => $chiffeurs,
            'sales' => $sales,
        ]);
    }

    //-------------- Store New Expense -----------\\

    public function store(Request $request)
    {
        $this->authorizeForUser($request->user('api'), 'create', Expense::class);

        request()->validate([
            'expense.source' => 'required',
            'expense.date' => 'required',
            'expense.warehouse_id' => 'required',
            'expense.category_id' => 'required',
            'expense.details' => 'required',
            'expense.amount' => 'required',
        ]);

        $expense = new Expense();
        $expense->user_id = Auth::user()->id;
        $expense->source = $request['expense']['source'];
        $expense->date = $request['expense']['date'];
        $expense->Ref = $this->getNumberOrder();
        $expense->societe_id = $request['expense']['societe_id'];
        $expense->warehouse_id = $request['expense']['warehouse_id'];
        $expense->expense_category_id = $request['expense']['category_id'];
        $expense->details = $request['expense']['details'];
        $expense->amount = $request['expense']['amount'];
        $expense->facturation = $request['expense']['facturation'];


        if ($expense->source == "Voyage") {
            $expense->sale_id = $request['expense']['sale_id'];
            $expense->chiffeur_id = $request['expense']['chiffeur_id'];
            $expense->vehicule_id = $request['expense']['vehicule_id'];
            $expense->num_facture = $request['expense']['num_facture'];
        } else if ($expense->source == "Person") {
            $expense->chiffeur_id = $request['expense']['chiffeur_id'];
        }

        $expense->save();

        return response()->json(['success' => true]);
    }

    //------------ function show -----------\\

    public function show($id)
    {
        //

    }

    //-------------- Update  Expense -----------\\

    public function update(Request $request, $id)
    {

        $this->authorizeForUser($request->user('api'), 'update', Expense::class);
        $role = Auth::user()->roles()->first();
        $view_records = Role::findOrFail($role->id)->inRole('record_view');
        $expense = Expense::findOrFail($id);

        // Check If User Has Permission view All Records
        if (!$view_records) {
            // Check If User->id === expense->id
            $this->authorizeForUser($request->user('api'), 'check_record', $expense);
        }

        request()->validate([
            'expense.source' => 'required',
            'expense.date' => 'required',
            'expense.societe_id' => 'required',
            'expense.warehouse_id' => 'required',
            'expense.category_id' => 'required',
            'expense.details' => 'required',
            'expense.amount' => 'required',
        ]);

        $expense->source = $request['expense']['source'];
        $expense->date = $request['expense']['date'];
        $expense->societe_id = $request['expense']['societe_id'];
        $expense->warehouse_id = $request['expense']['warehouse_id'];
        $expense->expense_category_id = $request['expense']['category_id'];
        $expense->details = $request['expense']['details'];
        $expense->amount = $request['expense']['amount'];
        $expense->facturation = $request['expense']['facturation'];

        if ($expense->source == "Voyage") {
            $expense->sale_id = $request['expense']['sale_id'];
            $expense->chiffeur_id = $request['expense']['chiffeur_id'];
            $expense->vehicule_id = $request['expense']['vehicule_id'];
            $expense->num_facture = $request['expense']['num_facture'];
        } else if ($expense->source == "Person") {
            $expense->chiffeur_id = $request['expense']['chiffeur_id'];
        }

        $expense->save();

        return response()->json(['success' => true]);
    }

    //-------------- Delete Expense -----------\\

    public function destroy(Request $request, $id)
    {
        $this->authorizeForUser($request->user('api'), 'delete', Expense::class);
        $role = Auth::user()->roles()->first();
        $view_records = Role::findOrFail($role->id)->inRole('record_view');
        $expense = Expense::findOrFail($id);

        // Check If User Has Permission view All Records
        if (!$view_records) {
            // Check If User->id === expense->id
            $this->authorizeForUser($request->user('api'), 'check_record', $expense);
        }

        $expense->update([
            'deleted_at' => Carbon::now(),
        ]);

        return response()->json(['success' => true]);
    }

    //-------------- Delete by selection  ---------------\\

    public function delete_by_selection(Request $request)
    {
        $this->authorizeForUser($request->user('api'), 'delete', Expense::class);
        $selectedIds = $request->selectedIds;
        $role = Auth::user()->roles()->first();
        $view_records = Role::findOrFail($role->id)->inRole('record_view');

        foreach ($selectedIds as $expense_id) {
            $expense = Expense::findOrFail($expense_id);

            // Check If User Has Permission view All Records
            if (!$view_records) {
                // Check If User->id === expense->id
                $this->authorizeForUser($request->user('api'), 'check_record', $expense);
            }
            $expense->update([
                'deleted_at' => Carbon::now(),
            ]);
        }
        return response()->json(['success' => true]);
    }

    //--------------- Reference Number of Expense ----------------\\

    public function getNumberOrder()
    {

        $last = DB::table('expenses')->latest('id')->first();

        if ($last) {
            $item = $last->Ref;
            $nwMsg = explode("_", $item);
            $inMsg = $nwMsg[1] + 1;
            $code = $nwMsg[0] . '_' . $inMsg;
        } else {
            $code = 'EXP_1111';
        }
        return $code;
    }


    //---------------- Show Form Create Expense ---------------\\

    public function create(Request $request)
    {

        $this->authorizeForUser($request->user('api'), 'create', Expense::class);

        //get warehouses assigned to user
        $user_auth = auth()->user();
        if ($user_auth->is_all_warehouses) {
            $warehouses = Warehouse::where('deleted_at', '=', null)->get(['id', 'name']);
        } else {
            $warehouses_id = UserWarehouse::where('user_id', $user_auth->id)->pluck('warehouse_id')->toArray();
            $warehouses = Warehouse::where('deleted_at', '=', null)->whereIn('id', $warehouses_id)->get(['id', 'name']);
        }

        $Expenses_category = ExpenseCategory::where('deleted_at', '=', null)->get(['id', 'name']);
        $societes = Societe::where('deleted_at', '=', null)->get(['id', 'name']);
        $chiffeurs = Chiffeur::where('deleted_at', '=', null)->select('id', 'firstname', 'lastname', DB::raw("CONCAT(`firstname`, ' ', `lastname`) as name"))->get();
        $sales = Sale::where('deleted_at', '=', null)->select('id', 'Ref')->get();
        $vehicules = Vehicule::where('deleted_at', '=', null)->select('id', 'matricule')->get();

        return response()->json([
            'Expenses_category' => $Expenses_category,
            'warehouses' => $warehouses,
            'societes' => $societes,
            'sales' => $sales,
            'chiffeurs' => $chiffeurs,
            'vehicules' => $vehicules,
        ]);
    }

    //------------- Show Form Edit Expense -----------\\

    public function edit(Request $request, $id)
    {

        $this->authorizeForUser($request->user('api'), 'update', Expense::class);
        $role = Auth::user()->roles()->first();
        $view_records = Role::findOrFail($role->id)->inRole('record_view');
        $Expense = Expense::where('deleted_at', '=', null)->findOrFail($id);

        // Check If User Has Permission view All Records
        if (!$view_records) {
            // Check If User->id === Expense->id
            $this->authorizeForUser($request->user('api'), 'check_record', $Expense);
        }

        if ($Expense->warehouse_id) {
            if (Warehouse::where('id', $Expense->warehouse_id)
                ->where('deleted_at', '=', null)
                ->first()
            ) {
                $data['warehouse_id'] = $Expense->warehouse_id;
            } else {
                $data['warehouse_id'] = '';
            }
        } else {
            $data['warehouse_id'] = '';
        }

        if ($Expense->expense_category_id) {
            if (ExpenseCategory::where('id', $Expense->expense_category_id)
                ->where('deleted_at', '=', null)
                ->first()
            ) {
                $data['category_id'] = $Expense->expense_category_id;
            } else {
                $data['category_id'] = '';
            }
        } else {
            $data['category_id'] = '';
        }

        $data['source'] = $Expense->source;
        $data['societe_id'] = $Expense->societe_id;
        $data['chiffeur_id'] = $Expense->chiffeur_id;
        $data['sale_id'] = $Expense->sale_id;
        $data['vehicule_id'] = (int)$Expense->vehicule_id;
        $data['date'] = $Expense->date;
        $data['amount'] = $Expense->amount;
        $data['facturation'] = $Expense->facturation == 1 ? true : false;
        $data['num_facture'] = $Expense->num_facture;
        $data['details'] = $Expense->details;

        //get warehouses assigned to user
        $user_auth = auth()->user();
        if ($user_auth->is_all_warehouses) {
            $warehouses = Warehouse::where('deleted_at', '=', null)->get(['id', 'name']);
        } else {
            $warehouses_id = UserWarehouse::where('user_id', $user_auth->id)->pluck('warehouse_id')->toArray();
            $warehouses = Warehouse::where('deleted_at', '=', null)->whereIn('id', $warehouses_id)->get(['id', 'name']);
        }

        $Expenses_category = ExpenseCategory::where('deleted_at', '=', null)->get(['id', 'name']);
        $societes = Societe::where('deleted_at', '=', null)->get(['id', 'name']);
        $chiffeurs = Chiffeur::where('deleted_at', '=', null)->select('id', 'firstname', 'lastname', DB::raw("CONCAT(`firstname`, ' ', `lastname`) as name"))->get();
        $sales = Sale::where('deleted_at', '=', null)->select('id', 'Ref')->get();
        $vehicules = Vehicule::where('deleted_at', '=', null)->select('id', 'matricule')->get();

        return response()->json([
            'expense' => $data,
            'expense_Category' => $Expenses_category,
            'warehouses' => $warehouses,
            'societes' => $societes,
            'chiffeurs' => $chiffeurs,
            'sales' => $sales,
            'vehicules' => $vehicules,
        ]);
    }
}
