<?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 PurchaseOrder extends Model
{
    use HasFactory, HasScopes, SoftDeletes, HasAuditFields;

    /**
     * Status constants
     */
    public const STATUS_DRAFT = 'draft';
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';
    public const STATUS_RECEIVED = 'received';
    public const STATUS_CANCELLED = 'cancelled';

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

    protected $fillable = [
        'purchase_order_no',
        'purchase_order_date',
        'grn_no',
        'quotation_no',
        'quotation_date',
        'customer_ref_no',
        'company_name',
        'vendor_id',
        'company_address',
        'company_gstn',
        'company_phone',
        'company_email',
        'bill_address',
        'ship_address',
        'product_type',
        'inr_in_words',
        'subtotal',
        'sgst_amount',
        'cgst_amount',
        'igst_amount',
        'round_up',
        'grand_total',
        'rfq_no',
        'rfq_date',
        'description',
        'delivery_terms',
        'additional_charges',
        'note',
        'vendor_po_file_path',
        'status',
        'approved_by',
        'approved_at',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'purchase_order_date' => 'date',
        'quotation_date' => 'date',
        'rfq_date' => 'date',
        'approved_at' => 'datetime',
        'subtotal' => 'decimal:2',
        'sgst_amount' => 'decimal:2',
        'cgst_amount' => 'decimal:2',
        'igst_amount' => 'decimal:2',
        'round_up' => 'decimal:2',
        'grand_total' => 'decimal:2',
        'additional_charges' => 'decimal:2',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

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

    /**
     * Order items
     */
    public function items()
    {
        return $this->hasMany(PurchaseOrderItem::class);
    }

    /**
     * Related quotation
     */
    public function quotation()
    {
        return $this->belongsTo(PurchaseQuotation::class, 'quotation_no', 'quotation_no');
    }

    /**
     * Vendor relationship
     */
    public function vendor()
    {
        return $this->belongsTo(CustomerVendor::class, 'vendor_id', 'id');
    }

    /**
     * Purchase invoice
     */
    public function purchase()
    {
        return $this->hasOne(Purchase::class, 'purchase_order_no', 'purchase_order_no');
    }

    /**
     * GRN for this order
     */
    public function grn()
    {
        return $this->hasOne(Grn::class, 'order_no', 'purchase_order_no');
    }

    /**
     * Approver
     */
    public function approver()
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

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

    /**
     * Filter draft orders
     */
    public function scopeDraft(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_DRAFT);
    }

    /**
     * Filter pending approval
     */
    public function scopePendingApproval(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Filter approved orders
     */
    public function scopeApprovedOnly(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    /**
     * Filter received orders
     */
    public function scopeReceived(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_RECEIVED);
    }

    /**
     * Filter by vendor
     */
    public function scopeForVendor(Builder $query, int $vendorId): Builder
    {
        return $query->where('vendor_id', $vendorId);
    }

    /**
     * Filter orders awaiting GRN
     */
    public function scopeAwaitingGrn(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_APPROVED)
                     ->whereDoesntHave('grn');
    }

    /**
     * Search by PO number or vendor
     */
    public function scopeSearchOrder(Builder $query, string $term): Builder
    {
        return $query->where(function ($q) use ($term) {
            $q->where('purchase_order_no', 'LIKE', "%{$term}%")
              ->orWhere('customer_ref_no', 'LIKE', "%{$term}%")
              ->orWhereHas('vendor', function ($vq) use ($term) {
                  $vq->where('company', 'LIKE', "%{$term}%");
              });
        });
    }

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

    /**
     * Get all valid statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_DRAFT,
            self::STATUS_PENDING,
            self::STATUS_APPROVED,
            self::STATUS_REJECTED,
            self::STATUS_RECEIVED,
            self::STATUS_CANCELLED,
        ];
    }

    /**
     * Check if PO is approved
     */
    public function isApproved(): bool
    {
        return $this->status === self::STATUS_APPROVED;
    }

    /**
     * Check if PO is pending
     */
    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * Check if PO can be modified
     */
    public function canModify(): bool
    {
        return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_PENDING]);
    }

    /**
     * Check if GRN exists
     */
    public function hasGrn(): bool
    {
        return $this->grn()->exists();
    }

    /**
     * Approve the order
     */
    public function approve(int $userId): bool
    {
        return $this->update([
            'status' => self::STATUS_APPROVED,
            'approved_by' => $userId,
            'approved_at' => now(),
        ]);
    }

    /**
     * Reject the order
     */
    public function reject(int $userId): bool
    {
        return $this->update([
            'status' => self::STATUS_REJECTED,
            'approved_by' => $userId,
            'approved_at' => now(),
        ]);
    }

    /**
     * Calculate tax total
     */
    public function getTaxTotal(): float
    {
        return ($this->sgst_amount ?? 0) + ($this->cgst_amount ?? 0) + ($this->igst_amount ?? 0);
    }
}
