<?php

namespace App\Models\Tenants;

use App\Models\Members\User;
use App\Models\Orders\Client;
use App\Models\Quote\Quote;
use App\Traits\Auditable;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * 현장설명회 모델
 *
 * @property int $id
 * @property int $tenant_id
 * @property string|null $briefing_code 현설번호
 * @property string $title 현장설명회명
 * @property string|null $description 설명
 * @property int|null $partner_id 거래처 ID
 * @property int|null $site_id 현장 ID
 * @property string $briefing_date 현장설명회 일자
 * @property string|null $briefing_time 현장설명회 시간
 * @property string $briefing_type 구분 (online|offline)
 * @property string|null $location 장소
 * @property string|null $address 주소
 * @property string $status 상태
 * @property string $bid_status 입찰상태
 * @property string|null $bid_date 입찰일자
 * @property array|null $attendees 참석자 목록 (JSON)
 * @property string $attendance_status 참석상태
 * @property int $attendee_count 총 참석자 수
 * @property int $site_count 개소 수
 * @property string|null $construction_start_date 공사기간 시작
 * @property string|null $construction_end_date 공사기간 종료
 * @property string $vat_type 부가세 타입
 * @property int|null $created_by
 * @property int|null $updated_by
 * @property int|null $deleted_by
 * @property-read Client|null $partner
 * @property-read Site|null $site
 */
class SiteBriefing extends Model
{
    use Auditable, BelongsToTenant, ModelTrait, SoftDeletes;

    protected $table = 'site_briefings';

    // 상태 상수
    public const STATUS_SCHEDULED = 'scheduled';

    public const STATUS_ONGOING = 'ongoing';

    public const STATUS_COMPLETED = 'completed';

    public const STATUS_CANCELLED = 'cancelled';

    public const STATUS_POSTPONED = 'postponed';

    public const STATUSES = [
        self::STATUS_SCHEDULED,
        self::STATUS_ONGOING,
        self::STATUS_COMPLETED,
        self::STATUS_CANCELLED,
        self::STATUS_POSTPONED,
    ];

    // 입찰 상태 상수
    public const BID_STATUS_PENDING = 'pending';

    public const BID_STATUS_BIDDING = 'bidding';

    public const BID_STATUS_CLOSED = 'closed';

    public const BID_STATUS_FAILED = 'failed';

    public const BID_STATUS_AWARDED = 'awarded';

    public const BID_STATUSES = [
        self::BID_STATUS_PENDING,
        self::BID_STATUS_BIDDING,
        self::BID_STATUS_CLOSED,
        self::BID_STATUS_FAILED,
        self::BID_STATUS_AWARDED,
    ];

    // 구분 상수
    public const TYPE_ONLINE = 'online';

    public const TYPE_OFFLINE = 'offline';

    public const TYPES = [
        self::TYPE_ONLINE,
        self::TYPE_OFFLINE,
    ];

    // 참석 상태 상수
    public const ATTENDANCE_SCHEDULED = 'scheduled';

    public const ATTENDANCE_ATTENDED = 'attended';

    public const ATTENDANCE_ABSENT = 'absent';

    public const ATTENDANCE_STATUSES = [
        self::ATTENDANCE_SCHEDULED,
        self::ATTENDANCE_ATTENDED,
        self::ATTENDANCE_ABSENT,
    ];

    // 부가세 상수
    public const VAT_EXCLUDED = 'excluded';

    public const VAT_INCLUDED = 'included';

    public const VAT_TYPES = [
        self::VAT_EXCLUDED,
        self::VAT_INCLUDED,
    ];

    protected $fillable = [
        'tenant_id',
        'briefing_code',
        'title',
        'description',
        'partner_id',
        'site_id',
        'briefing_date',
        'briefing_time',
        'briefing_type',
        'location',
        'address',
        'status',
        'bid_status',
        'bid_date',
        'attendees',
        'attendance_status',
        'attendee_count',
        'site_count',
        'construction_start_date',
        'construction_end_date',
        'vat_type',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $casts = [
        'briefing_date' => 'date:Y-m-d',
        'bid_date' => 'date:Y-m-d',
        'construction_start_date' => 'date:Y-m-d',
        'construction_end_date' => 'date:Y-m-d',
        'attendees' => 'array',
        'attendee_count' => 'integer',
        'site_count' => 'integer',
    ];

    protected $attributes = [
        'briefing_type' => self::TYPE_OFFLINE,
        'status' => self::STATUS_SCHEDULED,
        'bid_status' => self::BID_STATUS_PENDING,
        'attendance_status' => self::ATTENDANCE_SCHEDULED,
        'vat_type' => self::VAT_EXCLUDED,
        'attendee_count' => 0,
        'site_count' => 0,
    ];

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

    /**
     * 거래처
     */
    public function partner(): BelongsTo
    {
        return $this->belongsTo(Client::class, 'partner_id');
    }

    /**
     * 현장
     */
    public function site(): BelongsTo
    {
        return $this->belongsTo(Site::class);
    }

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

    /**
     * 수정자
     */
    public function updater(): BelongsTo
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    /**
     * 견적들 (현장설명회에서 자동생성된 견적)
     */
    public function quotes(): HasMany
    {
        return $this->hasMany(Quote::class);
    }

    // =========================================================================
    // Accessors
    // =========================================================================

    /**
     * 거래처명 (partner.name)
     */
    public function getPartnerNameAttribute(): ?string
    {
        return $this->partner?->name;
    }

    /**
     * 현장명 (site.name)
     */
    public function getSiteNameAttribute(): ?string
    {
        return $this->site?->name;
    }

    /**
     * API 응답에 자동 추가할 속성
     */
    protected $appends = ['partner_name', 'site_name'];

    // =========================================================================
    // 스코프
    // =========================================================================

    /**
     * 상태별 필터
     */
    public function scopeStatus($query, string $status)
    {
        return $query->where('status', $status);
    }

    /**
     * 입찰상태별 필터
     */
    public function scopeBidStatus($query, string $bidStatus)
    {
        return $query->where('bid_status', $bidStatus);
    }

    /**
     * 날짜 범위 필터
     */
    public function scopeDateRange($query, ?string $startDate, ?string $endDate)
    {
        if ($startDate) {
            $query->where('briefing_date', '>=', $startDate);
        }
        if ($endDate) {
            $query->where('briefing_date', '<=', $endDate);
        }

        return $query;
    }

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

    /**
     * 현설번호 생성
     * 형식: SB-YYYYMM-XXXX (예: SB-202601-0001)
     */
    public static function generateBriefingCode(int $tenantId): string
    {
        $prefix = 'SB';
        $yearMonth = now()->format('Ym');

        // 해당 월의 마지막 번호 조회
        $lastCode = self::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->where('briefing_code', 'like', "{$prefix}-{$yearMonth}-%")
            ->orderBy('briefing_code', 'desc')
            ->value('briefing_code');

        if ($lastCode) {
            // 기존 번호에서 시퀀스 추출
            $lastSequence = (int) substr($lastCode, -4);
            $newSequence = $lastSequence + 1;
        } else {
            $newSequence = 1;
        }

        return sprintf('%s-%s-%04d', $prefix, $yearMonth, $newSequence);
    }
}
