<?php

namespace App\Models\Tenants;

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

/**
 * 데이터 내보내기 모델
 *
 * @property int $id
 * @property int $tenant_id 테넌트 ID
 * @property string $export_type 내보내기 유형
 * @property string $status 상태
 * @property string|null $file_path 파일 경로
 * @property string|null $file_name 파일명
 * @property int|null $file_size 파일 크기
 * @property array|null $options 옵션
 * @property \Carbon\Carbon|null $started_at 시작 시간
 * @property \Carbon\Carbon|null $completed_at 완료 시간
 * @property string|null $error_message 에러 메시지
 * @property int|null $created_by 생성자
 */
class DataExport extends Model
{
    use BelongsToTenant;

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

    /** 내보내기 유형 */
    public const TYPE_ALL = 'all';

    public const TYPE_USERS = 'users';

    public const TYPE_PRODUCTS = 'products';

    public const TYPE_ORDERS = 'orders';

    public const TYPE_CLIENTS = 'clients';

    public const TYPES = [
        self::TYPE_ALL,
        self::TYPE_USERS,
        self::TYPE_PRODUCTS,
        self::TYPE_ORDERS,
        self::TYPE_CLIENTS,
    ];

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

    public const STATUS_PROCESSING = 'processing';

    public const STATUS_COMPLETED = 'completed';

    public const STATUS_FAILED = 'failed';

    public const STATUSES = [
        self::STATUS_PENDING,
        self::STATUS_PROCESSING,
        self::STATUS_COMPLETED,
        self::STATUS_FAILED,
    ];

    /** 상태 라벨 */
    public const STATUS_LABELS = [
        self::STATUS_PENDING => '대기중',
        self::STATUS_PROCESSING => '처리중',
        self::STATUS_COMPLETED => '완료',
        self::STATUS_FAILED => '실패',
    ];

    // =========================================================================
    // 모델 설정
    // =========================================================================

    protected $fillable = [
        'tenant_id',
        'export_type',
        'status',
        'file_path',
        'file_name',
        'file_size',
        'options',
        'started_at',
        'completed_at',
        'error_message',
        'created_by',
    ];

    protected $casts = [
        'options' => 'array',
        'file_size' => 'integer',
        'started_at' => 'datetime',
        'completed_at' => 'datetime',
    ];

    protected $attributes = [
        'status' => self::STATUS_PENDING,
    ];

    // =========================================================================
    // 관계
    // =========================================================================

    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

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

    // =========================================================================
    // 접근자
    // =========================================================================

    /**
     * 상태 라벨
     */
    public function getStatusLabelAttribute(): string
    {
        return self::STATUS_LABELS[$this->status] ?? $this->status;
    }

    /**
     * 파일 크기 포맷
     */
    public function getFileSizeFormattedAttribute(): string
    {
        if (! $this->file_size) {
            return '-';
        }

        $units = ['B', 'KB', 'MB', 'GB'];
        $bytes = max($this->file_size, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= (1 << (10 * $pow));

        return round($bytes, 2).' '.$units[$pow];
    }

    /**
     * 완료 여부
     */
    public function getIsCompletedAttribute(): bool
    {
        return $this->status === self::STATUS_COMPLETED;
    }

    /**
     * 다운로드 가능 여부
     */
    public function getIsDownloadableAttribute(): bool
    {
        return $this->status === self::STATUS_COMPLETED && $this->file_path;
    }

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

    /**
     * 처리 시작
     */
    public function markAsProcessing(): bool
    {
        $this->status = self::STATUS_PROCESSING;
        $this->started_at = now();

        return $this->save();
    }

    /**
     * 처리 완료
     */
    public function markAsCompleted(string $filePath, string $fileName, int $fileSize): bool
    {
        $this->status = self::STATUS_COMPLETED;
        $this->file_path = $filePath;
        $this->file_name = $fileName;
        $this->file_size = $fileSize;
        $this->completed_at = now();

        return $this->save();
    }

    /**
     * 처리 실패
     */
    public function markAsFailed(string $errorMessage): bool
    {
        $this->status = self::STATUS_FAILED;
        $this->error_message = $errorMessage;
        $this->completed_at = now();

        return $this->save();
    }
}
