<?php

namespace App\Http\Controllers;

use App\Models\AttendanceRecord;
use App\Models\ChurchService;
use App\Models\Jumuiya;
use App\Models\Member;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class AttendanceController extends Controller
{
    public function qr(): View
    {
        return view('attendance.qr', [
            'openServices' => $this->openServices(),
            'recentRecords' => AttendanceRecord::with(['member.jumuiya', 'churchService', 'markedBy'])->latest()->limit(10)->get(),
        ]);
    }

    public function manual(Request $request): View|RedirectResponse
    {
        $filterKeys = ['church_service_id', 'search', 'jumuiya_id'];

        if ($request->hasAny($filterKeys)) {
            $request->session()->put('attendance.manual_filters', $request->only($filterKeys));

            return redirect()->route('attendance.manual');
        }

        $filters = $request->session()->get('attendance.manual_filters', []);

        $members = Member::with(['jumuiya', 'position'])
            ->where('status', 'active')
            ->when($filters['search'] ?? null, function ($query, $search) {
                $query->where(function ($query) use ($search) {
                    $query->where('first_name', 'like', "%{$search}%")
                        ->orWhere('middle_name', 'like', "%{$search}%")
                        ->orWhere('last_name', 'like', "%{$search}%")
                        ->orWhere('phone', 'like', "%{$search}%")
                        ->orWhere('member_code', 'like', "%{$search}%");
                });
            })
            ->when($filters['jumuiya_id'] ?? null, fn ($query, $jumuiyaId) => $query->where('jumuiya_id', $jumuiyaId))
            ->orderBy('first_name')
            ->paginate(15);

        $openServices = $this->openServices();

        return view('attendance.manual', [
            'members' => $members,
            'openServices' => $openServices,
            'jumuiyas' => Jumuiya::where('status', 'active')->orderBy('name')->get(),
            'selectedServiceId' => filled($filters['church_service_id'] ?? null) ? (int) $filters['church_service_id'] : optional($openServices->first())->id,
            'filters' => $filters,
        ]);
    }

    public function manualFilter(Request $request): RedirectResponse
    {
        if ($request->boolean('clear_filters')) {
            $request->session()->forget('attendance.manual_filters');

            return redirect()->route('attendance.manual');
        }

        $data = $request->validate([
            'church_service_id' => ['nullable', 'exists:church_services,id'],
            'search' => ['nullable', 'string', 'max:255'],
            'jumuiya_id' => ['nullable', 'exists:jumuiyas,id'],
        ]);

        $request->session()->put('attendance.manual_filters', array_filter($data, fn ($value) => filled($value)));

        return redirect()->route('attendance.manual');
    }

    public function records(Request $request): View
    {
        $records = AttendanceRecord::with(['member.jumuiya', 'churchService.serviceType', 'markedBy'])
            ->when($request->from_date, fn ($query, $from) => $query->whereDate('attendance_date', '>=', $from))
            ->when($request->to_date, fn ($query, $to) => $query->whereDate('attendance_date', '<=', $to))
            ->when($request->method, fn ($query, $method) => $query->where('method', $method))
            ->when($request->church_service_id, fn ($query, $service) => $query->where('church_service_id', $service))
            ->latest()
            ->paginate(20)
            ->withQueryString();

        return view('attendance.records', [
            'records' => $records,
            'services' => ChurchService::latest('service_date')->get(),
        ]);
    }

    public function today(): View
    {
        return view('attendance.records', [
            'records' => AttendanceRecord::with(['member.jumuiya', 'churchService.serviceType', 'markedBy'])
                ->whereDate('attendance_date', now()->toDateString())
                ->latest()
                ->paginate(20),
            'services' => ChurchService::latest('service_date')->get(),
            'todayMode' => true,
        ]);
    }

    public function absent(Request $request): View
    {
        $service = $request->church_service_id ? ChurchService::find($request->church_service_id) : null;
        $members = collect();

        if ($service) {
            $members = Member::with(['jumuiya', 'position'])
                ->where('status', 'active')
                ->whereDoesntHave('attendanceRecords', fn ($query) => $query->where('church_service_id', $service->id))
                ->orderBy('first_name')
                ->get();
        }

        return view('attendance.absent', [
            'services' => ChurchService::latest('service_date')->get(),
            'selectedService' => $service,
            'members' => $members,
        ]);
    }

    public function mark(Request $request): JsonResponse|RedirectResponse
    {
        $data = $request->validate([
            'church_service_id' => ['required', 'exists:church_services,id'],
            'method' => ['required', 'in:qr,manual'],
            'member_id' => ['nullable', 'exists:members,id'],
            'qr_token' => ['nullable', 'string'],
            'remarks' => ['nullable', 'string'],
        ]);

        $service = ChurchService::findOrFail($data['church_service_id']);
        if ($service->status !== 'open') {
            return $this->attendanceResponse($request, false, 'Service hii imefungwa. Attendance haiwezi kuongezwa.', 422);
        }

        $member = $data['method'] === 'qr'
            ? Member::where('qr_token', $data['qr_token'] ?? null)->first()
            : Member::find($data['member_id'] ?? null);

        if (! $member) {
            return $this->attendanceResponse($request, false, 'Member hakupatikana kwenye database.', 404);
        }

        if ($member->status !== 'active') {
            return $this->attendanceResponse($request, false, "{$member->full_name} hayupo active kwa sasa.", 422);
        }

        $duplicate = AttendanceRecord::where('member_id', $member->id)
            ->where('church_service_id', $service->id)
            ->exists();

        if ($duplicate) {
            return $this->attendanceResponse($request, false, "{$member->full_name} tayari ameshawekwa present kwa service hii.", 409, [
                'member' => $member->full_name,
            ]);
        }

        $record = AttendanceRecord::create([
            'member_id' => $member->id,
            'church_service_id' => $service->id,
            'attendance_date' => $service->service_date,
            'time_in' => now()->format('H:i:s'),
            'method' => $data['method'],
            'marked_by' => $this->actingUser()?->id,
            'status' => 'present',
            'remarks' => $data['remarks'] ?? null,
        ]);

        $this->logActivity('created', 'attendance', "Marked {$member->full_name} present for {$service->name}", [
            'method' => $data['method'],
            'service_id' => $service->id,
            'member_id' => $member->id,
        ]);

        return $this->attendanceResponse($request, true, "{$member->full_name} amewekwa present.", 201, [
            'record' => $record->load(['member.jumuiya', 'churchService', 'markedBy']),
        ]);
    }

    private function openServices()
    {
        return ChurchService::where('status', 'open')->latest('service_date')->get();
    }

    private function attendanceResponse(Request $request, bool $ok, string $message, int $status = 200, array $extra = []): JsonResponse|RedirectResponse
    {
        if ($request->expectsJson() || $request->ajax()) {
            return response()->json(['ok' => $ok, 'message' => $message] + $extra, $status);
        }

        return back()->with($ok ? 'success' : 'error', $message);
    }
}
