<?php

namespace App\Models;

use App\Models\Members\User;
use App\Models\Permissions\Role;
use App\Models\Tenants\Tenant;
use App\Traits\Auditable;
use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Str;

class UserInvitation extends Model
{
    use Auditable, BelongsToTenant;

    // 상태 상수
    public const STATUS_PENDING = 'pending';

    public const STATUS_ACCEPTED = 'accepted';

    public const STATUS_EXPIRED = 'expired';

    public const STATUS_CANCELLED = 'cancelled';

    // 기본 만료 기간 (일)
    public const DEFAULT_EXPIRES_DAYS = 7;

    protected $fillable = [
        'tenant_id',
        'email',
        'role_id',
        'message',
        'token',
        'status',
        'invited_by',
        'expires_at',
        'accepted_at',
    ];

    protected $casts = [
        'expires_at' => 'datetime',
        'accepted_at' => 'datetime',
    ];

    /**
     * 테넌트 관계
     */
    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    /**
     * 역할 관계
     */
    public function role(): BelongsTo
    {
        return $this->belongsTo(Role::class);
    }

    /**
     * 초대한 사용자 관계
     */
    public function inviter(): BelongsTo
    {
        return $this->belongsTo(User::class, 'invited_by');
    }

    /**
     * 토큰 생성
     */
    public static function generateToken(): string
    {
        return Str::random(64);
    }

    /**
     * 만료 일시 계산
     */
    public static function calculateExpiresAt(int $days = self::DEFAULT_EXPIRES_DAYS): \DateTime
    {
        return now()->addDays($days);
    }

    /**
     * 만료 여부 확인
     */
    public function isExpired(): bool
    {
        return $this->expires_at->isPast();
    }

    /**
     * 수락 가능 여부 확인
     */
    public function canAccept(): bool
    {
        return $this->status === self::STATUS_PENDING && ! $this->isExpired();
    }

    /**
     * 취소 가능 여부 확인
     */
    public function canCancel(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * 초대 수락 처리
     */
    public function markAsAccepted(): void
    {
        $this->status = self::STATUS_ACCEPTED;
        $this->accepted_at = now();
        $this->save();
    }

    /**
     * 초대 만료 처리
     */
    public function markAsExpired(): void
    {
        $this->status = self::STATUS_EXPIRED;
        $this->save();
    }

    /**
     * 초대 취소 처리
     */
    public function markAsCancelled(): void
    {
        $this->status = self::STATUS_CANCELLED;
        $this->save();
    }

    /**
     * Scope: 대기 중인 초대만
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Scope: 만료된 초대 (상태 업데이트 대상)
     */
    public function scopeExpiredPending($query)
    {
        return $query->where('status', self::STATUS_PENDING)
            ->where('expires_at', '<', now());
    }

    /**
     * Scope: 특정 이메일 초대
     */
    public function scopeForEmail($query, string $email)
    {
        return $query->where('email', $email);
    }

    /**
     * 상태 라벨 반환
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_PENDING => '대기중',
            self::STATUS_ACCEPTED => '수락됨',
            self::STATUS_EXPIRED => '만료됨',
            self::STATUS_CANCELLED => '취소됨',
            default => $this->status,
        };
    }
}
