<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\UserDevice;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class DeviceController extends Controller
{
    /**
     * Get current user's registered devices
     */
    public function myDevices(): JsonResponse
    {
        $user = auth()->user();

        $devices = $user->devices()
            ->orderBy('is_primary', 'desc')
            ->orderBy('last_used_at', 'desc')
            ->get()
            ->map(function ($device) {
                return [
                    'id' => $device->id,
                    'device_id' => $device->device_id,
                    'device_name' => $device->formatted_name,
                    'device_model' => $device->device_model,
                    'device_brand' => $device->device_brand,
                    'os_version' => $device->os_version,
                    'app_version' => $device->app_version,
                    'status' => $device->status,
                    'status_label' => $device->status_label,
                    'is_primary' => $device->is_primary,
                    'last_used_at' => $device->last_used_at?->toIso8601String(),
                    'created_at' => $device->created_at->toIso8601String(),
                ];
            });

        $company = $user->company;

        return response()->json([
            'success' => true,
            'data' => [
                'devices' => $devices,
                'max_devices' => $company?->max_devices_per_user ?? 3,
                'device_validation_enabled' => $company?->device_validation_enabled ?? false,
                'allow_editable_location' => $company?->allow_editable_location ?? true,
            ],
        ]);
    }

    /**
     * Register a new device for the user
     * Called automatically during check-in/check-out
     */
    public function register(Request $request): JsonResponse
    {
        $request->validate([
            'device_id' => 'required|string',
            'device_model' => 'nullable|string',
            'device_brand' => 'nullable|string',
            'os_version' => 'nullable|string',
            'app_version' => 'nullable|string',
        ]);

        $user = auth()->user();
        $company = $user->company;
        $maxDevices = $company?->max_devices_per_user ?? 3;

        $result = UserDevice::registerDevice(
            $user->id,
            $request->device_id,
            [
                'device_model' => $request->device_model,
                'device_brand' => $request->device_brand,
                'os_version' => $request->os_version,
                'app_version' => $request->app_version,
            ],
            $maxDevices
        );

        if (isset($result['error'])) {
            return response()->json([
                'success' => false,
                'message' => $result['message'],
                'error_code' => $result['error'],
            ], 400);
        }

        $device = $result['device'];

        return response()->json([
            'success' => true,
            'message' => $result['is_new']
                ? 'Device baru terdaftar dan menunggu persetujuan admin'
                : 'Device sudah terdaftar',
            'data' => [
                'device' => [
                    'id' => $device->id,
                    'device_id' => $device->device_id,
                    'device_name' => $device->formatted_name,
                    'status' => $device->status,
                    'status_label' => $device->status_label,
                    'is_primary' => $device->is_primary,
                ],
                'is_new' => $result['is_new'],
                'needs_approval' => $result['needs_approval'],
            ],
        ]);
    }

    /**
     * Remove a device from user's registered devices
     */
    public function remove(Request $request, int $deviceId): JsonResponse
    {
        $user = auth()->user();

        $device = $user->devices()->find($deviceId);

        if (!$device) {
            return response()->json([
                'success' => false,
                'message' => 'Device tidak ditemukan',
            ], 404);
        }

        // Cannot remove primary device if it's the only approved device
        if ($device->is_primary && $device->isApproved()) {
            $otherApproved = $user->approvedDevices()->where('id', '!=', $deviceId)->count();
            if ($otherApproved === 0) {
                return response()->json([
                    'success' => false,
                    'message' => 'Tidak dapat menghapus device utama. Setidaknya harus ada 1 device aktif.',
                ], 400);
            }
        }

        $device->delete();

        return response()->json([
            'success' => true,
            'message' => 'Device berhasil dihapus',
        ]);
    }

    /**
     * Set a device as primary
     */
    public function setPrimary(Request $request, int $deviceId): JsonResponse
    {
        $user = auth()->user();

        $device = $user->devices()->find($deviceId);

        if (!$device) {
            return response()->json([
                'success' => false,
                'message' => 'Device tidak ditemukan',
            ], 404);
        }

        if (!$device->isApproved()) {
            return response()->json([
                'success' => false,
                'message' => 'Hanya device yang sudah disetujui yang dapat dijadikan device utama',
            ], 400);
        }

        $device->setAsPrimary();

        return response()->json([
            'success' => true,
            'message' => 'Device berhasil dijadikan device utama',
        ]);
    }

    /**
     * Check device status - called before check-in/check-out
     * Returns whether device is valid for attendance
     */
    public function checkStatus(Request $request): JsonResponse
    {
        $request->validate([
            'device_id' => 'required|string',
        ]);

        $user = auth()->user();
        $company = $user->company;
        $deviceValidationEnabled = $company?->device_validation_enabled ?? false;
        $allowEditable = $company?->allow_editable_location ?? true;

        // If device validation is disabled, allow all
        if (!$deviceValidationEnabled) {
            return response()->json([
                'success' => true,
                'data' => [
                    'can_checkin' => true,
                    'device_validation_enabled' => false,
                    'message' => 'Validasi device tidak aktif',
                ],
            ]);
        }

        // Super admin is exempt from device validation
        $isSuperAdmin = $user->hasRole('super_admin');

        // Check if device is registered by another user
        $deviceUsedByOther = UserDevice::where('device_id', $request->device_id)
            ->where('user_id', '!=', $user->id)
            ->whereIn('status', [UserDevice::STATUS_APPROVED, UserDevice::STATUS_PENDING])
            ->with('user')
            ->first();

        if ($deviceUsedByOther && !$isSuperAdmin) {
            return response()->json([
                'success' => true,
                'data' => [
                    'can_checkin' => false,
                    'device_registered' => false,
                    'device_approved' => false,
                    'device_used_by_other' => true,
                    'allow_editable' => $allowEditable,
                    'message' => 'Device ini sudah terdaftar oleh user lain. Satu device hanya dapat digunakan oleh satu user.',
                ],
            ]);
        }

        $device = UserDevice::where('user_id', $user->id)
            ->where('device_id', $request->device_id)
            ->first();

        // Device not registered for this user
        if (!$device) {
            // If editable=true, allow but with warning
            if ($allowEditable) {
                return response()->json([
                    'success' => true,
                    'data' => [
                        'can_checkin' => true,
                        'device_registered' => false,
                        'device_approved' => false,
                        'allow_editable' => true,
                        'use_registered_device_info' => true,
                        'message' => 'Device tidak terdaftar. Absensi akan menggunakan info device terdaftar.',
                        'registered_device' => $this->getRegisteredDeviceInfo($user),
                    ],
                ]);
            }

            // If editable=false, reject
            return response()->json([
                'success' => true,
                'data' => [
                    'can_checkin' => false,
                    'device_registered' => false,
                    'device_approved' => false,
                    'allow_editable' => false,
                    'message' => 'Device tidak terdaftar. Silakan gunakan device yang sudah terdaftar.',
                ],
            ]);
        }

        // Device registered but pending
        if ($device->isPending()) {
            if ($allowEditable) {
                return response()->json([
                    'success' => true,
                    'data' => [
                        'can_checkin' => true,
                        'device_registered' => true,
                        'device_approved' => false,
                        'device_status' => 'pending',
                        'allow_editable' => true,
                        'use_registered_device_info' => true,
                        'message' => 'Device menunggu persetujuan. Absensi akan menggunakan info device yang sudah disetujui.',
                        'registered_device' => $this->getRegisteredDeviceInfo($user),
                    ],
                ]);
            }

            return response()->json([
                'success' => true,
                'data' => [
                    'can_checkin' => false,
                    'device_registered' => true,
                    'device_approved' => false,
                    'device_status' => 'pending',
                    'allow_editable' => false,
                    'message' => 'Device masih menunggu persetujuan admin.',
                ],
            ]);
        }

        // Device registered and approved
        if ($device->isApproved()) {
            return response()->json([
                'success' => true,
                'data' => [
                    'can_checkin' => true,
                    'device_registered' => true,
                    'device_approved' => true,
                    'device_status' => 'approved',
                    'allow_editable' => $allowEditable,
                    'use_registered_device_info' => false,
                    'message' => 'Device valid',
                    'device' => [
                        'id' => $device->id,
                        'device_name' => $device->formatted_name,
                        'is_primary' => $device->is_primary,
                    ],
                ],
            ]);
        }

        // Device rejected
        return response()->json([
            'success' => true,
            'data' => [
                'can_checkin' => false,
                'device_registered' => true,
                'device_approved' => false,
                'device_status' => 'rejected',
                'allow_editable' => $allowEditable,
                'message' => 'Device ditolak: ' . ($device->rejection_reason ?? 'Tidak ada alasan'),
            ],
        ]);
    }

    /**
     * Get info of first approved/registered device for the user
     */
    private function getRegisteredDeviceInfo(User $user): ?array
    {
        // Priority: primary device > first approved > first any
        $device = $user->primaryDevice
            ?? $user->approvedDevices()->first()
            ?? $user->devices()->first();

        if (!$device) {
            return null;
        }

        return [
            'device_model' => $device->device_model,
            'device_brand' => $device->device_brand,
            'os_version' => $device->os_version,
            'app_version' => $device->app_version,
            'device_name' => $device->formatted_name,
        ];
    }

    // ==================== ADMIN ENDPOINTS ====================

    /**
     * Get all pending device approvals (Admin only)
     */
    public function pendingApprovals(): JsonResponse
    {
        $user = auth()->user();

        if (!$user->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $query = UserDevice::with(['user', 'user.company'])
            ->pending()
            // Hide super_admin from pending approvals (using Spatie roles)
            ->whereHas('user', function ($q) {
                $q->whereDoesntHave('roles', function ($r) {
                    $r->where('name', 'super_admin');
                });
            })
            ->orderBy('created_at', 'asc');

        // Admin can only see users from their company
        if ($user->hasRole('admin') && !$user->hasRole('super_admin')) {
            $query->whereHas('user', function ($q) use ($user) {
                $q->where('company_id', $user->company_id)
                    ->whereDoesntHave('roles', function ($r) {
                        $r->where('name', 'super_admin');
                    });
            });
        }

        $devices = $query->get()->map(function ($device) {
            return [
                'id' => $device->id,
                'user' => [
                    'id' => $device->user->id,
                    'name' => $device->user->name,
                    'employee_id' => $device->user->employee_id,
                    'department' => $device->user->department,
                    'company' => $device->user->company?->name,
                ],
                'device_id' => $device->device_id,
                'device_name' => $device->formatted_name,
                'device_model' => $device->device_model,
                'device_brand' => $device->device_brand,
                'os_version' => $device->os_version,
                'app_version' => $device->app_version,
                'created_at' => $device->created_at->toIso8601String(),
                'existing_devices_count' => $device->user->approvedDevices()->count(),
            ];
        });

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

    /**
     * Approve a device (Admin only)
     */
    public function approve(Request $request, int $deviceId): JsonResponse
    {
        $user = auth()->user();

        if (!$user->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $device = UserDevice::with('user')->find($deviceId);

        if (!$device) {
            return response()->json([
                'success' => false,
                'message' => 'Device tidak ditemukan',
            ], 404);
        }

        // Admin can only approve users from their company
        if ($user->hasRole('admin') && !$user->hasRole('super_admin')) {
            if ($device->user->company_id !== $user->company_id) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized - Device milik company lain',
                ], 403);
            }
        }

        if ($device->isApproved()) {
            return response()->json([
                'success' => false,
                'message' => 'Device sudah disetujui',
            ], 400);
        }

        $device->approve($user->id);

        return response()->json([
            'success' => true,
            'message' => 'Device berhasil disetujui',
            'data' => [
                'device_id' => $device->id,
                'user_name' => $device->user->name,
                'device_name' => $device->formatted_name,
            ],
        ]);
    }

    /**
     * Reject a device (Admin only)
     */
    public function reject(Request $request, int $deviceId): JsonResponse
    {
        $request->validate([
            'reason' => 'nullable|string|max:500',
        ]);

        $user = auth()->user();

        if (!$user->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $device = UserDevice::with('user')->find($deviceId);

        if (!$device) {
            return response()->json([
                'success' => false,
                'message' => 'Device tidak ditemukan',
            ], 404);
        }

        // Admin can only reject users from their company
        if ($user->hasRole('admin') && !$user->hasRole('super_admin')) {
            if ($device->user->company_id !== $user->company_id) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized - Device milik company lain',
                ], 403);
            }
        }

        $device->reject($user->id, $request->reason);

        return response()->json([
            'success' => true,
            'message' => 'Device berhasil ditolak',
            'data' => [
                'device_id' => $device->id,
                'user_name' => $device->user->name,
                'device_name' => $device->formatted_name,
            ],
        ]);
    }

    /**
     * Get all devices for a specific user (Admin only)
     */
    public function userDevices(int $userId): JsonResponse
    {
        $authUser = auth()->user();

        if (!$authUser->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $targetUser = User::find($userId);

        if (!$targetUser) {
            return response()->json([
                'success' => false,
                'message' => 'User tidak ditemukan',
            ], 404);
        }

        // Admin can only see users from their company
        if ($authUser->hasRole('admin') && !$authUser->hasRole('super_admin')) {
            if ($targetUser->company_id !== $authUser->company_id) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized - User milik company lain',
                ], 403);
            }
        }

        $devices = $targetUser->devices()
            ->with('approver')
            ->orderBy('is_primary', 'desc')
            ->orderBy('status', 'asc')
            ->get()
            ->map(function ($device) {
                return [
                    'id' => $device->id,
                    'device_id' => $device->device_id,
                    'device_name' => $device->formatted_name,
                    'device_model' => $device->device_model,
                    'device_brand' => $device->device_brand,
                    'os_version' => $device->os_version,
                    'app_version' => $device->app_version,
                    'status' => $device->status,
                    'status_label' => $device->status_label,
                    'is_primary' => $device->is_primary,
                    'approved_by' => $device->approver?->name,
                    'approved_at' => $device->approved_at?->toIso8601String(),
                    'rejection_reason' => $device->rejection_reason,
                    'last_used_at' => $device->last_used_at?->toIso8601String(),
                    'created_at' => $device->created_at->toIso8601String(),
                ];
            });

        return response()->json([
            'success' => true,
            'data' => [
                'user' => [
                    'id' => $targetUser->id,
                    'name' => $targetUser->name,
                    'employee_id' => $targetUser->employee_id,
                ],
                'devices' => $devices,
            ],
        ]);
    }

    /**
     * Admin removes a device from a user
     */
    public function adminRemove(int $deviceId): JsonResponse
    {
        $authUser = auth()->user();

        if (!$authUser->hasRole(['admin', 'super_admin'])) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $device = UserDevice::with('user')->find($deviceId);

        if (!$device) {
            return response()->json([
                'success' => false,
                'message' => 'Device tidak ditemukan',
            ], 404);
        }

        // Admin can only remove devices from their company
        if ($authUser->hasRole('admin') && !$authUser->hasRole('super_admin')) {
            if ($device->user->company_id !== $authUser->company_id) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized - Device milik company lain',
                ], 403);
            }
        }

        $userName = $device->user->name;
        $deviceName = $device->formatted_name;

        $device->delete();

        return response()->json([
            'success' => true,
            'message' => "Device {$deviceName} milik {$userName} berhasil dihapus",
        ]);
    }

    /**
     * Migrate device from old ID format to new Installation UUID format
     * This is called when app updates and device ID format changes
     */
    public function migrate(Request $request): JsonResponse
    {
        $request->validate([
            'old_device_id' => 'required|string',
            'new_device_id' => 'required|string',
            'device_model' => 'nullable|string',
            'device_brand' => 'nullable|string',
            'os_version' => 'nullable|string',
            'app_version' => 'nullable|string',
        ]);

        $user = auth()->user();
        $oldDeviceId = $request->old_device_id;
        $newDeviceId = $request->new_device_id;

        // Check if old_device_id and new_device_id are the same (no migration needed)
        if ($oldDeviceId === $newDeviceId) {
            return response()->json([
                'success' => true,
                'message' => 'Device ID tidak berubah, tidak perlu migrasi',
                'data' => [
                    'migrated' => false,
                    'reason' => 'same_id',
                ],
            ]);
        }

        // Check if new device ID already exists for this user (already migrated)
        $existingNewDevice = UserDevice::where('user_id', $user->id)
            ->where('device_id', $newDeviceId)
            ->first();

        if ($existingNewDevice) {
            // Already migrated, just update device info
            $existingNewDevice->update([
                'device_model' => $request->device_model ?? $existingNewDevice->device_model,
                'device_brand' => $request->device_brand ?? $existingNewDevice->device_brand,
                'os_version' => $request->os_version ?? $existingNewDevice->os_version,
                'app_version' => $request->app_version ?? $existingNewDevice->app_version,
                'last_used_at' => now(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Device sudah termigrasi sebelumnya',
                'data' => [
                    'migrated' => false,
                    'reason' => 'already_migrated',
                    'device' => [
                        'id' => $existingNewDevice->id,
                        'device_id' => $existingNewDevice->device_id,
                        'status' => $existingNewDevice->status,
                    ],
                ],
            ]);
        }

        // Find old device for this user
        $oldDevice = UserDevice::where('user_id', $user->id)
            ->where('device_id', $oldDeviceId)
            ->first();

        if ($oldDevice) {
            // Migrate: update old device with new device ID
            $oldDevice->update([
                'device_id' => $newDeviceId,
                'device_model' => $request->device_model ?? $oldDevice->device_model,
                'device_brand' => $request->device_brand ?? $oldDevice->device_brand,
                'os_version' => $request->os_version ?? $oldDevice->os_version,
                'app_version' => $request->app_version ?? $oldDevice->app_version,
                'last_used_at' => now(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Device berhasil dimigrasi ke format ID baru',
                'data' => [
                    'migrated' => true,
                    'old_device_id' => $oldDeviceId,
                    'new_device_id' => $newDeviceId,
                    'device' => [
                        'id' => $oldDevice->id,
                        'device_id' => $oldDevice->device_id,
                        'status' => $oldDevice->status,
                        'is_primary' => $oldDevice->is_primary,
                    ],
                ],
            ]);
        }

        // Old device not found - this could be a new device
        // Don't auto-register here, let the normal flow handle it
        return response()->json([
            'success' => true,
            'message' => 'Device lama tidak ditemukan, tidak ada yang perlu dimigrasi',
            'data' => [
                'migrated' => false,
                'reason' => 'old_device_not_found',
            ],
        ]);
    }
}
