<?php

namespace App\Http\Controllers;

use App\Models\SmartCard;
use App\Models\SmartAttendance;
use App\Models\AttendanceDevice;
use App\Models\AttendanceLog;
use App\Models\Student;
use App\Models\Teacher;
use App\Models\Classes;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Barryvdh\DomPDF\Facade\Pdf;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class SmartAttendanceController extends Controller
{
    /**
     * Display attendance dashboard
     */
    public function index()
    {
        $today = now()->toDateString();
        
        $stats = [
            'total_students' => Student::count(),
            'total_teachers' => Teacher::count(),
            'present_today' => SmartAttendance::whereDate('attendance_date', $today)
                                              ->where('status', 'present')
                                              ->count(),
            'late_today' => SmartAttendance::whereDate('attendance_date', $today)
                                           ->where('status', 'late')
                                           ->count(),
            'absent_today' => SmartAttendance::whereDate('attendance_date', $today)
                                            ->where('status', 'absent')
                                            ->count(),
            'active_cards' => SmartCard::where('status', 'active')->count(),
            'online_devices' => AttendanceDevice::where('status', 'online')->count()
        ];

        $recentAttendances = SmartAttendance::with('student', 'teacher', 'card')
                                           ->whereDate('attendance_date', $today)
                                           ->orderBy('check_in_time', 'desc')
                                           ->limit(20)
                                           ->get();

        // ফিক্স করা অংশ: SQL query দিয়ে ক্লাস ভিত্তিক উপস্থিতি বের করা
        $classWiseAttendance = DB::select("
            SELECT 
                c.id as class_id,
                c.class_name_bn,
                c.section,
                COUNT(s.id) as total,
                (
                    SELECT COUNT(*) 
                    FROM smart_attendances sa 
                    WHERE sa.student_id IN (
                        SELECT id FROM students WHERE class_id = c.id
                    )
                    AND DATE(sa.attendance_date) = ?
                    AND sa.status = 'present'
                ) as present
            FROM classes c
            LEFT JOIN students s ON s.class_id = c.id
            WHERE c.status = 1
            GROUP BY c.id, c.class_name_bn, c.section
            ORDER BY c.class_name, c.section
        ", [$today]);

        $devices = AttendanceDevice::all();

        return view('attendance.index', compact('stats', 'recentAttendances', 'classWiseAttendance', 'devices'));
    }

    /**
     * Process card scan (API endpoint for devices)
     */
    public function processCardScan(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'device_id' => 'required|exists:attendance_devices,id',
            'card_uid' => 'required|string',
            'event_type' => 'required|in:check_in,check_out',
            'event_time' => 'required|date',
            'temperature' => 'nullable|numeric|min:30|max:45'
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        DB::beginTransaction();

        try {
            // Log the event
            $log = AttendanceLog::create([
                'device_id' => $request->device_id,
                'card_uid' => $request->card_uid,
                'event_type' => $request->event_type,
                'event_time' => $request->event_time,
                'temperature' => $request->temperature,
                'raw_data' => $request->all(),
                'processed' => false
            ]);

            // Find card
            $card = SmartCard::where('card_uid', $request->card_uid)
                            ->where('status', 'active')
                            ->first();

            if (!$card) {
                $log->error_message = 'Invalid card';
                $log->save();
                
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid card',
                    'code' => 'INVALID_CARD'
                ], 404);
            }

            // Check if card is valid
            if (!$card->isValid()) {
                $log->error_message = 'Card expired or inactive';
                $log->save();
                
                return response()->json([
                    'success' => false,
                    'message' => 'Card is not active',
                    'code' => 'CARD_INACTIVE'
                ], 403);
            }

            // Process attendance
            $attendance = $this->processAttendance($card, $request);

            $log->processed = true;
            $log->save();

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Attendance recorded successfully',
                'data' => [
                    'name' => $card->student ? $card->student->name_bn : ($card->teacher ? $card->teacher->name_bn : 'Unknown'),
                    'type' => $card->card_type,
                    'check_in_time' => $attendance->check_in_time ? $attendance->check_in_time->format('h:i A') : null,
                    'check_out_time' => $attendance->check_out_time ? $attendance->check_out_time->format('h:i A') : null,
                    'status' => $attendance->status
                ]
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            \Log::error('Attendance processing failed: ' . $e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Internal server error',
                'code' => 'SERVER_ERROR'
            ], 500);
        }
    }

    /**
     * Process attendance record
     */
    private function processAttendance($card, $request)
    {
        $today = now()->toDateString();

        // Find existing attendance for today
        $attendance = SmartAttendance::where('card_id', $card->id)
                                     ->whereDate('attendance_date', $today)
                                     ->first();

        if (!$attendance) {
            // Create new attendance record
            $attendance = new SmartAttendance();
            $attendance->card_id = $card->id;
            $attendance->student_id = $card->student_id;
            $attendance->teacher_id = $card->teacher_id;
            $attendance->attendance_date = $today;
            
            if ($request->event_type == 'check_in') {
                $attendance->check_in_time = $request->event_time;
                $attendance->check_in_method = 'card';
                $attendance->check_in_device_id = $request->device_id;
                $attendance->status = $this->determineStatus($request->event_time);
            }
        } else {
            // Update existing attendance
            if ($request->event_type == 'check_out' && !$attendance->check_out_time) {
                $attendance->check_out_time = $request->event_time;
                $attendance->check_out_method = 'card';
                $attendance->check_out_device_id = $request->device_id;
                $attendance->working_hours = $this->calculateWorkingHours($attendance->check_in_time, $attendance->check_out_time);
            }
        }

        $attendance->temperature = $request->temperature;
        $attendance->save();

        return $attendance;
    }

    /**
     * Determine status based on check-in time
     */
    private function determineStatus($checkInTime)
    {
        $checkIn = \Carbon\Carbon::parse($checkInTime);
        $schoolStart = \Carbon\Carbon::parse($checkInTime->format('Y-m-d') . ' 09:00:00');
        
        if ($checkIn->gt($schoolStart->copy()->addMinutes(30))) {
            return 'late';
        }
        
        return 'present';
    }

    /**
     * Calculate working hours
     */
    private function calculateWorkingHours($checkIn, $checkOut)
    {
        if ($checkIn && $checkOut) {
            $checkIn = \Carbon\Carbon::parse($checkIn);
            $checkOut = \Carbon\Carbon::parse($checkOut);
            return round($checkIn->diffInMinutes($checkOut) / 60, 2);
        }
        return 0;
    }

    /**
     * Issue new smart card
     */
    public function issueCard(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'card_type' => 'required|in:student,teacher,staff',
            'student_id' => 'required_if:card_type,student|exists:students,id',
            'teacher_id' => 'required_if:card_type,teacher|exists:teachers,id',
            'expiry_date' => 'nullable|date|after:today'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            $data = [
                'card_uid' => SmartCard::generateCardUid(),
                'card_type' => $request->card_type,
                'student_id' => $request->student_id,
                'teacher_id' => $request->teacher_id,
                'issue_date' => now(),
                'expiry_date' => $request->expiry_date,
                'status' => 'active',
                'issued_by' => auth()->id()
            ];

            $card = SmartCard::create($data);

            // Generate QR code
            $qrCode = QrCode::size(200)
                            ->format('png')
                            ->generate($card->card_uid);

            // Store QR code
            $qrPath = 'uploads/cards/qr/' . $card->card_uid . '.png';
            file_put_contents(public_path($qrPath), $qrCode);

            return redirect()->route('attendance.cards')
                           ->with('success', 'স্মার্ট কার্ড ইস্যু করা হয়েছে')
                           ->with('card_uid', $card->card_uid);

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'কার্ড ইস্যু করতে সমস্যা হয়েছে');
        }
    }

    /**
     * Display cards list
     */
    public function cards(Request $request)
    {
        $query = SmartCard::with('student', 'teacher', 'issuer');

        if ($request->card_type) {
            $query->where('card_type', $request->card_type);
        }

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

        $cards = $query->orderBy('created_at', 'desc')->paginate(20);

        $cardTypes = SmartCard::getCardTypes();
        $statusTypes = SmartCard::getStatusTypes();

        return view('attendance.cards', compact('cards', 'cardTypes', 'statusTypes', 'request'));
    }

    /**
     * View card details
     */
    public function showCard($id)
    {
        $card = SmartCard::with('student', 'teacher', 'issuer', 'attendances')
                        ->findOrFail($id);

        return view('attendance.show-card', compact('card'));
    }

    /**
     * Update card status
     */
    public function updateCardStatus(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'status' => 'required|in:active,inactive,lost,damaged',
            'remarks' => 'nullable|string|max:255'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            $card = SmartCard::findOrFail($id);
            $card->status = $request->status;
            $card->remarks = $request->remarks;
            $card->save();

            return redirect()->route('attendance.cards.show', $card->id)
                           ->with('success', 'কার্ডের স্ট্যাটাস আপডেট করা হয়েছে');

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'স্ট্যাটাস আপডেট করতে সমস্যা হয়েছে');
        }
    }

    /**
     * Register attendance device
     */
    public function registerDevice(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'device_name' => 'required|string|max:255',
            'device_type' => 'required|in:rfid,fingerprint,face,qr',
            'model' => 'nullable|string|max:255',
            'serial_number' => 'nullable|string|unique:attendance_devices',
            'ip_address' => 'nullable|ip',
            'port' => 'nullable|integer|min:1|max:65535',
            'location' => 'required|string|max:255'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            $data = $request->all();
            $data['device_id'] = 'DEV-' . strtoupper(uniqid());
            $data['api_key'] = bin2hex(random_bytes(16));
            $data['secret_key'] = bin2hex(random_bytes(16));
            $data['created_by'] = auth()->id();

            $device = AttendanceDevice::create($data);

            return redirect()->route('attendance.devices')
                           ->with('success', 'ডিভাইস রেজিস্ট্রেশন সম্পন্ন হয়েছে');

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'ডিভাইস রেজিস্ট্রেশনে সমস্যা হয়েছে');
        }
    }

    /**
     * Display devices list
     */
    public function devices()
    {
        $devices = AttendanceDevice::with('creator')->get();
        $deviceTypes = AttendanceDevice::getDeviceTypes();

        return view('attendance.devices', compact('devices', 'deviceTypes'));
    }

    /**
     * Manual attendance entry
     */
    public function manualEntry(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'student_id' => 'required_without:teacher_id|exists:students,id',
            'teacher_id' => 'required_without:student_id|exists:teachers,id',
            'attendance_date' => 'required|date',
            'check_in_time' => 'required',
            'check_out_time' => 'nullable|after:check_in_time',
            'status' => 'required|in:present,absent,late,half-day'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            $attendance = new SmartAttendance();
            $attendance->student_id = $request->student_id;
            $attendance->teacher_id = $request->teacher_id;
            $attendance->attendance_date = $request->attendance_date;
            $attendance->check_in_time = $request->attendance_date . ' ' . $request->check_in_time;
            
            if ($request->check_out_time) {
                $attendance->check_out_time = $request->attendance_date . ' ' . $request->check_out_time;
            }
            
            $attendance->check_in_method = 'manual';
            $attendance->check_out_method = 'manual';
            $attendance->status = $request->status;
            $attendance->remarks = $request->remarks;
            $attendance->save();

            return redirect()->route('attendance.report')
                           ->with('success', 'হাজিরা সংরক্ষণ করা হয়েছে');

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'হাজিরা সংরক্ষণে সমস্যা হয়েছে');
        }
    }

    /**
     * Attendance report
     */
    public function report(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'from_date' => 'required|date',
            'to_date' => 'required|date|after_or_equal:from_date',
            'class_id' => 'nullable|exists:classes,id',
            'student_id' => 'nullable|exists:students,id'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator);
        }

        $query = SmartAttendance::with('student', 'teacher');

        if ($request->from_date) {
            $query->whereDate('attendance_date', '>=', $request->from_date);
        }

        if ($request->to_date) {
            $query->whereDate('attendance_date', '<=', $request->to_date);
        }

        if ($request->class_id) {
            $query->whereHas('student', function($q) use ($request) {
                $q->where('class_id', $request->class_id);
            });
        }

        if ($request->student_id) {
            $query->where('student_id', $request->student_id);
        }

        $attendances = $query->orderBy('attendance_date', 'desc')
                             ->orderBy('check_in_time', 'desc')
                             ->get();

        // Calculate summary
        $summary = [
            'total_days' => $attendances->groupBy('attendance_date')->count(),
            'present' => $attendances->where('status', 'present')->count(),
            'absent' => $attendances->where('status', 'absent')->count(),
            'late' => $attendances->where('status', 'late')->count(),
            'percentage' => $attendances->count() > 0 
                ? round(($attendances->where('status', 'present')->count() / $attendances->count()) * 100, 2) 
                : 0
        ];

        if ($request->has('download')) {
            $pdf = Pdf::loadView('attendance.report-pdf', compact('attendances', 'summary', 'request'));
            return $pdf->download('attendance_report_' . date('Y-m-d') . '.pdf');
        }

        return view('attendance.report', compact('attendances', 'summary', 'request'));
    }

    /**
     * Daily attendance sheet
     */
    public function dailySheet(Request $request)
    {
        $date = $request->date ?: today()->toDateString();
        $classId = $request->class_id;

        $students = Student::with('class')
                          ->where('status', 1)
                          ->when($classId, function($q) use ($classId) {
                              return $q->where('class_id', $classId);
                          })
                          ->orderBy('class_id')
                          ->orderBy('roll_number')
                          ->get();

        $attendances = SmartAttendance::whereDate('attendance_date', $date)
                                      ->get()
                                      ->keyBy('student_id');

        return view('attendance.daily-sheet', compact('students', 'attendances', 'date', 'classId'));
    }

    /**
     * Export attendance data
     */
    public function export(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'from_date' => 'required|date',
            'to_date' => 'required|date|after_or_equal:from_date',
            'format' => 'required|in:csv,excel,pdf'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator);
        }

        $attendances = SmartAttendance::with('student', 'teacher')
                                     ->whereBetween('attendance_date', [$request->from_date, $request->to_date])
                                     ->orderBy('attendance_date')
                                     ->orderBy('check_in_time')
                                     ->get();

        if ($request->format == 'csv') {
            return $this->exportCsv($attendances);
        } elseif ($request->format == 'excel') {
            return $this->exportExcel($attendances);
        } else {
            $pdf = Pdf::loadView('attendance.export-pdf', compact('attendances', 'request'));
            return $pdf->download('attendance_export_' . date('Y-m-d') . '.pdf');
        }
    }

    /**
     * Export to CSV
     */
    private function exportCsv($attendances)
    {
        $filename = 'attendance_' . date('Y-m-d') . '.csv';
        $handle = fopen('php://output', 'w');

        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename="' . $filename . '"');

        // Headers
        fputcsv($handle, ['তারিখ', 'নাম', 'আইডি', 'শ্রেণি', 'চেক ইন', 'চেক আউট', 'স্ট্যাটাস']);

        foreach ($attendances as $attendance) {
            fputcsv($handle, [
                $attendance->attendance_date->format('d-m-Y'),
                $attendance->student->name_bn ?? $attendance->teacher->name_bn ?? '',
                $attendance->student->student_id ?? $attendance->teacher->teacher_id ?? '',
                $attendance->student->class->class_name_bn ?? '',
                $attendance->check_in_time ? $attendance->check_in_time->format('h:i A') : '',
                $attendance->check_out_time ? $attendance->check_out_time->format('h:i A') : '',
                $attendance->status
            ]);
        }

        fclose($handle);
        exit;
    }

    /**
     * Export to Excel (simplified)
     */
    private function exportExcel($attendances)
    {
        // Implement Excel export using Maatwebsite\Excel
        // For now, redirect to CSV
        return $this->exportCsv($attendances);
    }

    /**
     * API: Get device status
     */
    public function deviceStatus($deviceId)
    {
        $device = AttendanceDevice::where('device_id', $deviceId)->first();

        if (!$device) {
            return response()->json(['error' => 'Device not found'], 404);
        }

        // Update last online
        $device->last_online = now();
        $device->save();

        return response()->json([
            'device_id' => $device->device_id,
            'status' => $device->status,
            'last_sync' => $device->last_sync,
            'time' => now()->toDateTimeString()
        ]);
    }

    /**
     * API: Sync attendance data
     */
    public function syncAttendance(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'device_id' => 'required|exists:attendance_devices,id',
            'attendances' => 'required|array',
            'attendances.*.card_uid' => 'required|string',
            'attendances.*.event_type' => 'required|in:check_in,check_out',
            'attendances.*.event_time' => 'required|date'
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $synced = 0;
        $failed = 0;

        foreach ($request->attendances as $data) {
            try {
                // Process each attendance
                $card = SmartCard::where('card_uid', $data['card_uid'])->first();

                if ($card && $card->isValid()) {
                    $this->processAttendance($card, new Request([
                        'device_id' => $request->device_id,
                        'card_uid' => $data['card_uid'],
                        'event_type' => $data['event_type'],
                        'event_time' => $data['event_time']
                    ]));
                    $synced++;
                } else {
                    $failed++;
                }
            } catch (\Exception $e) {
                $failed++;
            }
        }

        // Update device sync time
        $device = AttendanceDevice::find($request->device_id);
        $device->last_sync = now();
        $device->save();

        return response()->json([
            'success' => true,
            'synced' => $synced,
            'failed' => $failed
        ]);
    }
}