<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;

/**
 * @property int $id
 * @property string $uuid
 * @property string $name
 * @property string $email
 * @property mixed $password
 * @property string $status
 * @property bool $email_verified
 * @property bool $is_deleted
 * @property string|null $remember_token
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
 * @property-read int|null $notifications_count
 * @property-read \Illuminate\Database\Eloquent\Collection<int, \Spatie\Permission\Models\Permission> $permissions
 * @property-read int|null $permissions_count
 * @property-read \Illuminate\Database\Eloquent\Collection<int, \Spatie\Permission\Models\Role> $roles
 * @property-read int|null $roles_count
 * @property-read \Illuminate\Database\Eloquent\Collection<int, \Laravel\Sanctum\PersonalAccessToken> $tokens
 * @property-read int|null $tokens_count
 *
 * @method static \Illuminate\Database\Eloquent\Builder|Admin newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|Admin newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|Admin permission($permissions, $without = false)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin query()
 * @method static \Illuminate\Database\Eloquent\Builder|Admin role($roles, $guard = null, $without = false)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereEmail($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereEmailVerified($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereIsDeleted($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereName($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin wherePassword($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereRememberToken($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin whereUuid($value)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin withoutPermission($permissions)
 * @method static \Illuminate\Database\Eloquent\Builder|Admin withoutRole($roles, $guard = null)
 *
 * @property \Illuminate\Support\Carbon|null $last_login_at
 * @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientBalance> $balanceEntries
 * @property-read int|null $balance_entries_count
 * @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\TicketDepartment> $ticketDepartments
 * @property-read int|null $ticket_departments_count
 *
 * @method static \Illuminate\Database\Eloquent\Builder<static>|Admin whereLastLoginAt($value)
 *
 * @mixin \Eloquent
 */
class Admin extends Authenticatable
{
    use HasApiTokens, HasFactory, HasRoles, Notifiable, \App\Traits\SealsAdminAttributes;

    /**
     * Admin-only attributes — emit an audit warning when filled from outside
     * a trusted (admin guard / console / unsealed-block) context. PRC-216.
     *
     * Per ticket: is_ai_staff (AI staff role-bypass risk), email_verified
     * (verification gate bypass), is_deleted (soft-delete bypass), status
     * (account activation), totp_* (two-factor state), notification_*
     * (admin notification routing).
     *
     * The first-admin bootstrap was via Admin\Auth\RegisteredUserController
     * (now removed — PRC-161 SEC-Critical takeover risk). İlk admin için
     * `sail artisan db:seed --class=AdminSeeder` veya manuel oluşturma kullan;
     * sonraki admin'ler `/admin/admin-management` üzerinden (mevcut admin
     * guard altında). The AiStaffController (admin-creates-ai-admin) runs
     * under the admin guard and is trusted.
     *
     * Defense-in-depth: $fillable is intentionally not modified so admin
     * controllers keep working. See app/Traits/SealsAdminAttributes.php.
     */
    protected static array $sealedAdminAttributes = [
        'uuid',
        'status',
        'email_verified',
        'is_deleted',
        'is_ai_staff',
        'last_login_at',
        'totp_secret',
        'totp_enabled',
        'totp_backup_codes',
        'totp_verified_at',
        'notification_preferences',
    ];

    protected $guard = 'admin';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'uuid',
        'name',
        'email',
        'phone',
        'password',
        'status',
        'email_verified',
        'is_deleted',
        'is_ai_staff',
        'last_login_at',
        'totp_secret',
        'totp_enabled',
        'totp_backup_codes',
        'totp_verified_at',
        'two_factor_method',
        'two_factor_otp_hash',
        'two_factor_otp_expires_at',
        'two_factor_otp_sent_at',
        'last_used_totp_step',
        'slack_user_id',
        'telegram_user_id',
        'pushover_user_key',
        'discord_webhook',
        'teams_webhook',
        'notification_preferences',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
        'totp_secret',
        'totp_backup_codes',
        'two_factor_otp_hash',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified' => 'boolean',
        'is_deleted' => 'boolean',
        'is_ai_staff' => 'boolean',
        'password' => 'hashed',
        'last_login_at' => 'datetime',
        'totp_enabled' => 'boolean',
        'totp_verified_at' => 'datetime',
        'two_factor_otp_expires_at' => 'datetime',
        'two_factor_otp_sent_at' => 'datetime',
        'notification_preferences' => 'array',
    ];

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->uuid = (string) Str::uuid();
        });
    }

    /**
     * Get the ticket departments assigned to this admin.
     */
    public function ticketDepartments()
    {
        return $this->belongsToMany(TicketDepartment::class, 'ticket_department_admins', 'admin_id', 'ticket_department_id')
            ->withTimestamps();
    }

    /**
     * Bakiye kayıtları ilişkisi
     */
    public function balanceEntries()
    {
        return $this->hasMany(ClientBalance::class, 'admin_id');
    }

    /**
     * Get per-admin notification channel preferences for a given event type.
     * Returns null if the admin has no override for this type (use system defaults).
     */
    public function aiStaffProfile()
    {
        return $this->hasOne(AiStaffProfile::class);
    }

    public function scopeHuman($query)
    {
        return $query->where('is_ai_staff', false);
    }

    public function scopeAiStaff($query)
    {
        return $query->where('is_ai_staff', true);
    }

    public function getNotificationChannels(string $type): ?array
    {
        $prefs = $this->notification_preferences;

        // PRC-624 — JSON key'ler prefKey (snake-slug) formda saklanır;
        // Title Case type adları sluglanarak aranır. Eski snake type'lar
        // için slug no-op olduğundan geriye uyumludur.
        $key = \App\Services\NotificationService::prefKey($type);

        if (empty($prefs) || !isset($prefs[$key])) {
            return null; // null = use system defaults
        }

        return $prefs[$key];
    }
}
