<?php

namespace App\Models\Tenants;

use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * 급여 설정 모델
 *
 * @property int $id
 * @property int $tenant_id
 * @property float $income_tax_rate
 * @property float $resident_tax_rate
 * @property float $health_insurance_rate
 * @property float $long_term_care_rate
 * @property float $pension_rate
 * @property float $employment_insurance_rate
 * @property float $pension_max_salary
 * @property float $pension_min_salary
 * @property int $pay_day
 * @property bool $auto_calculate
 * @property array|null $allowance_types
 * @property array|null $deduction_types
 */
class PayrollSetting extends Model
{
    use BelongsToTenant;

    protected $table = 'payroll_settings';

    public $timestamps = true;

    protected $casts = [
        'income_tax_rate' => 'decimal:2',
        'resident_tax_rate' => 'decimal:2',
        'health_insurance_rate' => 'decimal:3',
        'long_term_care_rate' => 'decimal:4',
        'pension_rate' => 'decimal:3',
        'employment_insurance_rate' => 'decimal:3',
        'pension_max_salary' => 'decimal:2',
        'pension_min_salary' => 'decimal:2',
        'pay_day' => 'integer',
        'auto_calculate' => 'boolean',
        'allowance_types' => 'array',
        'deduction_types' => 'array',
    ];

    protected $fillable = [
        'tenant_id',
        'income_tax_rate',
        'resident_tax_rate',
        'health_insurance_rate',
        'long_term_care_rate',
        'pension_rate',
        'employment_insurance_rate',
        'pension_max_salary',
        'pension_min_salary',
        'pay_day',
        'auto_calculate',
        'allowance_types',
        'deduction_types',
    ];

    protected $attributes = [
        'income_tax_rate' => 0,
        'resident_tax_rate' => 10,
        'health_insurance_rate' => 3.545,
        'long_term_care_rate' => 0.9082,
        'pension_rate' => 4.5,
        'employment_insurance_rate' => 0.9,
        'pension_max_salary' => 5900000,
        'pension_min_salary' => 370000,
        'pay_day' => 25,
        'auto_calculate' => false,
    ];

    // =========================================================================
    // 기본 수당 유형
    // =========================================================================

    public const DEFAULT_ALLOWANCE_TYPES = [
        ['code' => 'meal', 'name' => '식대', 'is_taxable' => false],
        ['code' => 'transport', 'name' => '교통비', 'is_taxable' => false],
        ['code' => 'position', 'name' => '직책수당', 'is_taxable' => true],
        ['code' => 'skill', 'name' => '기술수당', 'is_taxable' => true],
        ['code' => 'family', 'name' => '가족수당', 'is_taxable' => true],
        ['code' => 'housing', 'name' => '주거수당', 'is_taxable' => true],
    ];

    // =========================================================================
    // 기본 공제 유형
    // =========================================================================

    public const DEFAULT_DEDUCTION_TYPES = [
        ['code' => 'loan', 'name' => '대출상환'],
        ['code' => 'union', 'name' => '조합비'],
        ['code' => 'savings', 'name' => '저축'],
        ['code' => 'etc', 'name' => '기타공제'],
    ];

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

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

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

    /**
     * 수당 유형 목록 (기본값 포함)
     */
    public function getAllowanceTypesWithDefaultAttribute(): array
    {
        return $this->allowance_types ?? self::DEFAULT_ALLOWANCE_TYPES;
    }

    /**
     * 공제 유형 목록 (기본값 포함)
     */
    public function getDeductionTypesWithDefaultAttribute(): array
    {
        return $this->deduction_types ?? self::DEFAULT_DEDUCTION_TYPES;
    }

    /**
     * 건강보험료 계산
     */
    public function calculateHealthInsurance(float $salary): float
    {
        return round($salary * ($this->health_insurance_rate / 100), 0);
    }

    /**
     * 장기요양보험료 계산 (건강보험료의 %)
     */
    public function calculateLongTermCare(float $healthInsurance): float
    {
        return round($healthInsurance * ($this->long_term_care_rate / 100), 0);
    }

    /**
     * 국민연금 계산
     */
    public function calculatePension(float $salary): float
    {
        // 기준소득월액 상/하한 적용
        $standardSalary = min(max($salary, $this->pension_min_salary), $this->pension_max_salary);

        return round($standardSalary * ($this->pension_rate / 100), 0);
    }

    /**
     * 고용보험료 계산
     */
    public function calculateEmploymentInsurance(float $salary): float
    {
        return round($salary * ($this->employment_insurance_rate / 100), 0);
    }

    /**
     * 주민세 계산 (소득세의 10%)
     */
    public function calculateResidentTax(float $incomeTax): float
    {
        return round($incomeTax * ($this->resident_tax_rate / 100), 0);
    }

    /**
     * 테넌트별 설정 가져오기 또는 생성
     */
    public static function getOrCreate(int $tenantId): self
    {
        return self::firstOrCreate(
            ['tenant_id' => $tenantId],
            [
                'allowance_types' => self::DEFAULT_ALLOWANCE_TYPES,
                'deduction_types' => self::DEFAULT_DEDUCTION_TYPES,
            ]
        );
    }
}
