<?php

namespace App\Models\Bidding;

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

class Bidding extends Model
{
    use Auditable, BelongsToTenant, HasFactory, SoftDeletes;

    protected $fillable = [
        'tenant_id',
        'bidding_code',
        'quote_id',
        // 거래처/현장
        'client_id',
        'client_name',
        'project_name',
        // 입찰 정보
        'bidding_date',
        'bid_date',
        'submission_date',
        'confirm_date',
        'total_count',
        'bidding_amount',
        // 상태
        'status',
        // 입찰자
        'bidder_id',
        'bidder_name',
        // 공사기간
        'construction_start_date',
        'construction_end_date',
        'vat_type',
        // 비고
        'remarks',
        // 견적 데이터 스냅샷
        'expense_items',
        'estimate_detail_items',
        // 감사
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $casts = [
        'bidding_date' => 'date',
        'bid_date' => 'date',
        'submission_date' => 'date',
        'confirm_date' => 'date',
        'construction_start_date' => 'date',
        'construction_end_date' => 'date',
        'bidding_amount' => 'decimal:2',
        'expense_items' => 'array',
        'estimate_detail_items' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * 상태 상수
     */
    public const STATUS_WAITING = 'waiting';     // 입찰대기

    public const STATUS_SUBMITTED = 'submitted'; // 투찰

    public const STATUS_FAILED = 'failed';       // 탈락

    public const STATUS_INVALID = 'invalid';     // 유찰

    public const STATUS_AWARDED = 'awarded';     // 낙찰

    public const STATUS_HOLD = 'hold';           // 보류

    public const STATUSES = [
        self::STATUS_WAITING,
        self::STATUS_SUBMITTED,
        self::STATUS_FAILED,
        self::STATUS_INVALID,
        self::STATUS_AWARDED,
        self::STATUS_HOLD,
    ];

    /**
     * 부가세 유형 상수
     */
    public const VAT_INCLUDED = 'included';

    public const VAT_EXCLUDED = 'excluded';

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

    /**
     * 연결된 견적
     */
    public function quote(): BelongsTo
    {
        return $this->belongsTo(Quote::class);
    }

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

    /**
     * 입찰자
     */
    public function bidder(): BelongsTo
    {
        return $this->belongsTo(User::class, 'bidder_id');
    }

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

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

    /**
     * 상태별 스코프
     */
    public function scopeWaiting($query)
    {
        return $query->where('status', self::STATUS_WAITING);
    }

    public function scopeSubmitted($query)
    {
        return $query->where('status', self::STATUS_SUBMITTED);
    }

    public function scopeFailed($query)
    {
        return $query->where('status', self::STATUS_FAILED);
    }

    public function scopeInvalid($query)
    {
        return $query->where('status', self::STATUS_INVALID);
    }

    public function scopeAwarded($query)
    {
        return $query->where('status', self::STATUS_AWARDED);
    }

    public function scopeHold($query)
    {
        return $query->where('status', self::STATUS_HOLD);
    }

    /**
     * 상태 필터 스코프
     */
    public function scopeOfStatus($query, ?string $status)
    {
        if ($status) {
            return $query->where('status', $status);
        }

        return $query;
    }

    /**
     * 날짜 범위 스코프
     */
    public function scopeDateRange($query, ?string $from, ?string $to)
    {
        if ($from) {
            $query->where('bidding_date', '>=', $from);
        }
        if ($to) {
            $query->where('bidding_date', '<=', $to);
        }

        return $query;
    }

    /**
     * 검색 스코프
     */
    public function scopeSearch($query, ?string $keyword)
    {
        if (! $keyword) {
            return $query;
        }

        return $query->where(function ($q) use ($keyword) {
            $q->where('bidding_code', 'like', "%{$keyword}%")
                ->orWhere('client_name', 'like', "%{$keyword}%")
                ->orWhere('project_name', 'like', "%{$keyword}%")
                ->orWhere('bidder_name', 'like', "%{$keyword}%");
        });
    }

    /**
     * 수정 가능 여부 확인
     */
    public function isEditable(): bool
    {
        return ! in_array($this->status, [self::STATUS_AWARDED, self::STATUS_FAILED, self::STATUS_INVALID]);
    }

    /**
     * 삭제 가능 여부 확인
     */
    public function isDeletable(): bool
    {
        return ! in_array($this->status, [self::STATUS_AWARDED]);
    }

    /**
     * 낙찰 가능 여부 확인
     */
    public function isAwardable(): bool
    {
        return in_array($this->status, [self::STATUS_WAITING, self::STATUS_SUBMITTED, self::STATUS_HOLD]);
    }

    /**
     * 계약 전환 가능 여부 확인
     */
    public function isConvertibleToContract(): bool
    {
        return $this->status === self::STATUS_AWARDED;
    }
}
