<?php

namespace App\Http\Controllers\HumanResource;

use App\Http\Controllers\Controller;
use App\Imports\EmployeeImport;
use App\Models\Account;
use App\Models\AccountAddress;
use App\Models\AccountAttachment;
use App\Models\AccountContact;
use App\Models\AccountImage;
use App\Models\AccountingGroup;
use App\Models\AccountSettlementType;
use App\Models\AccountTitle;
use App\Models\CompanyAddress;
use App\Models\Country;
use App\Models\Designation;
use App\Models\Employee;
use App\Models\EmployeeType;
use App\Models\Gender;
use App\Models\Language;
use App\Models\MaritalStatus;
use App\Models\MasterCategory;
use App\Models\MasterType;
use App\Models\OrganizationDepartment;
use App\Models\ProjectTeam;
use App\Models\Scopes\GlobalStatusScope;
use App\Models\TaxRegisterCategory;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Maatwebsite\Excel\Facades\Excel;

class EmployeesController extends Controller
{
    function __construct()
    {
        $this->middleware('permission:employee-list', ['only' => ['index']]);
    }
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        // Selecting fields and loading relationships
        $data = Employee::select([
            'id',
            'account_id',
            'employee_type_id',
            'designation_id',
            'department_id',
            'gender_id',
            'reporting_to',
            'language_id',
            'title_id',
            'name',
            'email',
            'date_of_birth',
            'joining_date',
            'phone_no',
            'role_in_project_id',
            'address',
            'about',
            'skills',
            'probation_end_date',
            'notice_period_start_date',
            'notice_period_end_date',
            'marital_status_id',
            'login_allowed',
            'recieve_email_notifications',
            'hourly_rate',
            'slack_member_id',
            'country_id',
            'state_id',
            'city_id',
        ])
        ->with('getDesignation')
        ->with('getDepartment')
        ->with('getGender')
        ->with('getUser')
        ->with('getTitle')
        ->with('getLanguage')
        ->with('getRole')
        ->with('getCity')
        ->with('getAccount');

        // Handling AJAX request
        if ($request->ajax()) {
            $sort_by      = $request->get('sortby') ?? 10;
            $sort_type    = $request->get('sorttype');
            $search_query = $request->get('query');

            // Applying filtering based on search query
            $data = $data->when(!empty($search_query), function ($query) use ($search_query) {
                return $query->where('date_of_birth', 'LIKE', '%' . $search_query . '%')
                    ->orWhere('email', 'LIKE', '%' . $search_query . '%')
                    ->orWhere('phone_no', 'LIKE', '%' . $search_query . '%')
                    ->orWhereHas('getAccount', function ($query) use ($search_query) {
                        $query->where('accounts.name', 'LIKE', '%' . $search_query . '%');
                    })
                    ->orWhereHas('getCity', function ($query) use ($search_query) {
                        $query->where('cities.name', 'LIKE', '%' . $search_query . '%');
                    })
                    ->orWhereHas('getGender', function ($query) use ($search_query) {
                        $query->where('genders.name', 'LIKE', '%' . $search_query . '%');
                    })
                    ->orWhereHas('getDesignation', function ($query) use ($search_query) {
                        $query->where('designations.name', 'LIKE', '%' . $search_query . '%');
                    });
            });

            // Paginating the result
            $data = $data->paginate($sort_by);

            return view('employees.table', compact('data'));
        }
        else
        {
            // Default pagination when no AJAX request
            $data = $data->paginate(10);

            return view('employees.index', compact('data'));
        }
    }


    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $title           = AccountTitle::select(['id','name','value'])->where('status', '1')->get();
        $designation     = Designation::select('id','name')->where('status', '1')->get();
        $department      = OrganizationDepartment::select('id','name')->where('status', '1')->get();
        $gender          = Gender::select('id','name')->get();
        $reportTo        = User::select('id','name')->where('status', '1')->get();
        $language        = Language::select('id','name')->get();
        $country         = Country::select(['id','name'])->get();
        $maritalStatus   = MaritalStatus::select(['id','name'])->get();
        $employeeType    = EmployeeType::select(['id','name'])->where('status', '1')->get();
        $company_address = \Session::get('company_data');
        $countryCode     = $country_code['country_code'] ?? 'us';
        $ProjectTeam     = ProjectTeam::select('id','role_in_project')->get();

       return view('employees.create',compact('reportTo','department','designation','language','gender','title','country','maritalStatus','company_address','countryCode','employeeType','ProjectTeam'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $rules = [
            'date_of_birth'  => 'required',
            'joining_date'   => 'required',
            'designation_id' => 'required',
            'department_id'  => 'required',
            'gender_id'      => 'required',
            'reporting_to'   => 'required',
            'phone_no'       => 'required|unique:account_contacts,phone_no,'.$request->name.',name',
            'name'           => 'required|unique:account_contacts,name,'.$request->phone_no.',phone_no',
        ];
        $validator = \Validator::make($request->all(), $rules, [
            'unique' => 'This Name and Phone No are already taken.',
        ]);

        if ($validator->fails()) {
            if ($request->ajax()) {
                return response()->json([
                    'success' => false,
                    'message' => $validator->getMessageBag()->first(),
                    'data'    => []
                ]);
            }
            return redirect()->back()->with('error', $validator->getMessageBag()->first());
        }

        $data = $request->except([
            '_token',
            '_method',
            'date_of_birth',
            'joining_date',
            'probation_end_date',
            'notice_period_start_date',
            'notice_period_end_date',
        ]);

        $data['date_of_birth']            = $request->date_of_birth            != '' && $request->date_of_birth            != '0000-00-00' &&  $request->date_of_birth            != Null ? date('Y-m-d', strtotime($request->date_of_birth)) : null;
        $data['joining_date']             = $request->joining_date             != '' && $request->joining_date             != '0000-00-00' &&  $request->joining_date             != Null ? date('Y-m-d', strtotime($request->joining_date)) : null;
        $data['probation_end_date']       = $request->probation_end_date       != '' && $request->probation_end_date       != '0000-00-00' &&  $request->probation_end_date       != Null ? date('Y-m-d', strtotime($request->probation_end_date)) : null;
        $data['notice_period_start_date'] = $request->notice_period_start_date != '' && $request->notice_period_start_date != '0000-00-00' &&  $request->notice_period_start_date != Null ? date('Y-m-d', strtotime($request->notice_period_start_date)) : null;
        $data['notice_period_end_date']   = $request->notice_period_end_date   != '' && $request->notice_period_end_date   != '0000-00-00' &&  $request->notice_period_end_date   != Null ? date('Y-m-d', strtotime($request->notice_period_end_date)) : null;

        $account_type = MasterType::where('type_code', 'Employee')->first();
        $employee     = Employee::create($data);

        $account_type           = MasterType::where('id', $account_type->id)->first();
        $company_id             = Auth::user()->company_id ?? '';
        $accounting_category    = MasterCategory::select('id','category_name')->where('is_default',1)->first();
        $tax_register_cagtegory = TaxRegisterCategory::select('id','name')->where('is_default',1)->first();
        $settlementType         = AccountSettlementType::select('id','name')->where('is_default',1)->first();
        $accounting_group       = AccountingGroup::where('code','SUNDRY_DEBTORS')->first();


        $account = Account::create([
            'name'                     => $request->name,
            'account_title_id'         => $request->title_id,
            'account_type_id'          => $account_type->id,
            'company_id'               => $company_id,
            'account_category_id'      => $accounting_category->id,
            'tax_register_category_id' => $tax_register_cagtegory->id,
            'settlement_type'          => $settlementType->id,
            'accounting_group_id'      => $accounting_group->id,
        ]);
        $account_type = MasterType::where('type_code','EMPLOYEE')->first();
        $count        = 1;
        $prefix       = "CUS";

        if($account_type) {
            $count  = $account_type->count != '' ? $account_type->count + 1 : 1;
            $prefix = $account_type->prefix != '' ? $account_type->prefix : "CUS";

            $account_type->update(['count' => $count]);
        }

        $code = $this->generateCode($count, $prefix);

        $account->update(['code' => $code]);

        $account_id = $account->id;

        $employee->update(['account_id' => $account_id]);

        $accountAddress = AccountAddress::insert([
           'account_id'      => $account->id,
           'address_type_id' => $account_type->id,
           'address_line1'   => $request->address,
           'country_id'      => $request->country_id,
           'state_id'        => $request->state_id,
           'city_id'         => $request->city_id,
        ]);

        $accountContact = AccountContact::create([
            'account_id'     => $account->id,
            'name'           => $request->name,
            'account_id'     => $account->id,
            'email'          => $request->email,
            'address'        => $request->address,
            'phone_no'       => $request->phone_no,
            'date_of_birth'  => $request->date_of_birth,
            'marital_status' => $request->marital_status,
            'country_id'     => $request->country_id,
            'state_id'       => $request->state_id,
            'city_id'        => $request->city_id,

        ]);

        if ($request->ajax()) {
            return response()->json([
                'success' => true,
                'message' => 'Employee has been created successfully',
            ]);
        }
        return redirect()->back()
            ->with('success','Employee has been created successfully.');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $data            = Employee::find($id);
        $account         = Account::where('id',$data->account_id)->with('first_account_address','account_contact')->first();
        $title           = AccountTitle::select(['id','name','value'])->where('status', '1')->get();
        $designation     = Designation::select('id','name')->get();
        $department      = OrganizationDepartment::select('id','name')->get();
        $gender          = Gender::select('id','name')->get();
        $reportTo        = User::select('id','name')->get();
        $language        = Language::select('id','name')->get();
        $country         = Country::select(['id','name'])->where('status', '1')->get();
        $maritalStatus   = MaritalStatus::select(['id','name'])->get();
        $employeeType    = EmployeeType::select('id','name')->get();
        $company_address = \Session::get('company_data')['companies_addresses'];
        $countryCode     = $country_code->country_code ?? 'us';

       return view('employees.edit',compact('reportTo','department','designation','language','gender','title','country','maritalStatus','company_address','countryCode','employeeType','data','account'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */

    public function update(Request $request, $id)
    {
        $rules = [
            'date_of_birth'  => 'required',
            'joining_date'   => 'required',
            'designation_id' => 'required',
            'department_id'  => 'required',
            'gender_id'      => 'required',
            'reporting_to'   => 'required',
            'phone_no'       => 'required',
            'name'           => 'required',
            'country_id'     => 'required',
            'state_id'       => 'required',
            'city_id'        => 'required',
        ];

        $validator = \Validator::make($request->all(), $rules, [
            'unique' => 'This Name and Phone No are already taken.',
        ]);

        if ($validator->fails()) {
            if ($request->ajax()) {
                return response()->json([
                    'success' => false,
                    'message' => $validator->getMessageBag()->first(),
                    'data'    => []
                ]);
            }
            return redirect()->back()->with('error', $validator->getMessageBag()->first());
        }

        $data = $request->except([
            '_token',
            '_method',
            'date_of_birth',
            'joining_date',
            'probation_end_date',
            'notice_period_start_date',
            'notice_period_end_date',
        ]);

        // Add the following lines to convert date strings to proper format
        $data['date_of_birth']            = $request->date_of_birth            != '' && $request->date_of_birth            != '0000-00-00' &&  $request->date_of_birth            != Null ? date('Y-m-d', strtotime($request->date_of_birth)) : null;
        $data['joining_date']             = $request->joining_date             != '' && $request->joining_date             != '0000-00-00' &&  $request->joining_date             != Null ? date('Y-m-d', strtotime($request->joining_date)) : null;
        $data['probation_end_date']       = $request->probation_end_date       != '' && $request->probation_end_date       != '0000-00-00' &&  $request->probation_end_date       != Null ? date('Y-m-d', strtotime($request->probation_end_date)) : null;
        $data['notice_period_start_date'] = $request->notice_period_start_date != '' && $request->notice_period_start_date != '0000-00-00' &&  $request->notice_period_start_date != Null ? date('Y-m-d', strtotime($request->notice_period_start_date)) : null;
        $data['notice_period_end_date']   = $request->notice_period_end_date   != '' && $request->notice_period_end_date   != '0000-00-00' &&  $request->notice_period_end_date   != Null ? date('Y-m-d', strtotime($request->notice_period_end_date)) : null;

        // Update Employee model
        $employee = Employee::findOrFail($id);
        $employee->update($data);

        // Update Account model
        $account = Account::findOrFail($employee->account_id);
        $account->update([
            'name'             => $request->name,
            'account_title_id' => $request->title_id,
        ]);

        // Update AccountAddress model
        $accountAddress = AccountAddress::where('account_id', $account->id)->first();
        $accountAddress->update([
            'address_type_id' => $account->account_type_id,
            'address_line1'   => $request->address,
            'country_id'      => $request->country_id,
            'state_id'        => $request->state_id,
            'city_id'         => $request->city_id,
        ]);

        // Update AccountContact model
        $accountContact = AccountContact::where('account_id', $account->id)->first();
        $accountContact->update([
            'name'           => $request->name,
            'email'          => $request->email,
            'address'        => $request->address,
            'phone_no'       => $request->phone_no,
            'date_of_birth'  => $request->date_of_birth,
            'marital_status' => $request->marital_status,
            'country_id'     => $request->country_id,
            'state_id'       => $request->state_id,
            'city_id'        => $request->city_id,
        ]);

        if ($request->ajax()) {
            return response()->json([
                'success' => true,
                'message' => 'Employee has been updated successfully',
            ]);
        }

        return redirect()->back()
            ->with('success','Employee has been updated successfully.');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Request $request)
    {
        $employee = Employee::find($request->id);

        if ($employee) {
            $accountId = $employee->account_id;

            // Delete employee
            $employee->delete();

            // Delete related account
            if ($accountId) {
                $account = Account::find($accountId);

                if ($account) {
                    // Delete related images
                    AccountImage::where('account_id', $accountId)->delete();

                    // Delete related attachments
                    AccountAttachment::where('account_id', $accountId)->delete();

                    // Delete related contacts
                    AccountContact::where('account_id', $accountId)->delete();

                    // Delete related addresses
                    AccountAddress::where('account_id', $accountId)->delete();

                    // Delete the account
                    $account->delete();
                }
            }

            return response()->json([
                'success' => true,
                'message' => ['Deleted successfully'],
                'data'    => [
                    'redirect' => 'employee',
                ],
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => ['Employee not found'],
                'data'    => [],
            ]);
        }
    }

    public function employeeImportCreate(Request $request)
    {
        return view('employees.import');
    }
    public function employeeImport(Request $request)
    {
        $data = \Session::get('employee_import') ?? [];

        $data['successImport'] = 0;
        $data['errorImport']   = 0;

        \Session::put('employee_import', $data);

        $collection = Excel::import(new EmployeeImport($request), $request->file('employee_import'));
        $data       = \Session::get('employee_import') ?? [];

        $message = 'File uploaded successfully. ' . $data['successImport'] . ' New Records added, ' . $data['errorImport'] . ' Records already exist.';

        return Redirect::route('employee.index')->with('success', $message);
    }
}
