<?php

namespace App\Models\Tenants;

use App\Models\Members\User;
use App\Traits\Auditable;
use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * 결재 문서 모델
 *
 * @property int $id
 * @property int $tenant_id
 * @property string $document_number
 * @property int $form_id
 * @property string $title
 * @property array $content
 * @property string $status
 * @property int $drafter_id
 * @property \Carbon\Carbon|null $drafted_at
 * @property \Carbon\Carbon|null $completed_at
 * @property int $current_step
 * @property array|null $attachments
 * @property int|null $created_by
 * @property int|null $updated_by
 * @property int|null $deleted_by
 */
class Approval extends Model
{
    use Auditable, BelongsToTenant, SoftDeletes;

    protected $table = 'approvals';

    protected $casts = [
        'content' => 'array',
        'attachments' => 'array',
        'drafted_at' => 'datetime',
        'completed_at' => 'datetime',
        'current_step' => 'integer',
    ];

    protected $fillable = [
        'tenant_id',
        'document_number',
        'form_id',
        'title',
        'content',
        'status',
        'drafter_id',
        'drafted_at',
        'completed_at',
        'current_step',
        'attachments',
        'linkable_type',
        'linkable_id',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $attributes = [
        'status' => 'draft',
        'current_step' => 0,
    ];

    // =========================================================================
    // 상태 상수
    // =========================================================================

    public const STATUS_DRAFT = 'draft';           // 임시저장

    public const STATUS_PENDING = 'pending';       // 결재 진행중

    public const STATUS_APPROVED = 'approved';     // 승인 완료

    public const STATUS_REJECTED = 'rejected';     // 반려

    public const STATUS_CANCELLED = 'cancelled';   // 회수/취소

    public const STATUSES = [
        self::STATUS_DRAFT,
        self::STATUS_PENDING,
        self::STATUS_APPROVED,
        self::STATUS_REJECTED,
        self::STATUS_CANCELLED,
    ];

    // =========================================================================
    // 관계 정의
    // =========================================================================

    /**
     * 결재 양식
     */
    public function form(): BelongsTo
    {
        return $this->belongsTo(ApprovalForm::class, 'form_id');
    }

    /**
     * 기안자
     */
    public function drafter(): BelongsTo
    {
        return $this->belongsTo(User::class, 'drafter_id');
    }

    /**
     * 결재 단계들
     */
    public function steps(): HasMany
    {
        return $this->hasMany(ApprovalStep::class, 'approval_id')->orderBy('step_order');
    }

    /**
     * 결재자 단계들 (참조 제외)
     */
    public function approverSteps(): HasMany
    {
        return $this->hasMany(ApprovalStep::class, 'approval_id')
            ->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT])
            ->orderBy('step_order');
    }

    /**
     * 참조자 단계들
     */
    public function referenceSteps(): HasMany
    {
        return $this->hasMany(ApprovalStep::class, 'approval_id')
            ->where('step_type', ApprovalLine::STEP_TYPE_REFERENCE)
            ->orderBy('step_order');
    }

    /**
     * 연결 대상 (Document 등)
     */
    public function linkable(): MorphTo
    {
        return $this->morphTo();
    }

    /**
     * 생성자
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * 수정자
     */
    public function updater(): BelongsTo
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    // =========================================================================
    // 스코프
    // =========================================================================

    /**
     * 특정 상태
     */
    public function scopeWithStatus($query, string $status)
    {
        return $query->where('status', $status);
    }

    /**
     * 임시저장
     */
    public function scopeDraft($query)
    {
        return $query->where('status', self::STATUS_DRAFT);
    }

    /**
     * 결재 진행중
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * 승인 완료
     */
    public function scopeApproved($query)
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    /**
     * 반려
     */
    public function scopeRejected($query)
    {
        return $query->where('status', self::STATUS_REJECTED);
    }

    /**
     * 완료됨 (승인 또는 반려)
     */
    public function scopeCompleted($query)
    {
        return $query->whereIn('status', [self::STATUS_APPROVED, self::STATUS_REJECTED]);
    }

    /**
     * 특정 기안자
     */
    public function scopeByDrafter($query, int $userId)
    {
        return $query->where('drafter_id', $userId);
    }

    // =========================================================================
    // 헬퍼 메서드
    // =========================================================================

    /**
     * 수정 가능 여부 (임시저장 상태만)
     */
    public function isEditable(): bool
    {
        return $this->status === self::STATUS_DRAFT;
    }

    /**
     * 상신 가능 여부
     */
    public function isSubmittable(): bool
    {
        return $this->status === self::STATUS_DRAFT;
    }

    /**
     * 승인/반려 가능 여부
     */
    public function isActionable(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * 회수 가능 여부 (기안자만, 진행중 상태)
     */
    public function isCancellable(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * 삭제 가능 여부 (임시저장만)
     */
    public function isDeletable(): bool
    {
        return $this->status === self::STATUS_DRAFT;
    }

    /**
     * 상태 라벨
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_DRAFT => '임시저장',
            self::STATUS_PENDING => '진행',
            self::STATUS_APPROVED => '완료',
            self::STATUS_REJECTED => '반려',
            self::STATUS_CANCELLED => '회수',
            default => $this->status,
        };
    }

    /**
     * 현재 결재자 확인
     */
    public function getCurrentApproverStep(): ?ApprovalStep
    {
        return $this->steps()
            ->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT])
            ->where('status', ApprovalStep::STATUS_PENDING)
            ->orderBy('step_order')
            ->first();
    }

    /**
     * 특정 사용자가 현재 결재자인지 확인
     */
    public function isCurrentApprover(int $userId): bool
    {
        $currentStep = $this->getCurrentApproverStep();

        return $currentStep && $currentStep->approver_id === $userId;
    }

    /**
     * 특정 사용자가 참조자인지 확인
     */
    public function isReferee(int $userId): bool
    {
        return $this->referenceSteps()
            ->where('approver_id', $userId)
            ->exists();
    }

    /**
     * 결재 진행률
     */
    public function getProgressAttribute(): array
    {
        $totalSteps = $this->approverSteps()->count();
        $completedSteps = $this->approverSteps()
            ->whereIn('status', [ApprovalStep::STATUS_APPROVED, ApprovalStep::STATUS_REJECTED])
            ->count();

        return [
            'total' => $totalSteps,
            'completed' => $completedSteps,
            'percentage' => $totalSteps > 0 ? round(($completedSteps / $totalSteps) * 100) : 0,
        ];
    }
}
