<?php

namespace App\Modules\HR\Core\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\HR\Core\Models\Shift;
use App\Modules\HR\Core\Models\ShiftDetail;
use App\Modules\PLATFORM\Settings\Models\Branch;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Yajra\DataTables\Facades\DataTables;

class ShiftController extends Controller
{
    public function index(Request $request)
    {
        if ($request->ajax()) {
            $query = Shift::with('branch');

            return DataTables::of($query)
                ->addIndexColumn()
                ->addColumn('branch', fn ($row) => $row->branch?->name ?? '-')
                ->editColumn('status', fn ($row) =>
                    $row->status
                        ? '<span class="badge bg-success">Active</span>'
                        : '<span class="badge bg-danger">Inactive</span>'
                )
                ->addColumn('action', fn ($row) =>
                    view('core::shifts/partials/actions', compact('row'))->render()
                )
                ->rawColumns(['status', 'action'])
                ->make(true);
        }

        return view('core::shifts/index');
    }

    public function create()
    {
        return view('core::shifts/create', [
            'branches' => Branch::where('status', true)->orderBy('name')->get(),
        ]);
    }

    public function store(Request $request)
    {
        $data = $this->validateShift($request);

        DB::transaction(function () use ($data) {

            $shift = Shift::create($data['shift']);

            $this->storeSlots($shift, $data['slots']);
        });

        return response()->json([
            'status' => true,
            'message' => 'Shift created successfully',
        ]);
    }

    public function edit(Shift $shift)
    {
        $shift->load('details');

        return view('core::shifts/edit', [
            'shift'    => $shift,
            'branches' => Branch::where('status', true)->orderBy('name')->get(),
        ]);
    }

    public function update(Request $request, Shift $shift)
    {
        $data = $this->validateShift($request);

        DB::transaction(function () use ($shift, $data) {

            $shift->update($data['shift']);

            $shift->details()->delete();

            $this->storeSlots($shift, $data['slots']);
        });

        return response()->json([
            'status' => true,
            'message' => 'Shift updated successfully',
        ]);
    }

    public function destroy(Shift $shift)
    {
        
        // Check if shift is being used by shift segment days
        $shiftSegmentDayCount = DB::table('shift_segment_days')
            ->where('shift_id', $shift->id)
            ->count();

        if ($shiftSegmentDayCount > 0) {
            return response()->json([
                'status' => false,
                'message' => 'Cannot delete this shift. It is currently being used by ' . $shiftSegmentDayCount . ' shift segment day(s).',
            ], 422);
        }

        $shift->delete();

        return response()->json([
            'status' => true,
            'message' => 'Shift deleted successfully',
        ]);
    }

    /* ================= INTERNAL HELPERS ================= */

    private function validateShift(Request $request): array
    {
        $this->normalizeTimeInputs($request);

        $validated = $request->validate([
            // Shift core
            'branch_id' => 'nullable|exists:branches,id',
            'code'      => 'required|string|max:50',
            'name'      => 'required|string|max:150',
            'color'     => 'nullable|string|max:20',

            'work_start_time' => 'required|date_format:H:i',
            'work_end_time'   => 'required|date_format:H:i|after:work_start_time',

            'late_grace_minutes'  => 'nullable|integer|min:0',
            'early_grace_minutes' => 'nullable|integer|min:0',

            'late_after_time'  => 'nullable|date_format:H:i',
            'early_before_time' => 'nullable|date_format:H:i',

            'half_day_after_time'          => 'nullable|date_format:H:i',
            'half_day_after_grace_minutes' => 'nullable|integer|min:0',
            'half_day_before_time'         => 'nullable|date_format:H:i',
            'half_day_before_grace_minutes'=> 'nullable|integer|min:0',

            'short_leave_minutes' => 'nullable|integer|min:0',

            'ot_start_after_time'  => 'nullable|date_format:H:i',
            'ot_minimum_minutes'   => 'nullable|integer|min:0',
            'ot_rounding_minutes'  => 'nullable|integer|in:0,15,30',

            'early_ot_before_time' => 'nullable|date_format:H:i',
            'early_ot_minimum_minutes' => 'nullable|integer|min:0',

            'absent_status' => 'required|string|max:5',
            'minimum_half_day_minutes' => 'required|integer|min:0',

            // Slots
            'slots' => 'required|array|min:1',
            'slots.*.start_time' => 'required|date_format:H:i',
            'slots.*.end_time'   => 'required|date_format:H:i',
            'slots.*.slot_type'  => 'required|string|max:20',
            'slots.*.paid' => 'required|boolean',
        ], [
            'branch_id.exists' => 'The selected branch is invalid.',
            'code.required' => 'Shift code is required.',
            'code.max' => 'Shift code must not exceed 50 characters.',
            'name.required' => 'Shift name is required.',
            'name.max' => 'Shift name must not exceed 150 characters.',
            'work_start_time.required' => 'Work start time is required.',
            'work_start_time.date_format' => 'Work start time must be in HH:MM format.',
            'work_end_time.required' => 'Work end time is required.',
            'work_end_time.date_format' => 'Work end time must be in HH:MM format.',
            'work_end_time.after' => 'Work end time must be after work start time.',
            'absent_status.required' => 'Absent status is required.',
            'minimum_half_day_minutes.required' => 'Minimum half day minutes is required.',
            'slots.required' => 'At least one time slot is required.',
            'slots.min' => 'At least one time slot is required.',
        ]);

        return [
            'shift' => [
                'branch_id' => $validated['branch_id'] ?? null,
                'code' => $validated['code'],
                'name' => $validated['name'],
                'color' => $validated['color'] ?? null,

                'work_start_time' => $validated['work_start_time'],
                'work_end_time'   => $validated['work_end_time'],

                'late_grace_minutes'  => $validated['late_grace_minutes'] ?? 0,
                'early_grace_minutes' => $validated['early_grace_minutes'] ?? 0,

                'late_after_time'  => $validated['late_after_time'] ?? null,
                'early_before_time' => $validated['early_before_time'] ?? null,

                'half_day_after_time'           => $validated['half_day_after_time'] ?? null,
                'half_day_after_grace_minutes'  => $validated['half_day_after_grace_minutes'] ?? 0,
                'half_day_before_time'          => $validated['half_day_before_time'] ?? null,
                'half_day_before_grace_minutes' => $validated['half_day_before_grace_minutes'] ?? 0,

                'short_leave_minutes' => $validated['short_leave_minutes'] ?? 0,

                'ot_start_after_time' => $validated['ot_start_after_time'] ?? null,
                'ot_minimum_minutes'  => $validated['ot_minimum_minutes'] ?? 0,
                'ot_rounding_minutes' => $validated['ot_rounding_minutes'] ?? 0,

                'early_ot_before_time' => $validated['early_ot_before_time'] ?? null,
                'early_ot_minimum_minutes' => $validated['early_ot_minimum_minutes'] ?? 0,

                'absent_status' => $validated['absent_status'],
                'minimum_half_day_minutes' => $validated['minimum_half_day_minutes'],
                'status' => true,
            ],
            'slots' => $this->normalizeSlots($validated['slots']),
        ];
    }


    private function normalizeTimeInputs(Request $request): void
    {
        $timeFields = [
            'work_start_time',
            'work_end_time',
            'late_after_time',
            'early_before_time',
            'half_day_after_time',
            'half_day_before_time',
            'ot_start_after_time',
            'early_ot_before_time',
        ];

        foreach ($timeFields as $field) {
            if ($request->filled($field)) {
                $request->merge([
                    $field => substr($request->input($field), 0, 5),
                ]);
            }
        }

        // Normalize slot times
        if ($request->slots && is_array($request->slots)) {
            $slots = $request->slots;

            foreach ($slots as $i => $slot) {
                if (!empty($slot['start_time'])) {
                    $slots[$i]['start_time'] = substr($slot['start_time'], 0, 5);
                }
                if (!empty($slot['end_time'])) {
                    $slots[$i]['end_time'] = substr($slot['end_time'], 0, 5);
                }
            }

            $request->merge(['slots' => $slots]);
        }
    }

    /**
     * 🔥 CRITICAL: Normalize slot order & fix user mistakes
     */
    private function normalizeSlots(array $slots): array
    {
        // Sort by start time
        usort($slots, fn ($a, $b) =>
            strtotime($a['start_time']) <=> strtotime($b['start_time'])
        );

        $clean = [];
        $lastEnd = null;

        foreach ($slots as $slot) {
            if ($lastEnd && strtotime($slot['start_time']) < strtotime($lastEnd)) {
                $slot['start_time'] = $lastEnd;
            }

            if (strtotime($slot['start_time']) >= strtotime($slot['end_time'])) {
                continue; // skip invalid
            }

            $clean[] = $slot;
            $lastEnd = $slot['end_time'];
        }

        return $clean;
    }

    private function storeSlots(Shift $shift, array $slots): void
    {
        foreach ($slots as $i => $slot) {
            $shift->details()->create([
                'start_time'     => $slot['start_time'],
                'end_time'       => $slot['end_time'],
                'slot_type'      => $slot['slot_type'],
                'paid'           => ($slot['paid'] ?? 1) > 0,
                'sort_order'     => $i,
                'status'         => true,
            ]);
        }
    }
}
