<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Attendance;
use App\Models\Employee;
use App\Models\BusinessSetting;
use Carbon\Carbon;
use Yajra\DataTables\DataTables;
use Illuminate\Support\Facades\Auth;

class EmployeeDashboardController extends Controller
{
    public function index(Request $request)
    {
        // Determine which employee to show
        $employeeId = $this->getEmployeeId($request);
        
        if (!$employeeId) {
            return redirect()->route('dashboard')->with('error', 'No employee record found.');
        }

        $employee = Employee::findOrFail($employeeId);
        $employees = [];

        // If admin or manager, get authorized employees for selector
        if (Auth::user()->hasRole('Admin')) {
            $employees = Employee::orderBy('name')->get();
        } else {
            $userEmployee = Auth::user()->employee;
            if ($userEmployee) {
                $subordinates = $userEmployee->subordinates;
                if ($subordinates->count() > 0) {
                    $employees = Employee::whereIn('id', $subordinates->pluck('id')->push($userEmployee->id))
                        ->orderBy('name')
                        ->get();
                }
            }
        }

        return view('employee-dashboard.index', compact('employee', 'employees'));
    }

    public function getStats(Request $request)
    {
        $employeeId = $this->getEmployeeId($request);
        
        if (!$employeeId) {
            return response()->json(['error' => 'No employee found'], 404);
        }

        // Get date range
        $dateRange = $this->getDateRange($request);
        $startDate = $dateRange['start'];
        $endDate = $dateRange['end'];

        // Get business settings
        $settings = BusinessSetting::first();
        $standardPunchIn = $settings->standard_punch_in_time ?? '09:00:00';
        $minimumHours = (float) ($settings->minimum_working_hours ?? 8);

        // Get attendance records
        $attendances = Attendance::where('employee_id', $employeeId)
            ->whereBetween('date', [$startDate, $endDate])
            ->get();

        // Calculate statistics
        $totalPresents = $attendances->where('punch_out', '!=', null)->count();
        
        // Calculate working days (exclude weekends)
        $workingDays = 0;
        $current = Carbon::parse($startDate);
        $end = Carbon::parse($endDate);
        
        while ($current->lte($end)) {
            if (!$current->isWeekend()) {
                $workingDays++;
            }
            $current->addDay();
        }

        $totalAbsents = $workingDays - $totalPresents;

        // Calculate late entries
        $lateEntries = 0;
        $lowAttendance = 0;

        foreach ($attendances as $attendance) {
            if ($attendance->punch_in) {
                // Check late entry
                $standardTime = Carbon::parse($attendance->date . ' ' . $standardPunchIn);
                $actualPunchIn = Carbon::parse($attendance->punch_in);
                
                if ($actualPunchIn->gt($standardTime)) {
                    $lateEntries++;
                }

                // Check low attendance
                if ($attendance->punch_out) {
                    $workedHours = $actualPunchIn->diffInHours(Carbon::parse($attendance->punch_out), true);
                    if ($workedHours < $minimumHours) {
                        $lowAttendance++;
                    }
                }
            }
        }

        return response()->json([
            'total_presents' => $totalPresents,
            'total_absents' => max(0, $totalAbsents),
            'late_entries' => $lateEntries,
            'low_attendance' => $lowAttendance,
            'working_days' => $workingDays,
            'date_range' => [
                'start' => $startDate,
                'end' => $endDate
            ]
        ]);
    }

    public function getAttendanceData(Request $request)
    {
        $employeeId = $this->getEmployeeId($request);
        
        if (!$employeeId) {
            return response()->json(['error' => 'No employee found'], 404);
        }

        $dateRange = $this->getDateRange($request);
        $settings = BusinessSetting::first();
        $standardPunchIn = $settings->standard_punch_in_time ?? '09:00:00';
        $minimumHours = (float) ($settings->minimum_working_hours ?? 8);

        $query = Attendance::where('employee_id', $employeeId)
            ->whereBetween('date', [$dateRange['start'], $dateRange['end']])
            ->orderBy('date', 'desc');

        return DataTables::of($query)
            ->addColumn('punch_in_time', function ($attendance) {
                return $attendance->punch_in ? Carbon::parse($attendance->punch_in)->format('h:i A') : '-';
            })
            ->addColumn('punch_out_time', function ($attendance) {
                return $attendance->punch_out ? Carbon::parse($attendance->punch_out)->format('h:i A') : '-';
            })
            ->addColumn('worked_hours', function ($attendance) {
                if ($attendance->punch_in && $attendance->punch_out) {
                    $hours = Carbon::parse($attendance->punch_in)->diffInHours(Carbon::parse($attendance->punch_out), true);
                    return number_format($hours, 2) . ' hrs';
                }
                return '-';
            })
            ->addColumn('status', function ($attendance) use ($standardPunchIn, $minimumHours) {
                $badges = [];
                
                if ($attendance->punch_in && $attendance->punch_out) {
                    $badges[] = '<span class="badge bg-success">Present</span>';
                    
                    // Check late
                    $standardTime = Carbon::parse($attendance->date . ' ' . $standardPunchIn);
                    $actualPunchIn = Carbon::parse($attendance->punch_in);
                    if ($actualPunchIn->gt($standardTime)) {
                        $minutes = $actualPunchIn->diffInMinutes($standardTime);
                        $badges[] = '<span class="badge bg-warning">Late (' . $minutes . ' min)</span>';
                    }
                    
                    // Check low hours
                    $workedHours = $actualPunchIn->diffInHours(Carbon::parse($attendance->punch_out), true);
                    if ($workedHours < $minimumHours) {
                        $badges[] = '<span class="badge bg-danger">Low Hours</span>';
                    }
                } else {
                    $badges[] = '<span class="badge bg-secondary">Incomplete</span>';
                }
                
                return implode(' ', $badges);
            })
            ->editColumn('date', function ($attendance) {
                return Carbon::parse($attendance->date)->format('d M Y');
            })
            ->rawColumns(['status'])
            ->make(true);
    }

    private function getEmployeeId(Request $request)
    {
        $user = Auth::user();

        // If no specific employee requested, return self
        if (!$request->employee_id) {
            return $user->employee_id;
        }

        // Admin can view any employee
        if ($user->hasRole('Admin')) {
            return $request->employee_id;
        }

        // Manager check: can view subordinate
        if ($user->employee) {
            $isSubordinate = $user->employee->subordinates()->where('id', $request->employee_id)->exists();
            if ($isSubordinate) {
                return $request->employee_id;
            }
        }

        // Default to self for unauthorized requests
        return $user->employee_id;
    }

    private function getDateRange(Request $request)
    {
        if ($request->start_date && $request->end_date) {
            return [
                'start' => $request->start_date,
                'end' => $request->end_date
            ];
        }

        // Default to current month
        $month = $request->month ?? now()->month;
        $year = $request->year ?? now()->year;

        return [
            'start' => Carbon::create($year, $month, 1)->startOfMonth()->toDateString(),
            'end' => Carbon::create($year, $month, 1)->endOfMonth()->toDateString()
        ];
    }
}
