<?php

namespace App\Models\Tenants;

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

/**
 * 근무 설정 모델
 *
 * @property int $id
 * @property int $tenant_id
 * @property string $work_type
 * @property int $standard_hours
 * @property int $overtime_hours
 * @property int $overtime_limit
 * @property array|null $work_days
 * @property string $start_time
 * @property string $end_time
 * @property int $break_minutes
 * @property string|null $break_start
 * @property string|null $break_end
 */
class WorkSetting extends Model
{
    use BelongsToTenant;

    protected $table = 'work_settings';

    protected $fillable = [
        'tenant_id',
        'work_type',
        'standard_hours',
        'overtime_hours',
        'overtime_limit',
        'work_days',
        'start_time',
        'end_time',
        'break_minutes',
        'break_start',
        'break_end',
    ];

    protected $casts = [
        // work_days는 Attribute accessor에서 처리
        'standard_hours' => 'integer',
        'overtime_hours' => 'integer',
        'overtime_limit' => 'integer',
        'break_minutes' => 'integer',
    ];

    protected $attributes = [
        'work_type' => 'fixed',
        'standard_hours' => 40,
        'overtime_hours' => 12,
        'overtime_limit' => 52,
        'start_time' => '09:00:00',
        'end_time' => '18:00:00',
        'break_minutes' => 60,
        'break_start' => '12:00:00',
        'break_end' => '13:00:00',
    ];

    // =========================================================================
    // 상수 정의
    // =========================================================================

    public const TYPE_FIXED = 'fixed';         // 고정 근무

    public const TYPE_FLEXIBLE = 'flexible';   // 유연 근무

    public const TYPE_CUSTOM = 'custom';       // 커스텀 근무

    public const WORK_TYPES = [
        self::TYPE_FIXED,
        self::TYPE_FLEXIBLE,
        self::TYPE_CUSTOM,
    ];

    public const DEFAULT_WORK_DAYS = ['mon', 'tue', 'wed', 'thu', 'fri'];

    /**
     * 숫자 → 요일 문자열 매핑
     */
    public const DAY_INDEX_MAP = [
        1 => 'mon',
        2 => 'tue',
        3 => 'wed',
        4 => 'thu',
        5 => 'fri',
        6 => 'sat',
        7 => 'sun',
        0 => 'sun', // 일요일이 0인 경우도 처리
    ];

    // =========================================================================
    // Accessors & Mutators
    // =========================================================================

    /**
     * work_days 조회 시 숫자를 문자열로 변환
     */
    protected function workDays(): \Illuminate\Database\Eloquent\Casts\Attribute
    {
        return \Illuminate\Database\Eloquent\Casts\Attribute::make(
            get: function ($value) {
                $days = is_string($value) ? json_decode($value, true) : $value;

                if (! is_array($days)) {
                    return self::DEFAULT_WORK_DAYS;
                }

                // 숫자가 포함된 경우 문자열로 변환
                return array_values(array_unique(array_map(function ($day) {
                    if (is_int($day) || is_numeric($day)) {
                        return self::DAY_INDEX_MAP[(int) $day] ?? 'mon';
                    }

                    return $day;
                }, $days)));
            },
            set: function ($value) {
                if (! is_array($value)) {
                    return json_encode(self::DEFAULT_WORK_DAYS);
                }

                // 항상 문자열 배열로 저장
                $days = array_values(array_unique(array_map(function ($day) {
                    if (is_int($day) || is_numeric($day)) {
                        return self::DAY_INDEX_MAP[(int) $day] ?? 'mon';
                    }

                    return $day;
                }, $value)));

                return json_encode($days);
            }
        );
    }

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

    /**
     * 근무 유형 라벨
     */
    public function getWorkTypeLabelAttribute(): string
    {
        return match ($this->work_type) {
            self::TYPE_FIXED => '고정근무',
            self::TYPE_FLEXIBLE => '유연근무',
            self::TYPE_CUSTOM => '커스텀',
            default => $this->work_type,
        };
    }

    /**
     * 일일 근무시간 계산 (분)
     */
    public function getDailyWorkMinutesAttribute(): int
    {
        $start = strtotime($this->start_time);
        $end = strtotime($this->end_time);
        $totalMinutes = ($end - $start) / 60;

        return (int) ($totalMinutes - $this->break_minutes);
    }
}
