<?php

/**
 * ============================================================
 *
 * @project   biiproject
 *
 * @author    Andika Debi Putra
 *
 * @email     andikadebiputra@gmail.com
 *
 * @website   https://biiproject.com
 *
 * @copyright Copyright (c) 2026 Andika Debi Putra
 * @license   Proprietary - All Rights Reserved
 *
 * @version   1.0.0
 *
 * @created   2026-05-01
 * ============================================================
 *
 * Unauthorized copying, modification, distribution, or use
 * of this file is strictly prohibited without prior written
 * permission from the author.
 * ============================================================
 */

namespace App\Models;

use App\Notifications\Auth\ResetPasswordNotification;
use App\Notifications\Auth\VerifyEmailNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable as WebAuthnContract;
use Laragear\WebAuthn\WebAuthnAuthentication;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable implements HasMedia, WebAuthnContract
{
    use HasApiTokens, HasFactory, HasRoles, InteractsWithMedia, LogsActivity, Notifiable, SoftDeletes, WebAuthnAuthentication;

    protected string $guard_name = 'web';

    /**
     * Spatie Activitylog configuration
     */
    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->useLogName('user-management')
            ->logOnly(['name', 'username', 'email', 'phone_number', 'is_active'])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'name',
        'username',
        'email',
        'phone_number',
        'password',
        'google_id',
        'facebook_id',
        'github_id',
        'is_active',
        'password_changed_at',
        'last_session_id',
        'created_by',
        'updated_by',
    ];

    /**
     * Hidden fields
     */
    protected $hidden = [
        'password',
        'remember_token',
        'media', // Hide raw media relation
    ];

    /**
     * Appended attributes
     */
    protected $appends = ['avatar'];

    /**
     * Avatar Accessor (using Media Library)
     */
    public function getAvatarAttribute(): ?string
    {
        return $this->getFirstMediaUrl('avatar') ?: null;
    }

    /**
     * The attributes that should be cast.
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
        'is_active' => 'boolean',
        'password_changed_at' => 'datetime',
    ];

    /**
     * Password History Relation
     */
    public function passwordHistories()
    {
        return $this->hasMany(PasswordHistory::class);
    }

    /**
     * Trusted Devices Relation
     */
    public function trustedDevices()
    {
        return $this->hasMany(UserTrustedDevice::class);
    }

    /**
     * ==========================================
     * DISABLE RESET PASSWORD FOR SOCIAL USERS
     * ==========================================
     */
    public function sendPasswordResetNotification($token)
    {
        // ❌ OAuth user → BLOCK reset password
        if ($this->google_id || $this->facebook_id || $this->github_id) {
            return;
        }

        // ✅ User manual → normal
        $this->notify(new ResetPasswordNotification($token));
    }

    /**
     * Use our branded email verification template.
     */
    public function sendEmailVerificationNotification()
    {
        $this->notify(new VerifyEmailNotification);
    }

    /**
     * Helpers
     */
    public function isSocialUser(): bool
    {
        return ! is_null($this->google_id) || ! is_null($this->facebook_id) || ! is_null($this->github_id);
    }

    /**
     * Consents Relation
     */
    public function consents()
    {
        return $this->hasMany(UserConsent::class);
    }

    /**
     * Check if user has agreed to the current version of a document.
     */
    public function hasAgreedToCurrentLegal(string $type): bool
    {
        // Settings use 'pdp' prefix for Privacy Policy, while code uses 'privacy' type
        $keyPrefix = ($type === 'privacy' || $type === 'pdp') ? 'pdp' : $type;
        $currentVersion = (int) get_setting("{$keyPrefix}_document_version", 1);

        return $this->consents()
            ->where(function ($q) use ($type) {
                $q->where('consent_type', $type)
                    ->orWhere('consent_type', 'privacy')
                    ->orWhere('consent_type', 'pdp');
            })
            ->where('version_id', '>=', $currentVersion)
            ->exists();
    }

    /**
     * Notifications this user has interacted with (including personal read/deleted status).
     */
    public function broadcastNotifications()
    {
        return $this->belongsToMany(Notification::class, 'system_notification_user')
            ->withPivot('read_at', 'deleted_at')
            ->withTimestamps();
    }

    /**
     * Get the user who created this record.
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get the user who last updated this record.
     */
    public function updater()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }
}
