<?php

namespace Fleetbase\FleetOps\Models;

use Fleetbase\Casts\Json;
use Fleetbase\Models\Model;
use Fleetbase\Traits\HasApiModelBehavior;
use Fleetbase\Traits\HasInternalId;
use Fleetbase\Traits\HasMetaAttributes;
use Fleetbase\Traits\HasPublicId;
use Fleetbase\Traits\HasUuid;
use Fleetbase\Traits\Searchable;
use Fleetbase\Traits\TracksApiCredential;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * Manifest.
 *
 * Represents a committed delivery plan for a specific vehicle and (optionally)
 * driver. Generated by the Orchestrator commit step. Each Manifest contains an
 * ordered list of ManifestStops representing the physical locations to visit.
 *
 * Status lifecycle:
 *   draft → active → in_progress → completed
 *                               ↘ cancelled
 */
class Manifest extends Model
{
    use HasUuid;
    use HasPublicId;
    use HasInternalId;
    use HasMetaAttributes;
    use HasApiModelBehavior;
    use TracksApiCredential;
    use Searchable;
    use SoftDeletes;

    /**
     * The database table used by the model.
     */
    protected $table = 'manifests';

    /**
     * The type of public ID to generate.
     */
    protected $publicIdType = 'manifest';

    /**
     * Columns that can be searched.
     */
    protected $searchableColumns = ['public_id', 'internal_id'];

    /**
     * Mass-assignable attributes.
     */
    protected $fillable = [
        'company_uuid',
        'driver_uuid',
        'vehicle_uuid',
        'status',
        'scheduled_date',
        'started_at',
        'completed_at',
        'total_distance_m',
        'total_duration_s',
        'stop_count',
        'notes',
        'meta',
    ];

    /**
     * Attribute casts.
     */
    protected $casts = [
        'meta'           => Json::class,
        'scheduled_date' => 'date',
        'started_at'     => 'datetime',
        'completed_at'   => 'datetime',
    ];

    /**
     * Attributes appended to the model's JSON representation.
     */
    protected $appends = [
        'driver_name',
        'vehicle_name',
        'completed_stops',
        'pending_stops',
    ];

    // ── Relationships ─────────────────────────────────────────────────────────

    /**
     * The driver assigned to this manifest.
     */
    public function driver(): BelongsTo
    {
        return $this->belongsTo(Driver::class, 'driver_uuid', 'uuid');
    }

    /**
     * The vehicle assigned to this manifest.
     */
    public function vehicle(): BelongsTo
    {
        return $this->belongsTo(Vehicle::class, 'vehicle_uuid', 'uuid');
    }

    /**
     * The ordered list of stops in this manifest.
     */
    public function stops(): HasMany
    {
        return $this->hasMany(ManifestStop::class, 'manifest_uuid', 'uuid')
            ->orderBy('sequence');
    }

    /**
     * The orders associated with this manifest (through stops).
     */
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class, 'manifest_uuid', 'uuid');
    }

    // ── Computed Attributes ───────────────────────────────────────────────────

    public function getDriverNameAttribute(): ?string
    {
        return $this->driver?->name;
    }

    public function getVehicleNameAttribute(): ?string
    {
        return $this->vehicle?->display_name;
    }

    public function getCompletedStopsAttribute(): int
    {
        return $this->stops()->where('status', 'completed')->count();
    }

    public function getPendingStopsAttribute(): int
    {
        return $this->stops()->whereIn('status', ['pending', 'arrived'])->count();
    }

    // ── Scopes ────────────────────────────────────────────────────────────────

    public function scopeForCompany($query, string $companyUuid)
    {
        return $query->where('company_uuid', $companyUuid);
    }

    public function scopeActive($query)
    {
        return $query->whereIn('status', ['active', 'in_progress']);
    }

    public function scopeForDriver($query, string $driverUuid)
    {
        return $query->where('driver_uuid', $driverUuid);
    }

    public function scopeForVehicle($query, string $vehicleUuid)
    {
        return $query->where('vehicle_uuid', $vehicleUuid);
    }

    // ── Business Logic ────────────────────────────────────────────────────────

    /**
     * Mark the manifest as in_progress and record the start time.
     */
    public function start(): self
    {
        $this->update(['status' => 'in_progress', 'started_at' => now()]);

        return $this;
    }

    /**
     * Mark the manifest as completed and record the completion time.
     */
    public function complete(): self
    {
        $this->update(['status' => 'completed', 'completed_at' => now()]);

        return $this;
    }

    /**
     * Cancel the manifest.
     */
    public function cancel(): self
    {
        $this->update(['status' => 'cancelled']);

        return $this;
    }

    /**
     * Check whether all stops are completed and auto-complete the manifest.
     */
    public function checkAndAutoComplete(): void
    {
        $pendingCount = $this->stops()->whereIn('status', ['pending', 'arrived'])->count();
        if ($pendingCount === 0 && $this->status === 'in_progress') {
            $this->complete();
        }
    }
}
