<?php

namespace Modules\SpecialAttendance\Http\Controllers;

use Carbon\Carbon;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Log;
use Brian2694\Toastr\Facades\Toastr;
use App\Models\Hrm\Department\Department;
use App\Models\Hrm\Attendance\DutySchedule;
use App\Helpers\CoreApp\Traits\ApiReturnFormatTrait;
use Modules\SpecialAttendance\Entities\DutyCalendar;
use Modules\SpecialAttendance\Http\Requests\DutyCalendarRequest;
use Modules\SpecialAttendance\Http\Repositories\DutyCalendarRepository;

class DutyCalendarController extends Controller
{
    use ApiReturnFormatTrait;

    public function index()
    {
        return view('specialattendance::index');
    }

    public function calendar(Request $request)
    {
        $data['class'] = 'calendar';
        $data['title'] = _trans('common.Calendar view');

        $employees = User::query()
            ->with(['lastDutyCalendar:id,employee_id,date'])
            ->select('id', 'name', 'employee_id', 'company_id', 'branch_id', 'department_id', 'designation_id')
            ->where(currentCompanyCurrentBranch())
            ->where('status_id', 1);

        if (!isAdminOrHr()) {
            $employees = $employees->whereIn('id', getRelatedUserIds());
        }

        $data['employees'] = $employees->get();

        $data['dutySchedules'] = DutySchedule::where(currentCompanyCurrentBranch())
            ->where('status_id', 1)
            ->get();

        $data['departments'] = Department::select('id', 'title')
            ->where('status_id', 1)
            ->whereHas('users')
            ->get();

        return view('specialattendance::dutySchedule.calendar', compact('data'));
    }

    public function calendarEvent(Request $request)
    {
        $employeeId = $request->input('employee_id');
        $month = $request->input('month');
        $year = $request->input('year');

        $mapData = [];
        if ($employeeId && $month && $year) {
            $monthNumber = Carbon::parse("1 $month")->month;
            $startDate = Carbon::createFromDate($year, $monthNumber, 1)->startOfMonth();
            $endDate = $startDate->copy()->endOfMonth();

            $dutyCalendars = DutyCalendar::with(['dutySchedule', 'dutySchedule', 'holiday', 'leave'])
                ->where('employee_id', $employeeId)
                ->whereBetween('date', [$startDate, $endDate])
                ->where(function ($query) {
                    $query->whereNotNull('duty_schedule_id')
                        ->orWhereNotNull('holiday_id')
                        ->orWhereNotNull('leave_id')
                        ->orWhere('is_weekend', 1);
                })->get();

            $mapData = $dutyCalendars->flatMap(function ($item) {
                $events = [];
                $baseEvent = [
                    'id' => $item->id,
                    'start' => $item->date,
                    'end' => $item->date,
                    'duty_schedule_id' => $item->duty_schedule_id,
                    'holiday_id' => $item->holiday_id,
                    'holiday_title' => $item->holiday->title ?? null,
                    'leave_id' => $item->leave_id,
                    'is_weekend' => $item->is_weekend,
                    'is_editable' => 1,
                ];

                if ($item->dutySchedule) {
                    $shiftName = $item->dutySchedule->name ?? null;
                    $startTime = Carbon::createFromFormat('H:i:s', $item->dutySchedule->start_time)->format('g:i A');
                    $endTime = Carbon::createFromFormat('H:i:s', $item->dutySchedule->end_time)->format('g:i A');
                    $events[] = array_merge($baseEvent, [
                        'title' => "$shiftName ($startTime - $endTime)",
                        'color' => '#0000FF',
                    ]);
                }

                if ($item->holiday) {
                    $events[] = array_merge($baseEvent, [
                        'title' => $item->holiday->title,
                        'color' => '#FF0000',
                    ]);
                }

                if ($item->leave) {
                    $events[] = array_merge($baseEvent, [
                        'title' => "Leave ({$item->leave->reason})",
                        'color' => '#FF6347',
                    ]);
                }

                if ($item->is_weekend) {
                    $events[] = array_merge($baseEvent, [
                        'title' => 'Weekend',
                        'color' => '#FFA500',
                    ]);
                }

                if ($item->is_take_meal) {
                    $events[] = array_merge($baseEvent, [
                        'title' => 'Meal',
                        'color' => '#229954',
                        'is_editable' => 0,
                    ]);
                }

                return $events;
            })->all();
        }

        return response()->json($mapData);
    }

    public function calendarStore(DutyCalendarRequest $request)
    {
        try {
            $departmentId = $request->department_id ?? null;
            $employeeId = $request->employee_id ?? null;

            if ($employeeId) {
                $user = User::find($employeeId);

                if (!$user->duty_schedule_id) {
                    Toastr::warning("$user->name duty schedule not found", 'Warning');
                    return redirect()->route('duty.calendar.index');
                }

                (new DutyCalendarRepository)->store($user, $request->date_range);
            } else {
                $users = User::where('department_id', $departmentId)
                    ->where('company_id', userCompanies())
                    ->where('branch_id', userBranch())
                    ->get();

                foreach ($users as $user) {
                    if (!$user->duty_schedule_id) {
                        Toastr::warning("$user->name duty schedule not found", 'Warning');
                        continue;
                    }

                    (new DutyCalendarRepository)->store($user, $request->date_range);
                }
            }

            Toastr::success('Created successfully', 'Success');

            return redirect()->route('duty.calendar.index');
        } catch (\Throwable $th) {
            Log::error($th->getMessage());
            return $this->responseWithError($th->getMessage(), [], 400);
        }
    }

    public function calendarUpdate(Request $request)
    {
        try {
            $dutyCalendarId = $request->duty_calendar_id;
            $dutyScheduleId = $request->make_weekend ? null : $request->duty_schedule_id ?? null;
            $holidayId = $request->holiday_id != '' ? $request->holiday_id : null;
            $isWeekend = $request->make_weekend ? 1 : $request->is_weekend ?? 0;

            if ($dutyScheduleId) {
                $holidayId = null;
                $isWeekend = 0;
            }

            $dutyCalendar = DutyCalendar::find($dutyCalendarId);
            if (! $dutyCalendar) {
                return $this->responseWithError('Not found', [], 404);
            }

            $dutyCalendar->duty_schedule_id = $dutyScheduleId;
            $dutyCalendar->holiday_id = $holidayId;
            $dutyCalendar->is_weekend = $isWeekend;
            $dutyCalendar->save();

            return $this->responseWithSuccess(_trans('message.Updated successfully.'), $dutyCalendar);
        } catch (\Throwable $th) {
            Log::error($th->getMessage());

            return $this->responseWithError($th->getMessage(), [], 400);
        }
    }
}
