<?php

namespace App\Modules\Staff\Http\Controllers;

use App\Facades\General;
use App\Models\Role;
use App\Modules\Staff\Http\Requests\Store;
use App\Modules\Staff\Model\Staff;
use App\Modules\Student\Model\ClassSection;
use App\Modules\Student\Model\Section;
use App\Modules\Student\Model\Student;
use App\Modules\Student\Model\StudentClass;
use App\Rules\MatchOldPassword;
use Exception;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\URL;
use Illuminate\View\View;
use Throwable;

class StaffController extends Controller
{

    /**
     * Module variable
     *
     * @var array
     */
    protected $moduleName;

    /**
     * Class Constructor.
     *
     * @return string
     */
    public function __construct()
    {
        $this->moduleName = $this->getModuleName();
    }

    /**
     * Display a listing of the resource.
     *
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function index(Request $request)
    {
        if ($request->ajax()) {
            return Staff::getStaffs();
        }

        General::userLog('SL000201', ['action_module' => $this->moduleName]);

        return View('staff::index', ['moduleName' => $this->moduleName]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {
        $departments    = General::getDataArray("Department");
        $designations   = General::getDataArray("Designation");
        $staff_roles    = Role::getStaffRoles();
        $genders        = General::getGender();
        $marital_status = General::getMaritalStatus();
        return View('staff::add_edit_form',
            compact('departments', 'staff_roles', 'designations', 'genders', 'marital_status'))->with('moduleName',
            $this->moduleName);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param Request $request
     * @return RedirectResponse
     */
    public function store(Store $request)
    {
        // Add student details into user table
        $user = Staff::addUpdateStaffUser($request);
        // Add student details into student table
        $staff = Staff::addUpdateStaff($request, $user);

        Session::flash('success', trans('locale.success_add_msg', array('module_name' => ucfirst($this->moduleName))));

        General::userLog('SL000302', [
            'action_module' => $this->moduleName,
            'parent_id'     => $staff->id,
            'event_data'    => ['name' => $user->name, 'url' => route($this->moduleName . '.edit', $staff->id)]
        ]);

        return redirect()->route($this->moduleName . '.index');
    }

    /**
     * Display the specified resource.
     *
     * @param Staff $staff
     * @return Factory|View
     */
    public function show($staff)
    {
        $staff = (new Staff())->findById($staff);

//        $staff = Staff::getStaffMoreDetails($staff);
        General::userLog('SL000304', [
            'action_module' => $this->moduleName,
            'parent_id'     => $staff->id,
            'event_data'    => ['name' => $staff->user->name, 'url' => route($this->moduleName . '.edit', $staff->id)]
        ]);

        return View('staff::show', compact('staff'))->with('moduleName', $this->moduleName);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param Staff $staff
     * @return Factory|View
     */
    public function edit($staff)
    {
        $staff          = (new Staff())->findById($staff);
        $departments    = General::getDataArray("Department");
        $designations   = General::getDataArray("Designation");
        $staff_roles    = Role::getStaffRoles();
        $genders        = General::getGender();
        $marital_status = General::getMaritalStatus();

        return View('staff::add_edit_form', compact('staff', 'departments', 'designations', 'staff_roles', 'genders',
            'marital_status'))->with('moduleName', $this->moduleName);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param Staff $staff
     * @return Factory|View
     */
    public function teacherProfile()
    {
        if (!General::isSchoolTeacher() && !General::isSchoolAdmin()) {
            Session::flash('error',
                "You don't have permission to access this module. Kindly contact administration.");
            return redirect('dashboard');
        }

        $staff          = (new Staff())->findById(Auth::user()->staff->id);
        $departments    = General::getDataArray("Department");
        $designations   = General::getDataArray("Designation");
        $staff_roles    = Role::getStaffRoles();
        $genders        = General::getGender();
        $marital_status = General::getMaritalStatus();

        return View('staff::add_edit_form', compact('staff', 'departments', 'designations', 'staff_roles', 'genders',
            'marital_status'))->with('moduleName', $this->moduleName)->with('isTeacherProfile', true);
    }

    /**
     * Update student profile
     *
     * @param Store $request
     * @param $staff
     * @return RedirectResponse|Redirector
     */
    public function updateTeacherProfile(Store $request, $staff)
    {
        // Add student details into user table
        $user = Staff::addUpdateStaffUser($request, true);
        // Add student details into student table
        $staff = Staff::addUpdateStaff($request, $user, $staff);

        Session::flash('success',
            trans('locale.success_update_msg', array('module_name' => ucfirst('Teacher profile'))));

        General::userLog('SL000303', [
            'action_module' => $this->moduleName,
            'parent_id'     => $staff->id,
            'event_data'    => ['name' => $staff->user->name, 'url' => route($this->moduleName . '.edit', $staff->id)]
        ]);

        return redirect(route('teacher.profile'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param Request $request
     * @param int $staff
     * @return RedirectResponse
     */
    public function update(Store $request, $staff)
    {

        // Add student details into user table
        $user = Staff::addUpdateStaffUser($request, true);
        // Add student details into student table
        $staff = Staff::addUpdateStaff($request, $user, $staff);

        Session::flash('success',
            trans('locale.success_update_msg', array('module_name' => ucfirst($this->moduleName))));
        General::userLog('SL000303', [
            'action_module' => $this->moduleName,
            'parent_id'     => $staff->id,
            'event_data'    => ['name' => $staff->user->name, 'url' => route($this->moduleName . '.edit', $staff->id)]
        ]);

        return redirect()->route($this->moduleName . '.index');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param Staff $staff
     * @return RedirectResponse
     * @throws Exception
     */
    public function destroy($staff)
    {
        $staff = (new Staff())->findById($staff);
        General::userLog('SL000305', [
            'action_module' => $this->moduleName,
            'parent_id'     => $staff->id,
            'event_data'    => ['name' => $staff->user->name]
        ]);

        Session::flash('success',
            trans('locale.success_delete_msg', array('module_name' => ucfirst($this->moduleName))));
        $staff->delete();

        return redirect()->route($this->moduleName . '.index');
    }

    /**
     * Display a listing of the resource.
     *
     * @param Request $request
     * @return false|Factory|View|string
     * @throws Throwable
     */
    public function import(Request $request)
    {
        if ($request->isMethod("post")) {

            $fileResponse = General::uploadImportFile($request, 'file', 'staff');
            if ($fileResponse == 'extension_not_match') {
                return json_encode(["success" => false, "message" => "Invalid File Extension."]);
            }

            if ($fileResponse == 'large_file_size') {
                return json_encode(["success" => false,
                                    "message" => "File too large. File must be less than 2MB."]);
            }

            $importDataArr = self::getDataFromImportedFile()['importDataArr'];
            $preview       = view('staff::preview', compact('importDataArr'))->render();

            return json_encode(["success" => true, "data" => $preview]);
        } else {
            return View('staff::import', ['moduleName' => $this->moduleName]);
        }
    }

    /**
     * Save imported file into storage
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function importSave(Request $request)
    {
        $importData    = self::getDataFromImportedFile();
        $importDataArr = $importData['importDataArr'];
        $totalData     = $importData['totalData'];
        $totalSaved    = 0;
        foreach ($importDataArr as $key => $data) {

            $staffModel = new Staff();
            $userModel  = new \App\Models\User();
            //Check if student exists?
            $userData = $userModel->find([
                "where" => [
//                    "name"  => $data['name'],
                    "email" => $data['email']
                ]
            ]);
            if ($userData && count($userData)) {
                $userModel = $userData->first();
            }

            //Save Section if not exists
            $sectionModel = new Section();
            $section      = $sectionModel->getSectionByTitle($data['division']);
            if (!$section) {
                $sectionModel->title      = trim($data['division']);
                $sectionModel->account_id = Config::get('account.id');
                $sectionModel->save();
                $section = $sectionModel->id;
            }

            //Save Class if not exists
            $classModel = new StudentClass();
            $class      = $classModel->getStudentClassByTitle($data['grade']);
            if (!$class) {
                $classModel->title      = trim($data['grade']);
                $classModel->account_id = Config::get('account.id');
                $classModel->save();
                $class = $classModel->id;
            }

            /*$classModel = (new StudentClass())->findById($class);
            $classModel->section()->sync([$section]);*/

            $userModel->name          = trim($data['name']);
            $userModel->email = trim($data['email']);
            $userModel->role_id       = Role::ROLE_TEACHER;
            $userModel->account_id    = Config::get('account.id');
            $userModel->password      = '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi'; // password
            $userModel->save();

            // check the existence of student by user id
            $staffData = $staffModel->find(["where" => ["user_id" => $userModel->id]]);
            if ($staffData && count($staffData)) {
                $staffModel = $staffData->first();
            }
            $staffModel->user_id    = $userModel->id;
            $staffModel->role       = Role::ROLE_TEACHER;
            $staffModel->account_id = Config::get('account.id');
            $staffModel->save();

            $input = [];
            $input['class_id']   = $class;
            $input['section_id'] = $section;
            $input['staff_id']   = $staffModel->id;
            $classTeacher = ClassSection::updateOrCreate([
                "class_id" => $request->$class,
                'section_id' => $request->$section
            ], $input);

            $totalSaved++;
        }

        $msg = "File imported successfully. Run imports over $totalData Teachers, out of which $totalSaved are saved.";
        return response()->json(['message' => $msg], 200);
    }

    /**
     * Return data from imported file
     *
     * @return array
     */
    public function getDataFromImportedFile()
    {
        $fileAccess = General::getImportedFileAccess('staff');

        // Import CSV to preview
        $filepath = storage_path($fileAccess['path'] . "/" . $fileAccess['filename']);
        // Reading file
        $file = fopen($filepath, "r");

        $importDataArr = [];
        $i             = 0;
        $totalData     = 0;
        while (($fileData = fgetcsv($file, 1000, ",")) !== false) {
            // Skip first row
            if ($i == 0) {
                $i++;
                continue;
            }
            if (!empty($fileData[0]) && $fileData[0] != null && !empty($fileData[1]) && $fileData[1] != null && !empty($fileData[2]) && $fileData[2] != null && !empty($fileData[3]) && $fileData[3] != null) {
                $importDataArr[$i]['name']     = $fileData[0];
                $importDataArr[$i]['grade']    = $fileData[1];
                $importDataArr[$i]['division'] = $fileData[2];
                $importDataArr[$i]['email']    = $fileData[3];

                $i++;
            }

            $totalData++;
        }
        fclose($file);

        return [
            'importDataArr' => $importDataArr,
            'totalData'     => $totalData
        ];
    }

    /**
     * Change the password of user
     *
     * @param Request $request
     * @return RedirectResponse|Redirector
     */
    public function changePassword(Request $request)
    {

        if ($request->isMethod("post")) {
            $request->validate([
                'current_password'     => ['required', new MatchOldPassword()],
                'new_password'         => ['required'],
                'new_confirm_password' => ['same:new_password'],
            ]);

            (new \App\Models\User())->findById(auth()->user()->id)->update(['password' => Hash::make($request->new_password)]);

            Session::flash('success', trans('locale.success_change_pass', array('module_name' => 'Password')));
            return redirect(route('staff.change-password'));
        }else{
            return View('staff::change_password')->with('moduleName', $this->moduleName);
        }
    }

    public function resetPassword(Request $request){
        if ($request->isMethod("post")) {
            $request->validate([
                'new_password'         => ['required'],
                'new_confirm_password' => ['same:new_password'],
            ]);

            $option = [];
            $option["where"] = [
                'account_id' => Config::get('account.id'),
                'email' => $request->email
            ];
            $result = (new \App\Models\User())->find($option)->first()->update(['password' => Hash::make($request->new_password)]);

            Session::flash('success', trans('locale.success_reset_pass', array('module_name' => 'Password')));
            return redirect(route('reset-password.index'));
        }else{
            $emailIds = \App\Models\User::getUserEmails();

            return View('staff::reset_password')->with('moduleName', $this->moduleName)->with('emailIds', $emailIds);
        }
    }

    /**
     * Get Module name.
     *
     * @return string
     */
    public function getModuleName()
    {
        return "staffs";
    }

}
