<?php

namespace App\Models\Warehouse\FixedAssets;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Warehouse\Supplier;
use App\Models\Warehouse\Project;
use App\Models\Warehouse\ProjectDivision;
use App\Models\User;
use Carbon\Carbon;

class FixedAsset extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'fixed_assets';

    protected $fillable = [
        'asset_code',
        'asset_name',
        'asset_tag',
        'serial_number',
        'model_number',
        'manufacturer',
        'category_id',
        'supplier_id',
        'purchase_order_number',
        'invoice_number',
        'invoice_date',
        'purchase_date',
        'purchase_price',
        'currency',
        'depreciation_method',
        'useful_life_years',
        'salvage_value',
        'current_book_value',
        'depreciation_start_date',
        'condition',
        'lifecycle_status',
        'current_project_id',
        'current_division_id',
        'current_location',
        'warranty_start_date',
        'warranty_end_date',
        'warranty_terms',
        'photo',
        'attached_documents',
        'status',
        'notes',
        'registered_by',
    ];

    protected $casts = [
        'purchase_price' => 'decimal:2',
        'salvage_value' => 'decimal:2',
        'current_book_value' => 'decimal:2',
        'purchase_date' => 'date',
        'invoice_date' => 'date',
        'depreciation_start_date' => 'date',
        'warranty_start_date' => 'date',
        'warranty_end_date' => 'date',
        'attached_documents' => 'array',
        'useful_life_years' => 'integer',
    ];

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($asset) {
            if (empty($asset->asset_code)) {
                $asset->asset_code = static::generateCode($asset->category_id);
            }
            if (empty($asset->depreciation_start_date) && $asset->purchase_date) {
                $asset->depreciation_start_date = $asset->purchase_date;
            }
            if ($asset->current_book_value === null) {
                $asset->current_book_value = $asset->purchase_price ?? 0;
            }
        });
    }

    public static function generateCode($categoryId = null): string
    {
        $prefix = 'FA-';
        if ($categoryId) {
            $category = FixedAssetCategory::find($categoryId);
            if ($category && $category->category_code) {
                $prefix = 'FA-' . strtoupper(substr($category->category_code, 0, 3));
            }
        }

        $last = static::where('asset_code', 'LIKE', $prefix . '%')
                      ->orderBy('asset_code', 'desc')
                      ->first();

        $seq = $last ? ((int) substr($last->asset_code, strlen($prefix)) + 1) : 1;

        return $prefix . str_pad($seq, 4, '0', STR_PAD_LEFT);
    }

    // Relationships

    public function category()
    {
        return $this->belongsTo(FixedAssetCategory::class, 'category_id');
    }

    public function supplier()
    {
        return $this->belongsTo(Supplier::class, 'supplier_id');
    }

    public function currentProject()
    {
        return $this->belongsTo(Project::class, 'current_project_id');
    }

    public function currentDivision()
    {
        return $this->belongsTo(ProjectDivision::class, 'current_division_id');
    }

    public function registeredByUser()
    {
        return $this->belongsTo(User::class, 'registered_by');
    }

    public function movements()
    {
        return $this->hasMany(FixedAssetMovement::class, 'fixed_asset_id');
    }

    public function maintenanceRecords()
    {
        return $this->hasMany(FixedAssetMaintenance::class, 'fixed_asset_id');
    }

    public function depreciationRecords()
    {
        return $this->hasMany(FixedAssetDepreciation::class, 'fixed_asset_id');
    }

    public function allocationItems()
    {
        return $this->hasMany(FixedAssetAllocationItem::class, 'fixed_asset_id');
    }

    public function returnItems()
    {
        return $this->hasMany(FixedAssetReturnItem::class, 'fixed_asset_id');
    }

    // Computed Attributes

    public function getAccumulatedDepreciationAttribute()
    {
        return $this->depreciationRecords()->sum('depreciation_amount');
    }

    public function getCurrentBookValueAttribute()
    {
        return max(0, $this->purchase_price - $this->accumulated_depreciation);
    }

    public function getIsUnderWarrantyAttribute()
    {
        return $this->warranty_end_date && $this->warranty_end_date->gte(Carbon::today());
    }

    public function getAgeInMonthsAttribute()
    {
        if (!$this->purchase_date) {
            return 0;
        }
        return $this->purchase_date->diffInMonths(Carbon::now());
    }

    public function getMonthlyDepreciationAttribute()
    {
        if ($this->useful_life_years <= 0) {
            return 0;
        }

        if ($this->depreciation_method === 'straight_line') {
            return round(($this->purchase_price - $this->salvage_value) / ($this->useful_life_years * 12), 2);
        }

        // Declining balance - uses current book value
        $rate = 2 / $this->useful_life_years;
        return round($rate * $this->current_book_value / 12, 2);
    }

    // Scopes

    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    public function scopeSearch($query, $search)
    {
        if (empty($search)) {
            return $query;
        }

        return $query->where(function ($q) use ($search) {
            $q->where('asset_code', 'LIKE', "%{$search}%")
              ->orWhere('asset_name', 'LIKE', "%{$search}%")
              ->orWhere('asset_tag', 'LIKE', "%{$search}%")
              ->orWhere('serial_number', 'LIKE', "%{$search}%")
              ->orWhere('manufacturer', 'LIKE', "%{$search}%")
              ->orWhere('model_number', 'LIKE', "%{$search}%")
              ->orWhereHas('category', function ($q2) use ($search) {
                  $q2->where('category_name', 'LIKE', "%{$search}%");
              });
        });
    }

    public function scopeInWarehouse($query)
    {
        return $query->whereIn('lifecycle_status', ['in_warehouse', 'returned']);
    }

    public function scopeInUse($query)
    {
        return $query->where('lifecycle_status', 'in_use');
    }

    public function scopeByCondition($query, $condition)
    {
        return $query->where('condition', $condition);
    }

    public function scopeByLifecycleStatus($query, $status)
    {
        return $query->where('lifecycle_status', $status);
    }

    public function scopeAvailableForAllocation($query)
    {
        return $query->whereIn('lifecycle_status', ['in_warehouse', 'returned'])
                     ->where('status', 'active');
    }

    public function scopeNeedsMaintenance($query)
    {
        return $query->where(function ($q) {
            $q->whereIn('condition', ['poor', 'damaged'])
              ->orWhereHas('maintenanceRecords', function ($q2) {
                  $q2->where('next_maintenance_date', '<=', Carbon::today())
                     ->where('status', '!=', 'completed');
              });
        });
    }

    public function scopeWarrantyExpiringSoon($query, $days = 30)
    {
        return $query->whereNotNull('warranty_end_date')
                     ->where('warranty_end_date', '>=', Carbon::today())
                     ->where('warranty_end_date', '<=', Carbon::today()->addDays($days));
    }
}
