<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Attendance;
use App\Models\Employee;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class AttendanceController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index(Request $request)
    {
        $user  = auth()->user();
        $month = $request->month ?? now()->format('Y-m');
        [$year, $mon] = explode('-', $month);

        $query = Attendance::with(['employee.user', 'employee.department'])
                           ->whereYear('date', $year)
                           ->whereMonth('date', $mon);

        if ($user->isEmployee()) {
            $emp = $user->employee;
            if ($emp) $query->where('employee_id', $emp->id);
            else      $query->whereRaw('1=0');
        } elseif ($user->isDeptHead()) {
            $query->whereHas('employee', fn($q) =>
                $q->where('department_id', $user->getDepartmentIdAttribute())
            );
        } elseif ($request->employee_id) {
            $query->where('employee_id', $request->employee_id);
        }

        if ($request->status) $query->where('status', $request->status);

        $records = $query->orderByDesc('date')->paginate(20)->withQueryString();

        $employees = ($user->isHrOrAdmin() || $user->isPresident())
            ? Employee::with('user')->where('status', 'active')->get()
            : null;

        // Per-month summary for the logged-in employee
        $my_summary = null;
        if ($user->isEmployee() && $user->employee) {
            $eid = $user->employee->id;
            $my_summary = [
                'present'  => Attendance::where('employee_id', $eid)->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'present')->count(),
                'absent'   => Attendance::where('employee_id', $eid)->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'absent')->count(),
                'late'     => Attendance::where('employee_id', $eid)->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'late')->count(),
                'on_leave' => Attendance::where('employee_id', $eid)->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'on_leave')->count(),
            ];
        }

        return view('attendance.index', compact('records', 'employees', 'month', 'my_summary'));
    }

    public function bulkStore(Request $request)
    {
        $this->authorize('isHrOrAdmin');
        $request->validate(['date' => 'required|date', 'records' => 'required|array']);

        DB::transaction(function () use ($request) {
            foreach ($request->records as $empId => $data) {
                Attendance::updateOrCreate(
                    ['employee_id' => $empId, 'date' => $request->date],
                    array_merge($data, ['recorded_by' => auth()->id()])
                );
            }
        });

        return back()->with('success', 'Attendance saved for ' . $request->date);
    }

    public function markToday(Request $request)
    {
        $employee = auth()->user()->employee;
        if (! $employee) return back()->with('error', 'Employee profile not found.');

        // ── GPS restriction (server-side enforcement) ──────────────────────
        if (config('hrms.gps_restrict')) {
            $allowedLat    = (float) config('hrms.gps_lat');
            $allowedLng    = (float) config('hrms.gps_lng');
            $radiusMeters  = (int)   config('hrms.gps_radius_meters', 150);

            $submittedLat  = $request->input('gps_lat');
            $submittedLng  = $request->input('gps_lng');

            // Reject if coordinates were not submitted at all
            if (is_null($submittedLat) || is_null($submittedLng)) {
                return back()->with('error',
                    'Clock-in requires location access. Please allow location in your browser and try again.');
            }

            // Haversine formula — distance in metres between two lat/lng points
            $earthRadius = 6371000; // metres
            $dLat = deg2rad((float)$submittedLat - $allowedLat);
            $dLng = deg2rad((float)$submittedLng - $allowedLng);
            $a = sin($dLat / 2) ** 2
               + cos(deg2rad($allowedLat)) * cos(deg2rad((float)$submittedLat))
               * sin($dLng / 2) ** 2;
            $distance = $earthRadius * 2 * asin(sqrt($a));

            if ($distance > $radiusMeters) {
                $distanceRounded = round($distance);
                return back()->with('error',
                    "Clock-in not allowed: you are {$distanceRounded} m from the office "
                    . "(allowed within {$radiusMeters} m).");
            }
        }

        $att = Attendance::firstOrNew([
            'employee_id' => $employee->id,
            'date'        => today(),
        ]);

        if (! $att->time_in) {
            $att->time_in    = now()->format('H:i:s');
            $att->status     = 'present';
            $att->recorded_by= auth()->id();
            $att->save();
            return back()->with('success', 'Clock-in recorded: ' . now()->format('h:i A'));
        }

        $att->time_out     = now()->format('H:i:s');
        $att->hours_worked = Carbon::parse($att->time_in)->diffInMinutes(now()) / 60;
        $att->save();
        return back()->with('success', 'Clock-out recorded: ' . now()->format('h:i A'));
    }

    public function summary(Request $request)
    {
        $month = $request->month ?? now()->format('Y-m');
        [$year, $mon] = explode('-', $month);

        $summary = Employee::where('status', 'active')
            ->with(['user', 'department'])
            ->withCount([
                'attendance as present_days' => fn($q) => $q->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'present'),
                'attendance as absent_days'  => fn($q) => $q->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'absent'),
                'attendance as late_days'    => fn($q) => $q->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'late'),
                'attendance as leave_days'   => fn($q) => $q->whereYear('date', $year)->whereMonth('date', $mon)->where('status', 'on_leave'),
            ])
            ->paginate(20)
            ->withQueryString();

        return view('attendance.summary', compact('summary', 'month'));
    }
}
