<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class UserDevice extends Model
{
    use HasFactory;

    /**
     * Disable auto timestamps for manual override capability
     */
    public $timestamps = false;

    protected $fillable = [
        'user_id',
        'device_id',
        'device_model',
        'device_brand',
        'os_version',
        'app_version',
        'device_name',
        'status',
        'approved_by',
        'approved_at',
        'rejection_reason',
        'last_used_at',
        'is_primary',
        'created_at',
        'updated_at',
    ];

    protected function casts(): array
    {
        return [
            'approved_at' => 'datetime',
            'last_used_at' => 'datetime',
            'is_primary' => 'boolean',
            'created_at' => 'datetime',
            'updated_at' => 'datetime',
        ];
    }

    /**
     * Boot method untuk handle timestamps
     */
    protected static function booted()
    {
        static::creating(function ($device) {
            $now = now();
            if (!$device->created_at) {
                $device->created_at = $now;
            }
            if (!$device->updated_at) {
                $device->updated_at = $device->created_at;
            }
        });

        static::updating(function ($device) {
            if (!$device->isDirty('updated_at')) {
                $device->updated_at = now();
            }
        });
    }

    // Status constants
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';

    /**
     * Get the user that owns the device
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the admin who approved/rejected this device
     */
    public function approver(): BelongsTo
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    /**
     * Scope for approved devices
     */
    public function scopeApproved($query)
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    /**
     * Scope for pending devices
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Check if device is approved
     */
    public function isApproved(): bool
    {
        return $this->status === self::STATUS_APPROVED;
    }

    /**
     * Check if device is pending
     */
    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * Approve this device
     */
    public function approve(int $approverId): bool
    {
        $this->status = self::STATUS_APPROVED;
        $this->approved_by = $approverId;
        $this->approved_at = now();
        $this->rejection_reason = null;

        return $this->save();
    }

    /**
     * Reject this device
     */
    public function reject(int $approverId, ?string $reason = null): bool
    {
        $this->status = self::STATUS_REJECTED;
        $this->approved_by = $approverId;
        $this->approved_at = now();
        $this->rejection_reason = $reason;

        return $this->save();
    }

    /**
     * Update last used timestamp
     */
    public function markAsUsed(): bool
    {
        $this->last_used_at = now();
        return $this->save();
    }

    /**
     * Set as primary device (unset others)
     */
    public function setAsPrimary(): bool
    {
        // Unset other primary devices for this user
        self::where('user_id', $this->user_id)
            ->where('id', '!=', $this->id)
            ->update(['is_primary' => false]);

        $this->is_primary = true;
        return $this->save();
    }

    /**
     * Get formatted device name
     */
    public function getFormattedNameAttribute(): string
    {
        if ($this->device_name) {
            return $this->device_name;
        }

        $parts = array_filter([
            $this->device_brand,
            $this->device_model,
        ]);

        return implode(' ', $parts) ?: 'Unknown Device';
    }

    /**
     * Get status label in Indonesian
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_PENDING => 'Menunggu Persetujuan',
            self::STATUS_APPROVED => 'Disetujui',
            self::STATUS_REJECTED => 'Ditolak',
            default => $this->status,
        };
    }

    /**
     * Register or get existing device for a user
     * Returns the device and a flag indicating if it's new
     */
    public static function registerDevice(
        int $userId,
        string $deviceId,
        array $deviceInfo = [],
        int $maxDevices = 3
    ): array {
        $user = User::find($userId);

        // Check if device already registered for this user
        $existingDevice = self::where('user_id', $userId)
            ->where('device_id', $deviceId)
            ->first();

        if ($existingDevice) {
            // Update device info and last used
            $existingDevice->update([
                'device_model' => $deviceInfo['device_model'] ?? $existingDevice->device_model,
                'device_brand' => $deviceInfo['device_brand'] ?? $existingDevice->device_brand,
                'os_version' => $deviceInfo['os_version'] ?? $existingDevice->os_version,
                'app_version' => $deviceInfo['app_version'] ?? $existingDevice->app_version,
                'last_used_at' => now(),
            ]);

            return [
                'device' => $existingDevice->fresh(),
                'is_new' => false,
                'needs_approval' => $existingDevice->isPending(),
            ];
        }

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

        if ($deviceUsedByOther) {
            return [
                'device' => null,
                'is_new' => false,
                'needs_approval' => false,
                'error' => 'device_used_by_other',
                'message' => 'Device ini sudah terdaftar oleh user lain. Satu device hanya dapat digunakan oleh satu user.',
            ];
        }

        // Check if user already has max devices
        $currentDeviceCount = self::where('user_id', $userId)
            ->whereIn('status', [self::STATUS_APPROVED, self::STATUS_PENDING])
            ->count();

        if ($currentDeviceCount >= $maxDevices) {
            return [
                'device' => null,
                'is_new' => false,
                'needs_approval' => false,
                'error' => 'max_devices_reached',
                'message' => "Maksimal {$maxDevices} device per user. Hapus device lama untuk menambah yang baru.",
            ];
        }

        // Create new device
        $deviceName = trim(($deviceInfo['device_brand'] ?? '') . ' ' . ($deviceInfo['device_model'] ?? ''));

        $newDevice = self::create([
            'user_id' => $userId,
            'device_id' => $deviceId,
            'device_model' => $deviceInfo['device_model'] ?? null,
            'device_brand' => $deviceInfo['device_brand'] ?? null,
            'os_version' => $deviceInfo['os_version'] ?? null,
            'app_version' => $deviceInfo['app_version'] ?? null,
            'device_name' => $deviceName ?: null,
            'status' => self::STATUS_PENDING,
            'last_used_at' => now(),
            // First device is primary by default
            'is_primary' => $currentDeviceCount === 0,
        ]);

        return [
            'device' => $newDevice,
            'is_new' => true,
            'needs_approval' => true,
        ];
    }

    /**
     * Get device info for backdate attendance
     * Returns device info from user's registered device, or default values
     * This ensures backdate attendance has consistent device info
     */
    public static function getDeviceInfoForBackdate(int $userId): array
    {
        // Priority: primary device > first approved > first any
        $device = self::where('user_id', $userId)
            ->where('is_primary', true)
            ->first();

        if (!$device) {
            $device = self::where('user_id', $userId)
                ->where('status', self::STATUS_APPROVED)
                ->first();
        }

        if (!$device) {
            $device = self::where('user_id', $userId)->first();
        }

        if ($device) {
            return [
                'device_model' => $device->device_model,
                'device_brand' => $device->device_brand,
                'os_version' => $device->os_version,
                'app_version' => $device->app_version,
            ];
        }

        // Default device info jika user belum punya device
        return [
            'device_model' => 'Android',
            'device_brand' => 'Samsung',
            'os_version' => 'Android 14',
            'app_version' => '1.0.0',
        ];
    }

}
