<?php

namespace App\Http\Controllers;

use App\Models\Attendance;
use App\Models\Client;
use App\Models\PatrolSchedule;
use App\Models\Status;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class DashboardController extends Controller
{
    public function index()
    {
        $user = Auth::user();
        $tenantId = config('app.default_tenant_id', 1);

        // Get dashboard statistics
        $stats = $this->getDashboardStats($tenantId);

        // Get recent activities
        $recentActivities = $this->getRecentActivities($user);

        // Get attendance overview for the week
        $attendanceOverview = $this->getAttendanceOverview($tenantId);

        // Get patrol schedules for today
        $todayPatrols = $this->getTodayPatrols($tenantId);

        // Get upcoming events
        $upcomingEvents = $this->getUpcomingEvents($user);

        return view('dashboard.index', compact(
            'stats',
            'recentActivities',
            'attendanceOverview',
            'todayPatrols',
            'upcomingEvents'
        ));
    }

    public function admin()
    {
        $user = Auth::user();
        $tenantId = config('app.default_tenant_id', 1);

        // Get dashboard statistics (using admin-specific stats)
        $stats = $this->getAdminStats($tenantId);

        // Get recent activities
        $recentActivities = $this->getRecentActivities($user);

        // Get attendance overview for the week
        $attendanceOverview = $this->getAttendanceOverview($tenantId);

        // Get patrol schedules for today
        $todayPatrols = $this->getTodayPatrols($tenantId);

        // Get upcoming events
        $upcomingEvents = $this->getUpcomingEvents($user);

        return view('dashboard.index', compact(
            'stats',
            'recentActivities',
            'attendanceOverview',
            'todayPatrols',
            'upcomingEvents'
        ));
    }

    public function employee()
    {
        $user = Auth::user();

        // Employee's current attendance status
        $attendanceStatus = $this->getEmployeeAttendanceStatus($user);

        // Employee's patrol schedule for today
        $todaySchedule = $user->getCurrentPatrolSchedule();

        // Employee's recent attendance history
        $recentAttendance = $this->getEmployeeRecentAttendance($user);

        // Employee's upcoming patrols
        $upcomingPatrols = $this->getEmployeeUpcomingPatrols($user);

        // Employee's performance metrics
        $performanceMetrics = $this->getEmployeePerformanceMetrics($user);

        return view('dashboard.employee', compact(
            'attendanceStatus',
            'todaySchedule',
            'recentAttendance',
            'upcomingPatrols',
            'performanceMetrics'
        ));
    }

    private function getDashboardStats(int $tenantId): array
    {
        return [
            'total_employees' => User::byTenant($tenantId)->active()->count(),
            'present_today' => Attendance::byTenant($tenantId)
                ->whereDate('in_date', today())
                ->whereHas('status', fn($q) => $q->where('name', 'present'))
                ->count(),
            'active_patrols' => PatrolSchedule::byTenant($tenantId)
                ->where('schedule_date', today())
                ->whereHas('status', fn($q) => $q->where('name', 'active'))
                ->count(),
            'total_clients' => Client::byTenant($tenantId)->active()->count(),
            'pending_requests' => DB::table('attendance_requests')
                ->where('tenant_id', $tenantId)
                ->whereExists(function ($query) {
                    $query->select(DB::raw(1))
                        ->from('statuses')
                        ->whereColumn('attendance_requests.status_id', 'statuses.id')
                        ->where('statuses.name', 'pending');
                })
                ->count(),
        ];
    }

    private function getRecentActivities($user): array
    {
        // Simplified recent activities since we removed activity logging
        return [
            [
                'description' => 'User logged in',
                'time' => $user->last_login_at?->diffForHumans() ?? 'Never',
                'icon' => 'login',
                'color' => 'green',
            ],
            [
                'description' => 'Profile created',
                'time' => $user->created_at->diffForHumans(),
                'icon' => 'plus',
                'color' => 'blue',
            ],
        ];
    }

    private function getAttendanceOverview(int $tenantId): array
    {
        $startDate = Carbon::now()->startOfWeek();
        $endDate = Carbon::now()->endOfWeek();

        $attendance = Attendance::byTenant($tenantId)
            ->whereBetween('in_date', [$startDate, $endDate])
            ->selectRaw('DATE(in_date) as date, COUNT(*) as count')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        return [
            'labels' => $attendance->pluck('date')->map(fn($date) => Carbon::parse($date)->format('D')),
            'data' => $attendance->pluck('count'),
        ];
    }

    private function getTodayPatrols(int $tenantId): array
    {
        return PatrolSchedule::with(['client', 'location', 'employee', 'status'])
            ->where('schedule_date', today())
            ->where('tenant_id', $tenantId)
            ->whereHas('status', fn($q) => $q->where('name', 'active'))
            ->get()
            ->map(function ($schedule) {
                return [
                    'id' => $schedule->id,
                    'client' => $schedule->client?->name ?? 'Unknown Client',
                    'location' => $schedule->location?->name ?? 'Unknown Location',
                    'employee' => $schedule->employee?->full_name ?? 'Unassigned',
                    'shift' => ucfirst($schedule->shift_type),
                    'time' => $schedule->start_time . ' - ' . $schedule->end_time,
                    'status' => $schedule->status?->name ?? 'Unknown Status',
                ];
            })
            ->toArray();
    }

    private function getUpcomingEvents($user): array
    {
        // This would integrate with a calendar/events system
        // For now, return upcoming patrols and holidays
        $events = [];

        // Upcoming patrols for the user
        $upcomingPatrols = $user->patrolSchedules()
            ->where('schedule_date', '>', today())
            ->where('schedule_date', '<=', today()->addDays(7))
            ->with(['client', 'location'])
            ->get();

        foreach ($upcomingPatrols as $patrol) {
            $events[] = [
                'title' => 'Patrol: ' . ($patrol->client?->name ?? 'Unknown Client'),
                'location' => $patrol->location?->name ?? 'Unknown Location',
                'date' => $patrol->schedule_date->format('M d, Y'),
                'time' => $patrol->start_time,
                'type' => 'patrol',
                'color' => 'blue',
            ];
        }

        return $events;
    }

    private function getAdminStats(int $tenantId): array
    {
        $thisMonth = Carbon::now()->startOfMonth();
        $lastMonth = Carbon::now()->subMonth()->startOfMonth();

        return [
            'total_employees' => User::byTenant($tenantId)->active()->count(),
            'present_today' => Attendance::byTenant($tenantId)
                ->whereDate('in_date', today())
                ->whereHas('status', fn($q) => $q->where('name', 'present'))
                ->count(),
            'active_patrols' => PatrolSchedule::byTenant($tenantId)
                ->where('schedule_date', today())
                ->whereHas('status', fn($q) => $q->where('name', 'active'))
                ->count(),
            'total_clients' => Client::byTenant($tenantId)->active()->count(),
            'monthly_revenue' => $this->getMonthlyRevenue($tenantId, $thisMonth),
            'revenue_growth' => $this->getRevenueGrowth($tenantId, $thisMonth, $lastMonth),
            'new_clients' => Client::byTenant($tenantId)
                ->where('created_at', '>=', $thisMonth)
                ->count(),
            'client_retention' => $this->getClientRetentionRate($tenantId),
            'patrol_completion' => $this->getPatrolCompletionRate($tenantId),
            'attendance_rate' => $this->getAttendanceRate($tenantId),
            'pending_requests' => DB::table('attendance_requests')
                ->where('tenant_id', $tenantId)
                ->whereExists(function ($query) {
                    $query->select(DB::raw(1))
                        ->from('statuses')
                        ->whereColumn('attendance_requests.status_id', 'statuses.id')
                        ->where('statuses.name', 'pending');
                })
                ->count(),
        ];
    }

    private function getDepartmentAttendance(int $tenantId): array
    {
        return DB::table('departments as d')
            ->select([
                'd.name',
                DB::raw('COUNT(DISTINCT u.id) as total_employees'),
                DB::raw('COUNT(DISTINCT CASE WHEN a.in_date = CURDATE() THEN a.id END) as present_today'),
            ])
            ->leftJoin('department_user as du', 'd.id', '=', 'du.department_id')
            ->leftJoin('users as u', 'du.user_id', '=', 'u.id')
            ->leftJoin('attendances as a', 'u.id', '=', 'a.user_id')
            ->where('d.tenant_id', $tenantId)
            ->whereNull('d.deleted_at')
            ->whereNull('u.deleted_at')
            ->groupBy('d.id', 'd.name')
            ->get()
            ->map(function ($dept) {
                $attendanceRate = $dept->total_employees > 0 
                    ? ($dept->present_today / $dept->total_employees) * 100 
                    : 0;

                return [
                    'department' => $dept->name,
                    'total' => $dept->total_employees,
                    'present' => $dept->present_today,
                    'rate' => round($attendanceRate, 1),
                ];
            })
            ->toArray();
    }

    private function getClientMetrics(int $tenantId): array
    {
        return Client::byTenant($tenantId)
            ->withCount(['locations', 'contracts' => function ($q) {
                $q->whereHas('status', fn($sq) => $sq->where('name', 'active'));
            }])
            ->with(['patrolSchedules' => function ($q) {
                $q->where(function ($query) {
                    // Get schedules for today's date OR recurring schedules (NULL date)
                    $query->where('schedule_date', today())
                          ->orWhereNull('schedule_date');
                })->whereHas('timeSlots', function ($subQuery) {
                    // Only get schedules that have time slots for today
                    $subQuery->where(function ($innerQuery) {
                        $innerQuery->where('date', today())
                                ->orWhere('day_of_week', strtolower(now()->format('l')));
                    })->where('is_active', true);
                });
            }])
            ->get()
            ->map(function ($client) {
                return [
                    'name' => $client->name,
                    'locations' => $client->locations_count,
                    'active_contracts' => $client->contracts_count,
                    'today_patrols' => $client->patrol_schedules->count(),
                    'status' => $client->status?->name ?? 'Unknown Status',
                ];
            })
            ->toArray();
    }

    private function getPatrolCompliance(int $tenantId): array
    {
        $totalScheduled = PatrolSchedule::byTenant($tenantId)
            ->where('schedule_date', today())
            ->count();

        $completedPatrols = DB::table('patrol_logs')
            ->join('patrol_schedules', 'patrol_logs.schedule_id', '=', 'patrol_schedules.id')
            ->where('patrol_schedules.schedule_date', today())
            ->where('patrol_schedules.tenant_id', $tenantId)
            ->distinct('patrol_logs.schedule_id')
            ->count('patrol_logs.schedule_id');

        $complianceRate = $totalScheduled > 0 ? ($completedPatrols / $totalScheduled) * 100 : 0;

        return [
            'total_scheduled' => $totalScheduled,
            'completed' => $completedPatrols,
            'compliance_rate' => round($complianceRate, 1),
        ];
    }

    private function getRecentViolations(int $tenantId): array
    {
        return DB::table('patrol_violations as pv')
            ->join('users as u', 'pv.employee_id', '=', 'u.id')
            ->join('patrol_schedules as ps', 'pv.schedule_id', '=', 'ps.id')
            ->join('clients as c', 'ps.client_id', '=', 'c.id')
            ->where('pv.tenant_id', $tenantId)
            ->where('pv.is_resolved', false)
            ->orderBy('pv.violation_time', 'desc')
            ->limit(10)
            ->get([
                'pv.id',
                'pv.violation_type',
                'pv.violation_time',
                'u.first_name',
                'u.last_name',
                'c.name as client_name',
            ])
            ->map(function ($violation) {
                return [
                    'id' => $violation->id,
                    'type' => str_replace('_', ' ', ucfirst($violation->violation_type)),
                    'employee' => $violation->first_name . ' ' . $violation->last_name,
                    'client' => $violation->client_name,
                    'time' => Carbon::parse($violation->violation_time)->format('M d, Y H:i'),
                ];
            })
            ->toArray();
    }

    private function getEmployeeAttendanceStatus($user): array
    {
        $todayAttendance = $user->attendances()
            ->where('in_date', today())
            ->with('details')
            ->first();

        $isPunchedIn = $user->is_punched_in;
        $lastPunch = $user->last_punch_time;

        return [
            'is_punched_in' => $isPunchedIn,
            'last_punch_time' => $lastPunch ? $lastPunch->format('H:i:s') : null,
            'punch_in_time' => $todayAttendance?->punch_in_time?->format('H:i:s'),
            'punch_out_time' => $todayAttendance?->punch_out_time?->format('H:i:s'),
            'total_hours' => $todayAttendance?->total_hours,
            'can_punch_in' => $user->canPunchIn(),
            'can_punch_out' => $user->canPunchOut(),
        ];
    }

    private function getEmployeeRecentAttendance($user): array
    {
        return $user->attendances()
            ->with('details')
            ->orderBy('in_date', 'desc')
            ->limit(7)
            ->get()
            ->map(function ($attendance) {
                return [
                    'date' => $attendance->in_date->format('M d, Y'),
                    'punch_in' => $attendance->punch_in_time?->format('H:i'),
                    'punch_out' => $attendance->punch_out_time?->format('H:i'),
                    'total_hours' => $attendance->total_hours,
                    'behavior' => $attendance->behavior,
                    'status' => $attendance->status?->name ?? 'Unknown Status',
                ];
            })
            ->toArray();
    }

    private function getEmployeeUpcomingPatrols($user): array
    {
        return $user->patrolSchedules()
            ->where('schedule_date', '>=', today())
            ->where('schedule_date', '<=', today()->addDays(7))
            ->with(['client', 'location'])
            ->orderBy('schedule_date')
            ->get()
            ->map(function ($schedule) {
                return [
                    'date' => $schedule->schedule_date->format('M d, Y'),
                    'client' => $schedule->client?->name ?? 'Unknown Client',
                    'location' => $schedule->location?->name ?? 'Unknown Location',
                    'shift' => ucfirst($schedule->shift_type),
                    'time' => $schedule->start_time . ' - ' . $schedule->end_time,
                ];
            })
            ->toArray();
    }

    private function getEmployeePerformanceMetrics($user): array
    {
        $thisMonth = Carbon::now()->startOfMonth();
        
        $attendanceRate = $this->calculateEmployeeAttendanceRate($user, $thisMonth);
        $patrolCompletionRate = $this->calculateEmployeePatrolCompletionRate($user, $thisMonth);
        $onTimeRate = $this->calculateEmployeeOnTimeRate($user, $thisMonth);

        return [
            'attendance_rate' => $attendanceRate,
            'patrol_completion' => $patrolCompletionRate,
            'on_time_rate' => $onTimeRate,
            'total_patrols' => $user->patrolLogs()
                ->where('created_at', '>=', $thisMonth)
                ->count(),
            'violations' => $user->patrolViolations()
                ->where('created_at', '>=', $thisMonth)
                ->count(),
        ];
    }

    // Helper methods for calculations
    private function getActivityIcon(string $description): string
    {
        if (str_contains($description, 'logged in')) return 'login';
        if (str_contains($description, 'logged out')) return 'logout';
        if (str_contains($description, 'created')) return 'plus';
        if (str_contains($description, 'updated')) return 'edit';
        if (str_contains($description, 'deleted')) return 'trash';
        return 'activity';
    }

    private function getActivityColor(string $description): string
    {
        if (str_contains($description, 'logged in')) return 'green';
        if (str_contains($description, 'logged out')) return 'blue';
        if (str_contains($description, 'created')) return 'green';
        if (str_contains($description, 'updated')) return 'yellow';
        if (str_contains($description, 'deleted')) return 'red';
        return 'gray';
    }

    private function getMonthlyRevenue(int $tenantId, Carbon $month): float
    {
        return Client::byTenant($tenantId)
            ->whereHas('contracts', function ($q) use ($month) {
                $q->where('start_date', '<=', $month)
                    ->where(function ($sq) use ($month) {
                        $sq->whereNull('end_date')
                            ->orWhere('end_date', '>=', $month);
                    });
            })
            ->with('contracts')
            ->get()
            ->sum(function ($client) use ($month) {
                return $client->contracts
                    ->where('status_id', Status::getActiveId())
                    ->sum('value');
            });
    }

    private function calculateEmployeeAttendanceRate($user, Carbon $month): float
    {
        $workingDays = Carbon::now()->diffInDaysFiltered(function ($date) use ($month) {
            return $date->isWeekday() && $date->gte($month);
        }, Carbon::now());

        if ($workingDays === 0) return 0;

        $presentDays = $user->attendances()
            ->where('in_date', '>=', $month)
            ->whereHas('status', fn($q) => $q->where('name', 'present'))
            ->count();

        return ($presentDays / $workingDays) * 100;
    }

    private function calculateEmployeePatrolCompletionRate($user, Carbon $month): float
    {
        $totalPatrols = $user->patrolSchedules()
            ->where('schedule_date', '>=', $month)
            ->count();

        if ($totalPatrols === 0) return 0;

        $completedPatrols = $user->patrolLogs()
            ->where('created_at', '>=', $month)
            ->distinct('schedule_id')
            ->count('schedule_id');

        return ($completedPatrols / $totalPatrols) * 100;
    }

    private function calculateEmployeeOnTimeRate($user, Carbon $month): float
    {
        $totalPunchIns = $user->attendanceDetails()
            ->where('type', 'in')
            ->where('punch_time', '>=', $month)
            ->count();

        if ($totalPunchIns === 0) return 0;

        $onTimePunchIns = $user->attendanceDetails()
            ->where('type', 'in')
            ->where('punch_time', '>=', $month)
            ->whereHas('attendance', fn($q) => $q->where('behavior', 'regular'))
            ->count();

        return ($onTimePunchIns / $totalPunchIns) * 100;
    }

    private function getRevenueGrowth(int $tenantId, Carbon $thisMonth, Carbon $lastMonth): float
    {
        $thisMonthRevenue = $this->getMonthlyRevenue($tenantId, $thisMonth);
        $lastMonthRevenue = $this->getMonthlyRevenue($tenantId, $lastMonth);

        if ($lastMonthRevenue <= 0) return 0;

        return (($thisMonthRevenue - $lastMonthRevenue) / $lastMonthRevenue) * 100;
    }

    private function getClientRetentionRate(int $tenantId): float
    {
        $totalClients = Client::byTenant($tenantId)->count();
        $activeClients = Client::byTenant($tenantId)->active()->count();

        return $totalClients > 0 ? ($activeClients / $totalClients) * 100 : 0;
    }

    private function getPatrolCompletionRate(int $tenantId): float
    {
        $totalScheduled = PatrolSchedule::byTenant($tenantId)
            ->where('schedule_date', '>=', Carbon::now()->subDays(30))
            ->count();

        if ($totalScheduled === 0) return 0;

        $completedPatrols = DB::table('patrol_logs')
            ->join('patrol_schedules', 'patrol_logs.schedule_id', '=', 'patrol_schedules.id')
            ->where('patrol_schedules.tenant_id', $tenantId)
            ->where('patrol_schedules.schedule_date', '>=', Carbon::now()->subDays(30))
            ->distinct('patrol_logs.schedule_id')
            ->count('patrol_logs.schedule_id');

        return ($completedPatrols / $totalScheduled) * 100;
    }

    private function getAttendanceRate(int $tenantId): float
    {
        $totalEmployees = User::byTenant($tenantId)->active()->count();
        $presentToday = Attendance::byTenant($tenantId)
            ->whereDate('in_date', today())
            ->whereHas('status', fn($q) => $q->where('name', 'present'))
            ->count();

        return $totalEmployees > 0 ? ($presentToday / $totalEmployees) * 100 : 0;
    }
}
