<?php

namespace App\Models;

use App\Models\Traits\HasAuditFields;
use App\Models\Traits\HasScopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Quotation extends Model
{
    use HasFactory, HasScopes, SoftDeletes, HasAuditFields;

    /**
     * Status constants for approval workflow
     */
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';

    /**
     * Custom column mapping for HasScopes trait
     */
    protected string $dateColumn = 'quotation_date';
    protected string $companyColumn = 'customer_name';

    protected $fillable = [
        'quotation_no',
        'quotation_date',
        'customer_name',
        'address',
        'gst',
        'phone',
        'email',
        'cust_ref_no',
        'rfq_no',
        'rfq_date',
        'part_no',
        'project_material_no',
        'drawing_no',
        'drawing_rev',
        'quantity',
        'quantity_uom',
        'description',
        'product_type',
        'note',
        'sub_total',
        'discount',
        'round_up',
        'grand_total',
        'raw_materials',
        'conversion_costs',
        'packing_charges',
        'status',
        'created_by',
        'updated_by',
        'approved_by',
        'approved_at',
        'rejection_reason',
    ];

    protected $casts = [
        'quotation_date' => 'date',
        'rfq_date' => 'date',
        'approved_at' => 'datetime',
        'raw_materials' => 'array',
        'conversion_costs' => 'array',
        'packing_charges' => 'array',
        'sub_total' => 'decimal:2',
        'discount' => 'decimal:2',
        'round_up' => 'decimal:2',
        'grand_total' => 'decimal:2',
        'quantity' => 'decimal:2',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    // ──────────────────────────────────────────────────────────────────────────
    // RELATIONSHIPS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Customer relationship
     */
    public function customer()
    {
        return $this->belongsTo(CustomerVendor::class, 'customer_name', 'id');
    }

    /**
     * Related RFQ
     */
    public function rfq()
    {
        return $this->belongsTo(Rfq::class, 'rfq_no', 'id');
    }

    /**
     * Sales orders created from this quotation
     */
    public function salesOrders()
    {
        return $this->hasMany(SalesOrder::class, 'quotation_no', 'quotation_no');
    }

    // ──────────────────────────────────────────────────────────────────────────
    // SCOPES
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Filter non-vendor quotations (customer quotations only)
     */
    public function scopeNonVendor(Builder $query, ?int $companyId = null): Builder
    {
        return $query->whereHas('customer', function ($q) use ($companyId) {
            $q->where('company_role', '!=', 'Vendor');
            if ($companyId) {
                $q->where('id', $companyId);
            }
        });
    }

    /**
     * Filter quotations with sales orders
     */
    public function scopeConverted(Builder $query): Builder
    {
        return $query->whereHas('salesOrders');
    }

    /**
     * Filter quotations without sales orders
     */
    public function scopeNotConverted(Builder $query): Builder
    {
        return $query->whereDoesntHave('salesOrders');
    }

    /**
     * Search by quotation number or customer
     */
    public function scopeSearchQuotation(Builder $query, string $term): Builder
    {
        return $query->where(function ($q) use ($term) {
            $q->where('quotation_no', 'LIKE', "%{$term}%")
              ->orWhere('cust_ref_no', 'LIKE', "%{$term}%")
              ->orWhere('part_no', 'LIKE', "%{$term}%")
              ->orWhereHas('customer', function ($cq) use ($term) {
                  $cq->where('company', 'LIKE', "%{$term}%");
              });
        });
    }

    /**
     * Filter by product type
     */
    public function scopeOfProductType(Builder $query, string $type): Builder
    {
        return $query->where('product_type', $type);
    }

    /**
     * Filter by amount range
     */
    public function scopeAmountBetween(Builder $query, float $min, float $max): Builder
    {
        return $query->whereBetween('grand_total', [$min, $max]);
    }

    // ──────────────────────────────────────────────────────────────────────────
    // ACCESSORS & HELPERS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Check if converted to sales order
     */
    public function isConverted(): bool
    {
        return $this->salesOrders()->exists();
    }

    /**
     * Get raw materials total cost
     */
    public function getRawMaterialsCost(): float
    {
        if (!$this->raw_materials) {
            return 0;
        }

        return collect($this->raw_materials)->sum('total') ?? 0;
    }

    /**
     * Get conversion costs total
     */
    public function getConversionCostsTotal(): float
    {
        if (!$this->conversion_costs) {
            return 0;
        }

        return collect($this->conversion_costs)->sum('total') ?? 0;
    }

    /**
     * Get packing charges total
     */
    public function getPackingChargesTotal(): float
    {
        if (!$this->packing_charges) {
            return 0;
        }

        return collect($this->packing_charges)->sum('total') ?? 0;
    }

    /**
     * Get discount percentage
     */
    public function getDiscountPercentage(): float
    {
        if ($this->sub_total == 0) {
            return 0;
        }

        return round(($this->discount / $this->sub_total) * 100, 2);
    }

    // ──────────────────────────────────────────────────────────────────────────
    // STATUS HELPERS
    // ──────────────────────────────────────────────────────────────────────────

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

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

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

    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    public function isApproved(): bool
    {
        return $this->status === self::STATUS_APPROVED;
    }

    public function isRejected(): bool
    {
        return $this->status === self::STATUS_REJECTED;
    }

    /**
     * Approve this quotation
     */
    public function approve(int $userId): bool
    {
        if (!$this->isPending()) {
            return false;
        }

        $this->status = self::STATUS_APPROVED;
        $this->approved_by = $userId;
        $this->approved_at = now();
        return $this->save();
    }

    /**
     * Reject this quotation
     */
    public function reject(int $userId, ?string $reason = null): bool
    {
        if (!$this->isPending()) {
            return false;
        }

        $this->status = self::STATUS_REJECTED;
        $this->approved_by = $userId;
        $this->approved_at = now();
        $this->rejection_reason = $reason;
        return $this->save();
    }

    /**
     * Get approved by user relationship
     */
    public function approver()
    {
        return $this->belongsTo(User::class, 'approved_by');
    }
}
