<?php

namespace App\Models\Orders;

use App\Models\Items\Item;
use App\Models\Production\WorkOrder;
use App\Models\Products\CommonCode;
use App\Models\Quote\Quote;
use App\Models\Tenants\Sale;
use App\Models\Tenants\Shipment;
use App\Traits\Auditable;
use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * 수주 마스터 (Orders)
 *
 * @mixin IdeHelperOrder
 */
class Order extends Model
{
    use Auditable, BelongsToTenant, SoftDeletes;

    // 상태 코드
    public const STATUS_DRAFT = 'DRAFT';

    public const STATUS_CONFIRMED = 'CONFIRMED';

    public const STATUS_IN_PROGRESS = 'IN_PROGRESS';

    public const STATUS_IN_PRODUCTION = 'IN_PRODUCTION';  // 생산중

    public const STATUS_PRODUCED = 'PRODUCED';            // 생산완료

    public const STATUS_SHIPPING = 'SHIPPING';            // 출하중

    public const STATUS_SHIPPED = 'SHIPPED';              // 출하완료

    public const STATUS_COMPLETED = 'COMPLETED';

    public const STATUS_CANCELLED = 'CANCELLED';

    /**
     * 전체 상태 목록
     */
    public const STATUSES = [
        self::STATUS_DRAFT,
        self::STATUS_CONFIRMED,
        self::STATUS_IN_PROGRESS,
        self::STATUS_IN_PRODUCTION,
        self::STATUS_PRODUCED,
        self::STATUS_SHIPPING,
        self::STATUS_SHIPPED,
        self::STATUS_COMPLETED,
        self::STATUS_CANCELLED,
    ];

    /**
     * 상태 라벨
     */
    public const STATUS_LABELS = [
        self::STATUS_DRAFT => '임시저장',
        self::STATUS_CONFIRMED => '확정',
        self::STATUS_IN_PROGRESS => '진행중',
        self::STATUS_IN_PRODUCTION => '생산중',
        self::STATUS_PRODUCED => '생산완료',
        self::STATUS_SHIPPING => '출하중',
        self::STATUS_SHIPPED => '출하완료',
        self::STATUS_COMPLETED => '완료',
        self::STATUS_CANCELLED => '취소',
    ];

    // 주문 유형
    public const TYPE_ORDER = 'ORDER'; // 수주

    public const TYPE_PURCHASE = 'PURCHASE'; // 발주

    // 매출 인식 시점
    public const SALES_ON_ORDER_CONFIRM = 'on_order_confirm'; // 수주확정 시

    public const SALES_ON_SHIPMENT = 'on_shipment';           // 출하완료 시

    public const SALES_MANUAL = 'manual';                     // 수동 등록

    public const SALES_RECOGNITION_TYPES = [
        self::SALES_ON_ORDER_CONFIRM => '수주확정 시',
        self::SALES_ON_SHIPMENT => '출하완료 시',
        self::SALES_MANUAL => '수동 등록',
    ];

    protected $table = 'orders';

    protected $fillable = [
        'tenant_id',
        'quote_id',
        'order_no',
        'order_type_code',
        'status_code',
        'category_code',
        'item_id',
        'received_at',
        'writer_id',
        'client_id',
        'client_name',
        'client_contact',
        'site_name',
        'quantity',
        // 금액 정보
        'supply_amount',
        'tax_amount',
        'total_amount',
        'discount_rate',
        'discount_amount',
        // 기타
        'delivery_date',
        'delivery_method_code',
        'memo',
        'remarks',
        'note',
        'options',
        // 매출 연동
        'sales_recognition',
        'sale_id',
        // 감사
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    protected $casts = [
        'quantity' => 'decimal:4',
        'supply_amount' => 'decimal:2',
        'tax_amount' => 'decimal:2',
        'total_amount' => 'decimal:2',
        'discount_rate' => 'decimal:2',
        'discount_amount' => 'decimal:2',
        'received_at' => 'datetime',
        'delivery_date' => 'date',
        'options' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * JSON 응답에 자동 포함할 accessor
     */
    protected $appends = [
        'delivery_method_label',
        'shipping_cost_label',
    ];

    /**
     * 수주 상세 품목
     */
    public function items(): HasMany
    {
        return $this->hasMany(OrderItem::class)->orderBy('sort_order');
    }

    /**
     * 수주 노드 (전체, depth/sort_order 순)
     */
    public function nodes(): HasMany
    {
        return $this->hasMany(OrderNode::class)->orderBy('depth')->orderBy('sort_order');
    }

    /**
     * 수주 루트 노드 (parent_id가 NULL인 최상위)
     */
    public function rootNodes(): HasMany
    {
        return $this->hasMany(OrderNode::class)->whereNull('parent_id')->orderBy('sort_order');
    }

    /**
     * 수주 이력
     */
    public function histories(): HasMany
    {
        return $this->hasMany(OrderHistory::class);
    }

    /**
     * 수주 버전
     */
    public function versions(): HasMany
    {
        return $this->hasMany(OrderVersion::class);
    }

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

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

    /**
     * 작성자 (담당자)
     */
    public function writer(): BelongsTo
    {
        return $this->belongsTo(\App\Models\Members\User::class, 'writer_id');
    }

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

    /**
     * 작업지시 목록
     */
    public function workOrders(): HasMany
    {
        return $this->hasMany(WorkOrder::class, 'sales_order_id');
    }

    /**
     * 출하 목록
     */
    public function shipments(): HasMany
    {
        return $this->hasMany(Shipment::class, 'order_id');
    }

    /**
     * 연결된 매출
     */
    public function sale(): BelongsTo
    {
        return $this->belongsTo(Sale::class);
    }

    /**
     * 이 수주에서 생성된 모든 매출 (출하별 포함)
     */
    public function sales(): HasMany
    {
        return $this->hasMany(Sale::class, 'order_id');
    }

    /**
     * 매출 인식 시점 라벨
     */
    public function getSalesRecognitionLabelAttribute(): string
    {
        return self::SALES_RECOGNITION_TYPES[$this->sales_recognition] ?? '출하완료 시';
    }

    /**
     * 배송방식 라벨 (common_codes 테이블에서 조회)
     */
    public function getDeliveryMethodLabelAttribute(): string
    {
        return CommonCode::getLabel('delivery_method', $this->delivery_method_code);
    }

    /**
     * 운임비용 라벨 (common_codes 테이블에서 조회)
     */
    public function getShippingCostLabelAttribute(): string
    {
        $shippingCostCode = $this->options['shipping_cost_code'] ?? null;

        return $shippingCostCode ? CommonCode::getLabel('shipping_cost', $shippingCostCode) : '';
    }

    /**
     * 수주확정 시 매출 생성 여부
     */
    public function shouldCreateSaleOnConfirm(): bool
    {
        return $this->sales_recognition === self::SALES_ON_ORDER_CONFIRM;
    }

    /**
     * 출하완료 시 매출 생성 여부
     */
    public function shouldCreateSaleOnShipment(): bool
    {
        return $this->sales_recognition === self::SALES_ON_SHIPMENT;
    }

    /**
     * 품목들로부터 금액 합계 재계산
     */
    public function recalculateTotals(): self
    {
        $this->supply_amount = $this->items->sum('supply_amount');
        $this->tax_amount = $this->items->sum('tax_amount');
        $this->total_amount = $this->items->sum('total_amount');
        $this->quantity = $this->items->sum('quantity');

        return $this;
    }

    /**
     * 견적에서 수주 생성
     */
    public static function createFromQuote(Quote $quote, string $orderNo): self
    {
        return new self([
            'tenant_id' => $quote->tenant_id,
            'quote_id' => $quote->id,
            'order_no' => $orderNo,
            'order_type_code' => self::TYPE_ORDER,
            'status_code' => self::STATUS_DRAFT,
            'client_id' => $quote->client_id,
            'client_name' => $quote->client?->name,
            'client_contact' => $quote->contact,
            'site_name' => $quote->site_name,
            'quantity' => $quote->items->sum('calculated_quantity'),
            'supply_amount' => $quote->total_amount,
            'tax_amount' => round($quote->total_amount * 0.1, 2),
            'total_amount' => round($quote->total_amount * 1.1, 2),
            'delivery_date' => $quote->completion_date,
            'memo' => $quote->remarks,
            'options' => [
                'manager_name' => $quote->manager,
            ],
        ]);
    }
}
