<?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\SoftDeletes;

/**
 * 급여 모델
 *
 * @property int $id
 * @property int $tenant_id
 * @property int $user_id
 * @property int $pay_year
 * @property int $pay_month
 * @property float $base_salary
 * @property float $overtime_pay
 * @property float $bonus
 * @property array|null $allowances
 * @property float $gross_salary
 * @property float $income_tax
 * @property float $resident_tax
 * @property float $health_insurance
 * @property float $pension
 * @property float $employment_insurance
 * @property array|null $deductions
 * @property float $total_deductions
 * @property float $net_salary
 * @property string $status
 * @property \Carbon\Carbon|null $confirmed_at
 * @property int|null $confirmed_by
 * @property \Carbon\Carbon|null $paid_at
 * @property int|null $withdrawal_id
 * @property string|null $note
 * @property int|null $created_by
 * @property int|null $updated_by
 * @property int|null $deleted_by
 */
class Payroll extends Model
{
    use Auditable, BelongsToTenant, SoftDeletes;

    protected $table = 'payrolls';

    protected $casts = [
        'allowances' => 'array',
        'deductions' => 'array',
        'base_salary' => 'decimal:2',
        'overtime_pay' => 'decimal:2',
        'bonus' => 'decimal:2',
        'gross_salary' => 'decimal:2',
        'income_tax' => 'decimal:2',
        'resident_tax' => 'decimal:2',
        'health_insurance' => 'decimal:2',
        'pension' => 'decimal:2',
        'employment_insurance' => 'decimal:2',
        'total_deductions' => 'decimal:2',
        'net_salary' => 'decimal:2',
        'confirmed_at' => 'datetime',
        'paid_at' => 'datetime',
        'pay_year' => 'integer',
        'pay_month' => 'integer',
    ];

    protected $fillable = [
        'tenant_id',
        'user_id',
        'pay_year',
        'pay_month',
        'base_salary',
        'overtime_pay',
        'bonus',
        'allowances',
        'gross_salary',
        'income_tax',
        'resident_tax',
        'health_insurance',
        'pension',
        'employment_insurance',
        'deductions',
        'total_deductions',
        'net_salary',
        'status',
        'confirmed_at',
        'confirmed_by',
        'paid_at',
        'withdrawal_id',
        'note',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $attributes = [
        'status' => 'draft',
        'base_salary' => 0,
        'overtime_pay' => 0,
        'bonus' => 0,
        'gross_salary' => 0,
        'income_tax' => 0,
        'resident_tax' => 0,
        'health_insurance' => 0,
        'pension' => 0,
        'employment_insurance' => 0,
        'total_deductions' => 0,
        'net_salary' => 0,
    ];

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

    public const STATUS_DRAFT = 'draft';           // 작성중

    public const STATUS_CONFIRMED = 'confirmed';   // 확정

    public const STATUS_PAID = 'paid';             // 지급완료

    public const STATUSES = [
        self::STATUS_DRAFT,
        self::STATUS_CONFIRMED,
        self::STATUS_PAID,
    ];

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

    /**
     * 급여 대상 사용자
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * 확정자
     */
    public function confirmer(): BelongsTo
    {
        return $this->belongsTo(User::class, 'confirmed_by');
    }

    /**
     * 출금 내역
     */
    public function withdrawal(): BelongsTo
    {
        return $this->belongsTo(Withdrawal::class, 'withdrawal_id');
    }

    /**
     * 생성자
     */
    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 scopeConfirmed($query)
    {
        return $query->where('status', self::STATUS_CONFIRMED);
    }

    /**
     * 지급완료
     */
    public function scopePaid($query)
    {
        return $query->where('status', self::STATUS_PAID);
    }

    /**
     * 특정 연월
     */
    public function scopeForPeriod($query, int $year, int $month)
    {
        return $query->where('pay_year', $year)->where('pay_month', $month);
    }

    /**
     * 특정 사용자
     */
    public function scopeForUser($query, int $userId)
    {
        return $query->where('user_id', $userId);
    }

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

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

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

    /**
     * 지급 가능 여부
     */
    public function isPayable(): bool
    {
        return $this->status === self::STATUS_CONFIRMED;
    }

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

    /**
     * 상태 라벨
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_DRAFT => '작성중',
            self::STATUS_CONFIRMED => '확정',
            self::STATUS_PAID => '지급완료',
            default => $this->status,
        };
    }

    /**
     * 급여 기간 문자열
     */
    public function getPeriodLabelAttribute(): string
    {
        return sprintf('%d년 %02d월', $this->pay_year, $this->pay_month);
    }

    /**
     * 수당 합계
     */
    public function getAllowancesTotalAttribute(): float
    {
        if (empty($this->allowances)) {
            return 0;
        }

        return collect($this->allowances)->sum('amount');
    }

    /**
     * 공제 합계 (JSON)
     */
    public function getDeductionsTotalAttribute(): float
    {
        if (empty($this->deductions)) {
            return 0;
        }

        return collect($this->deductions)->sum('amount');
    }

    /**
     * 총지급액 계산
     */
    public function calculateGrossSalary(): float
    {
        return $this->base_salary
            + $this->overtime_pay
            + $this->bonus
            + $this->allowances_total;
    }

    /**
     * 총공제액 계산
     */
    public function calculateTotalDeductions(): float
    {
        return $this->income_tax
            + $this->resident_tax
            + $this->health_insurance
            + $this->pension
            + $this->employment_insurance
            + $this->deductions_total;
    }

    /**
     * 실수령액 계산
     */
    public function calculateNetSalary(): float
    {
        return $this->gross_salary - $this->total_deductions;
    }
}
