<?php

namespace App\Services;

use App\Models\QrAttendanceLog;
use App\Models\User;

class QrAttendanceService
{
    public function __construct(
        protected QrCardService $qrCardService,
        protected AttendanceService $attendanceService
    ) {}

    /**
     * Process QR scan for attendance.
     *
     * @return array{success: bool, message: string, data?: array}
     */
    public function processQrScan(
        string $qrData,
        User $scanner,
        string $scanType,
        float $latitude,
        float $longitude,
        array $deviceInfo = []
    ): array {
        // Verify scanner has admin role
        if (!$scanner->hasRole(['admin', 'super_admin'])) {
            return [
                'success' => false,
                'message' => 'Hanya admin yang dapat melakukan scan QR',
            ];
        }

        // Verify company has QR scanner enabled
        if (!$scanner->company->qr_scanner_enabled) {
            return [
                'success' => false,
                'message' => 'Fitur QR Scanner tidak diaktifkan untuk perusahaan Anda',
            ];
        }

        // Parse and validate QR
        $validation = $this->qrCardService->parseAndValidateQr($qrData);

        if (!$validation['valid']) {
            $this->logScan(
                scanner: $scanner,
                scannedUser: null,
                scanType: $scanType,
                latitude: $latitude,
                longitude: $longitude,
                status: 'failed',
                failureReason: $validation['error'],
                deviceInfo: $deviceInfo
            );

            return [
                'success' => false,
                'message' => $validation['error'],
            ];
        }

        $scannedUser = $validation['user'];
        $company = $validation['company'];

        // Verify same company
        if ($scannedUser->company_id !== $scanner->company_id) {
            $this->logScan(
                scanner: $scanner,
                scannedUser: $scannedUser,
                scanType: $scanType,
                latitude: $latitude,
                longitude: $longitude,
                status: 'failed',
                failureReason: 'Karyawan bukan dari perusahaan yang sama',
                deviceInfo: $deviceInfo
            );

            return [
                'success' => false,
                'message' => 'Karyawan tidak terdaftar di perusahaan Anda',
            ];
        }

        // Process attendance
        $result = $this->processAttendance(
            user: $scannedUser,
            scanType: $scanType,
            latitude: $latitude,
            longitude: $longitude,
            deviceInfo: $deviceInfo,
            notes: ($scanType === 'check_in' ? 'Check-in' : 'Check-out') . ' via QR Scanner oleh ' . $scanner->name,
            scannedBy: $scanner->id
        );

        // Log the scan
        $this->logScan(
            scanner: $scanner,
            scannedUser: $scannedUser,
            scanType: $scanType,
            latitude: $latitude,
            longitude: $longitude,
            status: $result['success'] ? 'success' : 'failed',
            failureReason: $result['success'] ? null : $result['message'],
            deviceInfo: $deviceInfo,
            attendanceId: $result['data']['id'] ?? null
        );

        if ($result['success']) {
            // Use timezone-naive format so mobile parses it as local time
            $scannedAt = now()->timezone('Asia/Jakarta')->format('Y-m-d\TH:i:s');

            return [
                'success' => true,
                'message' => $result['message'],
                'data' => [
                    'attendance' => $result['data'] ?? null,
                    'user' => [
                        'id' => $scannedUser->id,
                        'name' => $scannedUser->name,
                        'employee_id' => $scannedUser->employee_id,
                        'department' => $scannedUser->department,
                        'position' => $scannedUser->position,
                        'avatar' => $scannedUser->avatar,
                    ],
                    'scan_type' => $scanType,
                    'scanned_at' => $scannedAt,
                ],
            ];
        }

        return $result;
    }

    /**
     * Process attendance check-in or check-out.
     */
    protected function processAttendance(
        User $user,
        string $scanType,
        float $latitude,
        float $longitude,
        array $deviceInfo,
        string $notes = null,
        ?int $scannedBy = null
    ): array {
        if ($scanType === 'check_in') {
            return $this->attendanceService->checkIn(
                user: $user,
                latitude: $latitude,
                longitude: $longitude,
                address: null,
                notes: $notes,
                type: 'office',
                deviceInfo: $deviceInfo,
                scannedBy: $scannedBy
            );
        } else {
            return $this->attendanceService->checkOut(
                user: $user,
                latitude: $latitude,
                longitude: $longitude,
                address: null,
                notes: $notes,
                checkoutTime: null,
                deviceInfo: $deviceInfo,
                scannedBy: $scannedBy
            );
        }
    }

    /**
     * Log QR scan attempt.
     */
    protected function logScan(
        User $scanner,
        ?User $scannedUser,
        string $scanType,
        float $latitude,
        float $longitude,
        string $status,
        ?string $failureReason,
        array $deviceInfo,
        ?string $attendanceId = null
    ): QrAttendanceLog {
        return QrAttendanceLog::create([
            'scanned_user_id' => $scannedUser?->id,
            'scanner_user_id' => $scanner->id,
            'company_id' => $scanner->company_id,
            'attendance_id' => $attendanceId,
            'scan_type' => $scanType,
            'latitude' => $latitude,
            'longitude' => $longitude,
            'scan_status' => $status,
            'failure_reason' => $failureReason,
            'device_info' => $deviceInfo,
            'scanned_at' => now(),
        ]);
    }

    /**
     * Get scan history for a company.
     */
    public function getScanHistory(int $companyId, array $filters = []): \Illuminate\Database\Eloquent\Collection
    {
        $query = QrAttendanceLog::where('company_id', $companyId)
            ->with(['scannedUser', 'scannerUser', 'attendance'])
            ->orderBy('scanned_at', 'desc');

        if (isset($filters['date'])) {
            $query->whereDate('scanned_at', $filters['date']);
        }

        if (isset($filters['scanner_id'])) {
            $query->where('scanner_user_id', $filters['scanner_id']);
        }

        if (isset($filters['status'])) {
            $query->where('scan_status', $filters['status']);
        }

        if (isset($filters['scan_type'])) {
            $query->where('scan_type', $filters['scan_type']);
        }

        if (isset($filters['limit'])) {
            $query->limit($filters['limit']);
        }

        return $query->get();
    }

    /**
     * Get scan statistics for a company.
     */
    public function getScanStatistics(int $companyId, string $period = 'today'): array
    {
        $query = QrAttendanceLog::where('company_id', $companyId);

        switch ($period) {
            case 'today':
                $query->whereDate('scanned_at', today());
                break;
            case 'week':
                $query->whereBetween('scanned_at', [now()->startOfWeek(), now()->endOfWeek()]);
                break;
            case 'month':
                $query->whereMonth('scanned_at', now()->month)
                    ->whereYear('scanned_at', now()->year);
                break;
        }

        $total = $query->count();
        $successful = (clone $query)->where('scan_status', 'success')->count();
        $failed = (clone $query)->where('scan_status', 'failed')->count();
        $checkIns = (clone $query)->where('scan_type', 'check_in')->where('scan_status', 'success')->count();
        $checkOuts = (clone $query)->where('scan_type', 'check_out')->where('scan_status', 'success')->count();

        return [
            'total_scans' => $total,
            'successful' => $successful,
            'failed' => $failed,
            'check_ins' => $checkIns,
            'check_outs' => $checkOuts,
            'success_rate' => $total > 0 ? round(($successful / $total) * 100, 2) : 0,
        ];
    }
}
