<?php

namespace App\Models\Quote;

use App\Models\Items\Item;
use App\Models\Members\User;
use App\Models\Orders\Client;
use App\Models\Orders\Order;
use App\Models\Tenants\SiteBriefing;
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\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

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

    protected $fillable = [
        'tenant_id',
        'quote_type',
        'order_id',
        'site_briefing_id',
        'quote_number',
        'registration_date',
        'receipt_date',
        'author',
        // 발주처 정보
        'client_id',
        'client_name',
        'manager',
        'contact',
        // 현장 정보
        'site_id',
        'site_name',
        'site_code',
        // 제품 정보
        'product_category',
        'item_id',
        'product_code',
        'product_name',
        // 규격 정보
        'open_size_width',
        'open_size_height',
        'quantity',
        'unit_symbol',
        'floors',
        // 금액 정보
        'material_cost',
        'labor_cost',
        'install_cost',
        'subtotal',
        'discount_rate',
        'discount_amount',
        'total_amount',
        // 상태 관리
        'status',
        'current_revision',
        'is_final',
        'finalized_at',
        'finalized_by',
        // 기타 정보
        'completion_date',
        'remarks',
        'memo',
        'notes',
        // 자동산출 입력값
        'calculation_inputs',
        // 견적 옵션 (summary_items, expense_items, price_adjustments)
        'options',
        // 감사
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $casts = [
        'registration_date' => 'date',
        'receipt_date' => 'date',
        'completion_date' => 'date',
        'finalized_at' => 'datetime',
        'is_final' => 'boolean',
        'calculation_inputs' => 'array',
        'options' => 'array',
        'material_cost' => 'decimal:2',
        'labor_cost' => 'decimal:2',
        'install_cost' => 'decimal:2',
        'subtotal' => 'decimal:2',
        'discount_rate' => 'decimal:2',
        'discount_amount' => 'decimal:2',
        'total_amount' => 'decimal:2',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * 견적 유형 상수
     */
    public const TYPE_MANUFACTURING = 'manufacturing';

    public const TYPE_CONSTRUCTION = 'construction';

    public const TYPES = [
        self::TYPE_MANUFACTURING,
        self::TYPE_CONSTRUCTION,
    ];

    /**
     * 제품 카테고리 상수
     */
    public const CATEGORY_SCREEN = 'SCREEN';

    public const CATEGORY_STEEL = 'STEEL';

    /**
     * 상태 상수
     */
    public const STATUS_PENDING = 'pending'; // 견적대기 (현장설명회에서 자동생성)

    public const STATUS_DRAFT = 'draft';

    public const STATUS_SENT = 'sent';

    public const STATUS_APPROVED = 'approved';

    public const STATUS_REJECTED = 'rejected';

    public const STATUS_FINALIZED = 'finalized';

    public const STATUS_CONVERTED = 'converted';

    public const STATUSES = [
        self::STATUS_PENDING,
        self::STATUS_DRAFT,
        self::STATUS_SENT,
        self::STATUS_APPROVED,
        self::STATUS_REJECTED,
        self::STATUS_FINALIZED,
        self::STATUS_CONVERTED,
    ];

    /**
     * 견적 품목들
     */
    public function items(): HasMany
    {
        return $this->hasMany(QuoteItem::class)->orderBy('sort_order');
    }

    /**
     * 수정 이력들
     */
    public function revisions(): HasMany
    {
        return $this->hasMany(QuoteRevision::class)->orderByDesc('revision_number');
    }

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

    /**
     * 품목 (통합 items 테이블)
     */
    public function item(): BelongsTo
    {
        return $this->belongsTo(Item::class, 'item_id');
    }

    /**
     * 전환된 수주 (Quote.order_id 기준)
     */
    public function order(): BelongsTo
    {
        return $this->belongsTo(Order::class);
    }

    /**
     * 이 견적을 참조하는 수주들 (Order.quote_id 기준)
     * 수주 전환 여부 확인 시 사용
     */
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class, 'quote_id');
    }

    /**
     * 현장설명회 (자동생성 시 연결)
     */
    public function siteBriefing(): BelongsTo
    {
        return $this->belongsTo(SiteBriefing::class);
    }

    /**
     * 확정자
     */
    public function finalizer(): BelongsTo
    {
        return $this->belongsTo(User::class, 'finalized_by');
    }

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

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

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

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

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

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

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

    public function scopeConverted($query)
    {
        return $query->whereNotNull('order_id');
    }

    /**
     * 확정된 견적 스코프
     */
    public function scopeIsFinal($query)
    {
        return $query->where('is_final', true);
    }

    /**
     * 제품 카테고리별 스코프
     */
    public function scopeScreen($query)
    {
        return $query->where('product_category', self::CATEGORY_SCREEN);
    }

    public function scopeSteel($query)
    {
        return $query->where('product_category', self::CATEGORY_STEEL);
    }

    /**
     * 견적 유형별 스코프
     */
    public function scopeManufacturing($query)
    {
        return $query->where('quote_type', self::TYPE_MANUFACTURING);
    }

    public function scopeConstruction($query)
    {
        return $query->where('quote_type', self::TYPE_CONSTRUCTION);
    }

    public function scopeOfType($query, string $type)
    {
        return $query->where('quote_type', $type);
    }

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

        return $query;
    }

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

        return $query->where(function ($q) use ($keyword) {
            $q->where('quote_number', 'like', "%{$keyword}%")
                ->orWhere('client_name', 'like', "%{$keyword}%")
                ->orWhere('manager', 'like', "%{$keyword}%")
                ->orWhere('site_name', 'like', "%{$keyword}%")
                ->orWhere('product_name', 'like', "%{$keyword}%");
        });
    }

    /**
     * 수정 가능 여부 확인
     * - 모든 상태에서 수정 가능 (finalized, converted 포함)
     * - 수주 전환된 견적 수정 시 연결된 수주도 함께 동기화됨
     */
    public function isEditable(): bool
    {
        return true;
    }

    /**
     * 상태 접근자: order_id가 존재하면 자동으로 'converted' 반환
     * DB에 status='converted'를 저장하지 않고, 수주 존재 여부로 판별
     */
    public function getStatusAttribute($value): string
    {
        if ($this->order_id) {
            return self::STATUS_CONVERTED;
        }

        return $value;
    }

    /**
     * 삭제 가능 여부 확인
     */
    public function isDeletable(): bool
    {
        if ($this->order_id) {
            return false;
        }

        return $this->getRawOriginal('status') !== self::STATUS_FINALIZED;
    }

    /**
     * 확정 가능 여부 확인
     */
    public function isFinalizable(): bool
    {
        return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_SENT, self::STATUS_APPROVED])
            && ! $this->is_final;
    }

    /**
     * 수주 전환 가능 여부 확인
     */
    public function isConvertible(): bool
    {
        return $this->status === self::STATUS_FINALIZED && $this->is_final;
    }
}
