<?php

namespace App\Models;

use App\Models\Traits\HasApproval;
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 RouteCard extends Model
{
    use HasFactory, HasScopes, HasApproval, SoftDeletes, HasAuditFields;

    protected $table = 'route_cards';

    /**
     * Status constants
     */
    public const STATUS_DRAFT = 'draft';
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_IN_PROGRESS = 'in_progress';
    public const STATUS_COMPLETED = 'completed';
    public const STATUS_ON_HOLD = 'on_hold';

    /**
     * Priority constants
     */
    public const PRIORITY_LOW = 'low';
    public const PRIORITY_NORMAL = 'normal';
    public const PRIORITY_HIGH = 'high';
    public const PRIORITY_URGENT = 'urgent';

    /**
     * Custom column mapping for HasScopes trait
     */
    protected string $dateColumn = 'route_date';
    protected string $approvalStatusColumn = 'approval_status';

    protected $fillable = [
        'route_no',
        'route_date',
        'grn_no',
        'grn_date',
        'order_no',
        'order_date',
        'company_name',
        'company_address',
        'company_gstn',
        'company_email',
        'company_phone',
        'order_ref_no',
        'quotation_no',
        'quotation_date',
        'rfq_no',
        'rfq_date',
        'part_no',
        'project_material_no',
        'drawing_no',
        'drawing_rev',
        'description',
        'product_type',
        'project_start_date',
        'created_by',
        'updated_by',
        'status',
        'approved_by',
        'approved_at',
        'priority',
        'approval_status',
    ];

    protected $casts = [
        'route_date' => 'date',
        'grn_date' => 'date',
        'order_date' => 'date',
        'quotation_date' => 'date',
        'rfq_date' => 'date',
        'project_start_date' => 'date',
        'approved_at' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

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

    /**
     * Route card processes
     */
    public function processes()
    {
        return $this->hasMany(RouteCardProcess::class, 'route_card_id');
    }

    /**
     * Related sales order
     */
    public function salesOrder()
    {
        return $this->belongsTo(SalesOrder::class, 'order_no', 'sales_order_no');
    }

    /**
     * Creator of this route card
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * QC approvals for all processes
     */
    public function qcApprovals()
    {
        return $this->hasManyThrough(
            QcApproval::class,
            RouteCardProcess::class,
            'route_card_id',
            'process_id',
            'id',
            'id'
        );
    }

    /**
     * Manufacturing plans associated with this route card
     */
    public function manufacturingPlans()
    {
        return $this->hasMany(ManufacturingPlan::class, 'rc_id');
    }

    /**
     * Get the active manufacturing plan
     */
    public function activeManufacturingPlan()
    {
        return $this->hasOne(ManufacturingPlan::class, 'rc_id')
            ->whereNotIn('status', [ManufacturingPlan::STATUS_COMPLETED]);
    }

    /**
     * Quality control records for this route card
     */
    public function qualityControls()
    {
        return $this->hasMany(QualityControl::class, 'route_card_id');
    }

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

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

    /**
     * Filter in progress
     */
    public function scopeInProgress(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_IN_PROGRESS);
    }

    /**
     * Filter completed
     */
    public function scopeCompleted(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_COMPLETED);
    }

    /**
     * Filter on hold
     */
    public function scopeOnHold(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_ON_HOLD);
    }

    /**
     * Filter by priority
     */
    public function scopeWithPriority(Builder $query, string $priority): Builder
    {
        return $query->where('priority', $priority);
    }

    /**
     * Filter urgent items
     */
    public function scopeUrgent(Builder $query): Builder
    {
        return $query->where('priority', self::PRIORITY_URGENT);
    }

    /**
     * Filter high priority
     */
    public function scopeHighPriority(Builder $query): Builder
    {
        return $query->whereIn('priority', [self::PRIORITY_HIGH, self::PRIORITY_URGENT]);
    }

    /**
     * Search by route number or part
     */
    public function scopeSearchRoute(Builder $query, string $term): Builder
    {
        return $query->where(function ($q) use ($term) {
            $q->where('route_no', 'LIKE', "%{$term}%")
              ->orWhere('part_no', 'LIKE', "%{$term}%")
              ->orWhere('order_no', 'LIKE', "%{$term}%")
              ->orWhere('description', 'LIKE', "%{$term}%");
        });
    }

    /**
     * Filter by start date range
     */
    public function scopeStartingBetween(Builder $query, string $from, string $to): Builder
    {
        return $query->whereBetween('project_start_date', [$from, $to]);
    }

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

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

    /**
     * Get all priority levels
     */
    public static function getPriorities(): array
    {
        return [
            self::PRIORITY_LOW,
            self::PRIORITY_NORMAL,
            self::PRIORITY_HIGH,
            self::PRIORITY_URGENT,
        ];
    }

    /**
     * Get completion percentage
     */
    public function getCompletionPercentage(): float
    {
        $total = $this->processes()->count();
        if ($total === 0) {
            return 0;
        }

        $completed = $this->processes()->where('status', 'completed')->count();
        return round(($completed / $total) * 100, 2);
    }

    /**
     * Get current active process
     */
    public function getCurrentProcess()
    {
        return $this->processes()
            ->whereIn('status', ['in_progress', 'qc_before', 'qc_during', 'qc_after'])
            ->first();
    }

    /**
     * Get next pending process
     */
    public function getNextPendingProcess()
    {
        return $this->processes()
            ->where('status', 'pending')
            ->orderBy('id')
            ->first();
    }

    /**
     * Check if all processes are completed
     */
    public function allProcessesCompleted(): bool
    {
        return $this->processes()->where('status', '!=', 'completed')->count() === 0
            && $this->processes()->count() > 0;
    }

    /**
     * Check if can start production
     */
    public function canStartProduction(): bool
    {
        return $this->approval_status === self::STATUS_APPROVED
            && $this->status !== self::STATUS_COMPLETED;
    }

    /**
     * Get estimated completion date
     */
    public function getEstimatedCompletionDate()
    {
        $lastProcess = $this->processes()->orderBy('end_date', 'desc')->first();
        return $lastProcess?->end_date;
    }
}
