<?php
// Forced lint check

namespace App\Http\Controllers;

use App\Models\Attendance;
use App\Models\Staff;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use App\Http\Controllers\Concerns\ResolvesTenantHotel;
use Illuminate\Validation\Rule;

class AttendanceController extends Controller
{
    use ResolvesTenantHotel;

    private function getHotelId()
    {
        return $this->tenantHotelIdOrAbort();
    }

    /**
     * Display attendance recording page
     */
    public function record()
    {
        try {
            $hotelId = $this->getHotelId();
            // Get active staff members
            $staff = Staff::where('hotel_id', $hotelId)->where('status', 'active')
                ->orderBy('first_name')
                ->orderBy('last_name')
                ->get();
            
            // Get today's date
            $today = Carbon::today()->format('Y-m-d');
            
            // TEMPORARY FIX: Use try-catch to handle table not found
            $todayAttendance = collect(); // Default to empty collection
            
            try {
                // Check if table exists before querying
                if (Schema::hasTable('attendances')) {
                    $todayAttendance = Attendance::with('staff')
                        ->where('hotel_id', $hotelId)
                        ->where('date', $today)
                        ->get()
                        ->keyBy('staff_id');
                }
            } catch (\Exception $e) {
                // If there's an error, just use empty collection
                $todayAttendance = collect();
            }
            
            return view('attendance.record', compact('staff', 'today', 'todayAttendance'));
            
        } catch (\Exception $e) {
            // If everything fails, show a simple error page
            return response("Attendance system is being set up. Please try again in a moment. Error: " . $e->getMessage());
        }
    }
    
    /**
     * Store single attendance record
     */
    public function store(Request $request)
    {
        $hotelId = $this->getHotelId();
        $request->validate([
            'staff_id' => [
                'required',
                Rule::exists('staff', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'date' => 'required|date',
            'clock_in' => 'nullable|date_format:H:i',
            'clock_out' => 'nullable|date_format:H:i',
            'status' => 'required|in:present,absent,late,half_day,on_leave,off_duty'
        ]);
        
        try {
            // Check if table exists
            if (!Schema::hasTable('attendances')) {
                return redirect()->back()
                    ->with('error', 'Attendance table is not ready yet. Please try again.')
                    ->withInput();
            }
            
            // Check if clock_out is after clock_in if both are provided
            if ($request->clock_in && $request->clock_out && $request->clock_out <= $request->clock_in) {
                return redirect()->back()
                    ->with('error', 'Clock out time must be after clock in time.')
                    ->withInput();
            }
            
            $attendance = Attendance::updateOrCreate(
                [
                    'staff_id' => $request->staff_id,
                    'date' => $request->date,
                    'hotel_id' => $hotelId,
                ],
                [
                    'clock_in_time' => $request->clock_in ?: null,
                    'clock_out_time' => $request->clock_out ?: null,
                    'status' => $request->status,
                    'notes' => $request->notes,
                ]
            );
            
            return redirect()->route('attendance.record')
                ->with('success', 'Attendance recorded successfully!');
                
        } catch (\Exception $e) {
            return redirect()->back()
                ->with('error', 'Error recording attendance: ' . $e->getMessage())
                ->withInput();
        }
    }
    
    /**
     * Store bulk attendance records
     */
    public function bulkStore(Request $request)
    {
        $request->validate([
            'date' => 'required|date',
            'attendance' => 'required|array',
            'attendance.*.status' => 'nullable|in:present,absent,late,half_day,on_leave,off_duty',
            'attendance.*.clock_in' => 'nullable|date_format:H:i',
            'attendance.*.clock_out' => 'nullable|date_format:H:i',
        ]);
        
        try {
            $date = $request->date;
            $attendanceData = $request->attendance;
            $recordedCount = 0;
            
            foreach ($attendanceData as $staffId => $data) {
                if (!empty($data['status'])) {
                    $hotelId = $this->getHotelId();
                    
                    Attendance::updateOrCreate(
                        [
                            'staff_id' => $staffId,
                            'date' => $date,
                            'hotel_id' => $hotelId,
                        ],
                        [
                            'clock_in_time' => $data['clock_in'] ?: null,
                            'clock_out_time' => $data['clock_out'] ?: null,
                            'status' => $data['status'],
                        ]
                    );
                    $recordedCount++;
                }
            }
            
            return redirect()->route('attendance.record')
                ->with('success', "Successfully recorded attendance for {$recordedCount} staff members!");
                
        } catch (\Exception $e) {
            return redirect()->back()
                ->with('error', 'Error recording bulk attendance: ' . $e->getMessage())
                ->withInput();
        }
    }
    
    /**
     * Display attendance report
     */
    public function report(Request $request)
    {
        $hotelId = $this->getHotelId();
        // Set default date range (last 30 days)
        $from = $request->get('from', Carbon::now()->subDays(30)->format('Y-m-d'));
        $to = $request->get('to', Carbon::now()->format('Y-m-d'));
        
        // Get staff for filter dropdown
        $staffList = Staff::where('hotel_id', $hotelId)->where('status', 'active')
            ->orderBy('first_name')
            ->get();
        
        // Build query for attendance records
        $query = Attendance::with('staff')
            ->where('hotel_id', $hotelId)
            ->whereBetween('date', [$from, $to])
            ->orderBy('date', 'desc')
            ->orderBy('created_at', 'desc');
        
        // Apply staff filter if selected
        if ($request->has('staff_id') && $request->staff_id) {
            $query->where('staff_id', $request->staff_id);
        }
        
        // Apply status filter if selected
        if ($request->has('status') && $request->status) {
            $query->where('status', $request->status);
        }
        
        $attendance = $query->paginate(50);
        
        // Calculate summary statistics
        $summary = [
            'total_days' => $attendance->count(),
            'present' => $attendance->where('status', 'present')->count(),
            'absent' => $attendance->where('status', 'absent')->count(),
            'late' => $attendance->where('status', 'late')->count(),
            'half_day' => $attendance->where('status', 'half_day')->count(),
            'on_leave' => $attendance->where('status', 'on_leave')->count(),
            'off_duty' => $attendance->where('status', 'off_duty')->count(),
        ];
        
        // Calculate overall stats
        $overallStats = $this->calculateOverallStats($from, $to, $hotelId);
        
        // Calculate attendance summary
        $attendanceSummary = $this->calculateAttendanceSummary($from, $to);
        
        // Calculate monthly trend
        $monthlyTrend = $this->calculateMonthlyTrend($from, $to, $hotelId);
        
        // Get all staff for the report table with their relationships
        $staff = Staff::with(['department', 'position'])
            ->where('hotel_id', $hotelId)
            ->where('status', 'active')
            ->orderBy('first_name')
            ->orderBy('last_name')
            ->get();
        
        // Calculate staff attendance statistics (for the table your view expects)
        $staffAttendance = $this->calculateStaffAttendanceStats($staff, $from, $to);
        
        // Get attendance data grouped by staff
        $attendanceData = Attendance::where('hotel_id', $hotelId)->whereBetween('date', [$from, $to])
            ->get()
            ->groupBy('staff_id');
        
        // Convert dates to Carbon for the view
        $startDate = Carbon::parse($from);
        $endDate = Carbon::parse($to);
        
        // Pass both staff models and calculated stats to view
        // The view needs to use the correct variable name
        return view('attendance.report', compact(
            'staff',           // Original Staff models collection
            'staffAttendance', // Calculated stats (array collection)
            'attendanceData',
            'overallStats',
            'attendanceSummary',
            'monthlyTrend',
            'startDate',
            'endDate',
            'attendance',
            'summary',
            'staffList',
            'from',
            'to'
        ));
    }
    
    /**
     * Calculate overall attendance statistics
     */
    private function calculateOverallStats($from, $to, $hotelId)
    {
        $totalStaff = Staff::where('hotel_id', $hotelId)->where('status', 'active')->count();
        $startDate = Carbon::parse($from);
        $endDate = Carbon::parse($to);
        
        // Calculate working days (excluding weekends)
        $workingDays = 0;
        $currentDate = $startDate->copy();
        while ($currentDate->lte($endDate)) {
            if (!$currentDate->isWeekend()) {
                $workingDays++;
            }
            $currentDate->addDay();
        }
        
        // Get total possible attendance days
        $totalPossibleAttendance = $totalStaff * $workingDays;
        
        // Get actual attendance
        $actualAttendance = Attendance::whereBetween('date', [$from, $to])
            ->where('hotel_id', $hotelId)
            ->whereIn('status', ['present', 'late', 'half_day'])
            ->count();
        
        // Calculate perfect attendance count
        $perfectAttendanceCount = 0;
        $staffList = Staff::where('hotel_id', $hotelId)->where('status', 'active')->get();
        
        foreach ($staffList as $staff) {
            $staffAttendanceCount = Attendance::where('staff_id', $staff->id)
                ->where('hotel_id', $hotelId)
                ->whereBetween('date', [$from, $to])
                ->whereIn('status', ['present', 'late', 'half_day'])
                ->count();
            
            if ($staffAttendanceCount == $workingDays) {
                $perfectAttendanceCount++;
            }
        }
        
        $averageAttendanceRate = $totalPossibleAttendance > 0 ? 
            ($actualAttendance / $totalPossibleAttendance) * 100 : 0;
        
        return [
            'total_staff' => $totalStaff,
            'working_days' => $workingDays,
            'total_possible_attendance' => $totalPossibleAttendance,
            'actual_attendance' => $actualAttendance,
            'average_attendance_rate' => round($averageAttendanceRate, 2),
            'perfect_attendance_count' => $perfectAttendanceCount,
        ];
    }
    
    /**
     * Calculate attendance summary
     */
    private function calculateAttendanceSummary($from, $to)
    {
        $startDate = Carbon::parse($from);
        $endDate = Carbon::parse($to);
        
        $totalDays = $startDate->diffInDays($endDate) + 1;
        
        // Calculate working days (excluding weekends)
        $workingDays = 0;
        $weekends = 0;
        $currentDate = $startDate->copy();
        
        while ($currentDate->lte($endDate)) {
            if ($currentDate->isWeekend()) {
                $weekends++;
            } else {
                $workingDays++;
            }
            $currentDate->addDay();
        }
        
        // Note: You would need a holidays table for actual holidays
        $holidays = 0;
        
        return [
            'total_days' => $totalDays,
            'working_days' => $workingDays,
            'weekends' => $weekends,
            'holidays' => $holidays,
        ];
    }
    
    /**
     * Calculate monthly trend
     */
    private function calculateMonthlyTrend($from, $to, $hotelId)
    {
        $startDate = Carbon::parse($from)->startOfMonth();
        $endDate = Carbon::parse($to)->endOfMonth();
        
        $months = [];
        $currentMonth = $startDate->copy();
        
        while ($currentMonth->lte($endDate)) {
            $monthStart = $currentMonth->copy()->startOfMonth();
            $monthEnd = $currentMonth->copy()->endOfMonth();
            
            // Get attendance for this month
            $monthAttendance = Attendance::where('hotel_id', $hotelId)
                ->whereBetween('date', [$monthStart, $monthEnd])
                ->get();
            
            $presentCount = $monthAttendance->whereIn('status', ['present', 'late'])->count();
            $totalCount = $monthAttendance->count();
            
            $attendanceRate = $totalCount > 0 ? ($presentCount / $totalCount) * 100 : 0;
            
            $months[] = [
                'month' => $currentMonth->format('M Y'),
                'attendance_rate' => round($attendanceRate, 2),
                'present_count' => $presentCount,
                'total_count' => $totalCount,
            ];
            
            $currentMonth->addMonth();
        }
        
        return $months;
    }
    
    /**
     * Calculate staff attendance statistics for the table
     */
    private function calculateStaffAttendanceStats($staff, $from, $to)
    {
        $staffAttendance = [];
        
        foreach ($staff as $employee) {
            // Get all attendance records for this staff member in date range
            $attendanceRecords = Attendance::where('staff_id', $employee->id)
                ->whereBetween('date', [$from, $to])
                ->get();
            
            // Count by status
            $presentDays = $attendanceRecords->where('status', 'present')->count();
            $absentDays = $attendanceRecords->where('status', 'absent')->count();
            $lateDays = $attendanceRecords->where('status', 'late')->count();
            $halfDays = $attendanceRecords->where('status', 'half_day')->count();
            $onLeaveDays = $attendanceRecords->where('status', 'on_leave')->count();
            $offDutyDays = $attendanceRecords->where('status', 'off_duty')->count();
            
            // Calculate attendance rate (present + late + half_day as attended)
            $totalWorkingDays = $attendanceRecords->count();
            $attendedDays = $presentDays + $lateDays + ($halfDays * 0.5);
            $attendanceRate = $totalWorkingDays > 0 ? round(($attendedDays / $totalWorkingDays) * 100, 2) : 0;
            
            // Get department and position names
            $departmentName = $employee->department ? $employee->department->name : 'N/A';
            $positionName = $employee->position ? $employee->position->name : 'N/A';
            
            $staffAttendance[] = [
                'id' => $employee->id,
                'employee_id' => $employee->employee_id ?? 'N/A',
                'name' => $employee->first_name . ' ' . $employee->last_name,
                'first_name' => $employee->first_name,
                'last_name' => $employee->last_name,
                'department' => $departmentName,
                'position' => $positionName,
                'present_days' => $presentDays,
                'absent_days' => $absentDays,
                'late_days' => $lateDays,
                'half_days' => $halfDays,
                'on_leave_days' => $onLeaveDays,
                'leave_days' => $onLeaveDays, // Add this for compatibility with your view
                'off_duty_days' => $offDutyDays,
                'attendance_rate' => $attendanceRate,
                'total_days' => $totalWorkingDays,
            ];
        }
        
        return collect($staffAttendance);
    }
    
    /**
     * Show attendance record for editing
     */
    public function edit($id)
    {
        $hotelId = $this->getHotelId();
        $attendance = Attendance::with('staff')->where('hotel_id', $hotelId)->findOrFail($id);
        $staff = Staff::where('hotel_id', $hotelId)->where('status', 'active')->get();
        
        return view('attendance.edit', compact('attendance', 'staff'));
    }
    
    /**
     * Update attendance record
     */
    public function update(Request $request, $id)
    {
        $hotelId = $this->getHotelId();
        $attendance = Attendance::where('hotel_id', $hotelId)->findOrFail($id);
        
        $request->validate([
            'staff_id' => [
                'required',
                Rule::exists('staff', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'date' => 'required|date',
            'clock_in' => 'nullable|date_format:H:i',
            'clock_out' => 'nullable|date_format:H:i',
            'status' => 'required|in:present,absent,late,half_day,on_leave,off_duty'
        ]);
        
        try {
            // Check if clock_out is after clock_in if both are provided
            if ($request->clock_in && $request->clock_out && $request->clock_out <= $request->clock_in) {
                return redirect()->back()
                    ->with('error', 'Clock out time must be after clock in time.')
                    ->withInput();
            }
            
            $attendance->update([
                'staff_id' => $request->staff_id,
                'date' => $request->date,
                'clock_in_time' => $request->clock_in ?: null,
                'clock_out_time' => $request->clock_out ?: null,
                'status' => $request->status,
                'notes' => $request->notes,
            ]);
            
            return redirect()->route('attendance.report')
                ->with('success', 'Attendance record updated successfully!');
                
        } catch (\Exception $e) {
            return redirect()->back()
                ->with('error', 'Error updating attendance: ' . $e->getMessage())
                ->withInput();
        }
    }
    
    /**
     * Delete attendance record
     */
    public function destroy($id)
    {
        try {
            $attendance = Attendance::where('hotel_id', $this->getHotelId())->findOrFail($id);
            $attendance->delete();
            
            return redirect()->route('attendance.report')
                ->with('success', 'Attendance record deleted successfully!');
                
        } catch (\Exception $e) {
            return redirect()->back()
                ->with('error', 'Error deleting attendance: ' . $e->getMessage());
        }
    }
    
    /**
     * API: Get today's attendance
     */
    public function getTodayAttendance()
    {
        $hotelId = $this->getHotelId();
        $today = Carbon::today()->format('Y-m-d');
        $attendance = Attendance::with('staff')
            ->where('hotel_id', $hotelId)
            ->where('date', $today)
            ->get()
            ->map(function ($record) {
                return [
                    'id' => $record->id,
                    'staff_id' => $record->staff_id,
                    'staff_name' => $record->staff ? 
                        ($record->staff->first_name . ' ' . $record->staff->last_name) : 'Unknown',
                    'date' => $record->date,
                    'clock_in_time' => $record->clock_in_time,
                    'clock_out_time' => $record->clock_out_time,
                    'status' => $record->status,
                ];
            });
        
        return response()->json([
            'date' => $today,
            'attendance' => $attendance,
            'count' => $attendance->count()
        ]);
    }
    
    /**
     * API: Record bulk attendance
     */
    public function recordBulk(Request $request)
    {
        $hotelId = $this->getHotelId();
        $request->validate([
            'date' => 'required|date',
            'records' => 'required|array',
            'records.*.staff_id' => [
                'required',
                Rule::exists('staff', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'records.*.status' => 'required|in:present,absent,late,half_day,on_leave,off_duty',
            'records.*.clock_in' => 'nullable|date_format:H:i',
            'records.*.clock_out' => 'nullable|date_format:H:i',
        ]);
        
        try {
            DB::beginTransaction();
            
            foreach ($request->records as $record) {
                Attendance::updateOrCreate(
                    [
                        'staff_id' => $record['staff_id'],
                        'date' => $request->date,
                        'hotel_id' => $hotelId,
                    ],
                    [
                        'clock_in_time' => $record['clock_in'] ?: null,
                        'clock_out_time' => $record['clock_out'] ?: null,
                        'status' => $record['status'],
                    ]
                );
            }
            
            DB::commit();
            
            return response()->json([
                'success' => true,
                'message' => 'Bulk attendance recorded successfully',
                'count' => count($request->records)
            ]);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Error recording bulk attendance: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * API: Get report data
     */
    public function getReportData(Request $request)
    {
        $hotelId = $this->getHotelId();
        $from = $request->get('from', Carbon::now()->subDays(30)->format('Y-m-d'));
        $to = $request->get('to', Carbon::now()->format('Y-m-d'));
        
        $query = Attendance::with('staff')
            ->where('hotel_id', $hotelId)
            ->whereBetween('date', [$from, $to]);
        
        if ($request->has('staff_id') && $request->staff_id) {
            $query->where('staff_id', $request->staff_id);
        }
        
        if ($request->has('status') && $request->status) {
            $query->where('status', $request->status);
        }
        
        $attendance = $query->get();
        
        // Group by status for chart data
        $statusCounts = $attendance->groupBy('status')->map->count();
        
        // Group by date for trend data
        $dateTrends = $attendance->groupBy('date')->map(function ($records) {
            return [
                'present' => $records->where('status', 'present')->count(),
                'absent' => $records->where('status', 'absent')->count(),
                'late' => $records->where('status', 'late')->count(),
                'total' => $records->count()
            ];
        })->sortKeys();
        
        return response()->json([
            'summary' => [
                'total' => $attendance->count(),
                'present' => $attendance->where('status', 'present')->count(),
                'absent' => $attendance->where('status', 'absent')->count(),
                'late' => $attendance->where('status', 'late')->count(),
                'half_day' => $attendance->where('status', 'half_day')->count(),
                'on_leave' => $attendance->where('status', 'on_leave')->count(),
                'off_duty' => $attendance->where('status', 'off_duty')->count(),
            ],
            'status_counts' => $statusCounts,
            'date_trends' => $dateTrends,
            'records' => $attendance->take(100)->values()
        ]);
    }
    
    /**
     * Get attendance summary for dashboard
     */
    public function getDashboardSummary()
    {
        $hotelId = $this->getHotelId();
        $today = Carbon::today()->format('Y-m-d');
        
        $todayAttendance = Attendance::where('hotel_id', $hotelId)->where('date', $today)->get();
        $totalStaff = Staff::where('hotel_id', $hotelId)->where('status', 'active')->count();
        
        $summary = [
            'present_today' => $todayAttendance->where('status', 'present')->count(),
            'absent_today' => $todayAttendance->where('status', 'absent')->count(),
            'late_today' => $todayAttendance->where('status', 'late')->count(),
            'total_staff' => $totalStaff,
            'attendance_rate' => $totalStaff > 0 ? 
                round(($todayAttendance->whereIn('status', ['present', 'late', 'half_day'])->count() / $totalStaff) * 100, 2) : 0,
        ];
        
        return response()->json($summary);
    }
}