<?php

namespace App\Models\Tenants;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class Tenant extends Model
{
    use SoftDeletes;

    protected $table = 'tenants';

    protected $fillable = [
        // 기본 정보
        'company_name',
        'code',
        'email',
        'phone',
        // 회사 정보
        'business_num',
        'corp_reg_no',
        'ceo_name',
        'address',
        'homepage',
        'fax',
        // 구독 정보
        'tenant_st_code',
        'tenant_type',
        'template_id',
        'billing_tp_code',
        'max_users',
        'trial_ends_at',
        'expires_at',
        'last_paid_at',
        // 관리 메모
        'admin_memo',
        // 삭제 정보
        'deleted_by',
        // 영업파트너 영업권 관련
        'registered_by',
        'business_card_path',
        'prospect_status',
        'prospect_registered_at',
        'prospect_expires_at',
        'cooldown_ends_at',
        'converted_at',
    ];

    protected $casts = [
        'max_users' => 'integer',
        'storage_limit' => 'integer',
        'storage_used' => 'integer',
        'trial_ends_at' => 'datetime',
        'expires_at' => 'datetime',
        'last_paid_at' => 'datetime',
        'storage_warning_sent_at' => 'datetime',
        'storage_grace_period_until' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * 활성 테넌트만 조회 (삭제되지 않은 모든 테넌트)
     */
    public function scopeActive($query)
    {
        return $query->whereNull('deleted_at');
    }

    /**
     * 관계: 사용자 (Many-to-Many via user_tenants)
     */
    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'user_tenants');
    }

    /**
     * 관계: 부서
     */
    public function departments(): HasMany
    {
        return $this->hasMany(\App\Models\Tenants\Department::class, 'tenant_id');
    }

    /**
     * 관계: 메뉴
     */
    public function menus(): HasMany
    {
        return $this->hasMany(\App\Models\Commons\Menu::class, 'tenant_id');
    }

    /**
     * 관계: 역할
     */
    public function roles(): HasMany
    {
        return $this->hasMany(\App\Models\Permissions\Role::class, 'tenant_id');
    }

    /**
     * 관계: 삭제한 사용자
     */
    public function deletedByUser(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(User::class, 'deleted_by');
    }

    /**
     * 상태 배지 색상 (Blade 뷰에서 사용)
     */
    public function getStatusBadgeColorAttribute(): string
    {
        return match ($this->tenant_st_code) {
            'active' => 'success',
            'trial' => 'warning',
            'suspended', 'expired' => 'error',
            default => 'neutral',
        };
    }

    /**
     * 상태 한글명 (Blade 뷰에서 사용)
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->tenant_st_code) {
            'trial' => '트라이얼',
            'active' => '활성',
            'suspended' => '정지',
            'expired' => '만료',
            default => $this->tenant_st_code ?? '미설정',
        };
    }

    /**
     * 결제 유형 한글명 (Blade 뷰에서 사용)
     */
    public function getBillingTypeLabelAttribute(): ?string
    {
        if (! $this->billing_tp_code) {
            return null;
        }

        return match ($this->billing_tp_code) {
            'monthly' => '월간',
            'yearly' => '연간',
            'free' => '무료',
            default => $this->billing_tp_code,
        };
    }

    /**
     * 저장소 사용률 (%) - Blade 뷰에서 사용
     */
    public function getStorageUsagePercentAttribute(): float
    {
        $limit = $this->storage_limit ?? 10737418240; // 기본 10GB
        if ($limit <= 0) {
            return 0;
        }

        return round(($this->storage_used ?? 0) / $limit * 100, 1);
    }

    /**
     * 저장소 사용량 포맷 (예: "2.5 GB / 10 GB")
     */
    public function getStorageUsageFormattedAttribute(): string
    {
        $used = $this->formatBytes($this->storage_used ?? 0);
        $limit = $this->formatBytes($this->storage_limit ?? 10737418240);

        return "{$used} / {$limit}";
    }

    /**
     * 저장소 사용량만 포맷 (예: "2.5 GB")
     */
    public function getStorageUsedFormattedAttribute(): string
    {
        return $this->formatBytes($this->storage_used ?? 0);
    }

    /**
     * 저장소 한도만 포맷 (예: "10 GB")
     */
    public function getStorageLimitFormattedAttribute(): string
    {
        return $this->formatBytes($this->storage_limit ?? 10737418240);
    }

    /**
     * 저장소 상태 배지 색상 (Blade 뷰에서 사용)
     */
    public function getStorageBadgeColorAttribute(): string
    {
        $percent = $this->storage_usage_percent;

        return match (true) {
            $percent >= 90 => 'error',
            $percent >= 70 => 'warning',
            default => 'success',
        };
    }

    /**
     * 바이트를 읽기 쉬운 형식으로 변환
     */
    protected function formatBytes(int $bytes): string
    {
        if ($bytes <= 0) {
            return '0 B';
        }

        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $factor = floor(log($bytes, 1024));
        $factor = min($factor, count($units) - 1);

        return round($bytes / pow(1024, $factor), 1).' '.$units[$factor];
    }

    /**
     * 전화번호 포맷 (하이픈 추가)
     */
    public function getPhoneFormattedAttribute(): ?string
    {
        if (! $this->phone) {
            return null;
        }

        // 숫자만 추출
        $numbers = preg_replace('/[^0-9]/', '', $this->phone);

        // 휴대폰 (010, 011, 016, 017, 018, 019)
        if (preg_match('/^(01[0-9])(\d{3,4})(\d{4})$/', $numbers, $matches)) {
            return $matches[1].'-'.$matches[2].'-'.$matches[3];
        }

        // 서울 (02)
        if (preg_match('/^(02)(\d{3,4})(\d{4})$/', $numbers, $matches)) {
            return $matches[1].'-'.$matches[2].'-'.$matches[3];
        }

        // 지역번호 (031, 032, ...)
        if (preg_match('/^(0\d{2})(\d{3,4})(\d{4})$/', $numbers, $matches)) {
            return $matches[1].'-'.$matches[2].'-'.$matches[3];
        }

        // 대표번호 (1588, 1544, ...)
        if (preg_match('/^(1\d{3})(\d{4})$/', $numbers, $matches)) {
            return $matches[1].'-'.$matches[2];
        }

        // 포맷 불가 시 원본 반환
        return $this->phone;
    }
}
