<?php

namespace Modules\SystemCore\App\Models;

use App\Traits\UserActionsTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\SystemCore\App\Enums\SupplierStatus;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;

class CoreSupplier extends Model implements AuditableContract
{
    use Auditable, HasFactory, SoftDeletes, UserActionsTrait;

    protected $table = 'core_suppliers';

    protected $fillable = [
        'supplier_code',
        'name',
        'company_name',
        'status',
        'email',
        'phone_number',
        'mobile',
        'website',
        'tax_number',
        'vat_number',
        'address',
        'city',
        'state',
        'country',
        'postal_code',
        'credit_limit',
        'payment_term_id',
        'currency_code',
        'lead_time_days',
        'minimum_order_value',
        'notes',
        'tags',
        'metadata',
        'is_active',
        'created_by_id',
        'updated_by_id',
    ];

    protected function casts(): array
    {
        return [
            'status' => SupplierStatus::class,
            'credit_limit' => 'decimal:2',
            'tags' => 'array',
            'metadata' => 'array',
            'is_active' => 'boolean',
        ];
    }

    /**
     * Get all addresses for this supplier
     */
    public function addresses(): HasMany
    {
        return $this->hasMany(CoreAddress::class, 'entity_id')
            ->where('entity_type', 'supplier');
    }

    /**
     * Get primary address
     */
    public function primaryAddress(): HasOne
    {
        return $this->hasOne(CoreAddress::class, 'entity_id')
            ->where('entity_type', 'supplier')
            ->where('is_primary', true);
    }

    /**
     * Get all contacts for this supplier
     */
    public function contacts(): HasMany
    {
        return $this->hasMany(CoreContact::class, 'entity_id')
            ->where('entity_type', 'supplier');
    }

    /**
     * Get primary contact
     */
    public function primaryContact(): HasOne
    {
        return $this->hasOne(CoreContact::class, 'entity_id')
            ->where('entity_type', 'supplier')
            ->where('is_primary', true);
    }

    /**
     * Get payment term
     */
    public function paymentTerm(): BelongsTo
    {
        return $this->belongsTo(CorePaymentTerm::class, 'payment_term_id');
    }

    /**
     * Get purchase orders
     */
    public function purchaseOrders(): HasMany
    {
        return $this->hasMany(CorePurchaseOrder::class, 'supplier_id');
    }

    /**
     * Alias for purchaseOrders() - for backward compatibility with VendorController
     */
    public function purchases(): HasMany
    {
        return $this->purchaseOrders();
    }

    /**
     * Get all documents for this supplier
     */
    public function documents(): HasMany
    {
        return $this->hasMany(SupplierDocument::class, 'supplier_id');
    }

    /**
     * Get full address string
     */
    public function getFullAddressAttribute(): ?string
    {
        $parts = array_filter([
            $this->address,
            $this->city,
            $this->state,
            $this->postal_code,
            $this->country,
        ]);

        return ! empty($parts) ? implode(', ', $parts) : null;
    }

    /**
     * Scope for active suppliers
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true)
            ->where('status', SupplierStatus::Active);
    }

    /**
     * Generate supplier code using settings
     */
    public static function generateSupplierCode(): string
    {
        $settingsService = app(\App\Services\Settings\ModuleSettingsService::class);
        $prefix = $settingsService->get('SystemCore', 'supplier_prefix', 'SUPP');
        $padding = (int) $settingsService->get('SystemCore', 'supplier_code_padding', 6);

        $lastSupplier = self::orderBy('id', 'desc')->first();
        $nextId = $lastSupplier ? $lastSupplier->id + 1 : 1;

        return $prefix.'-'.str_pad((string) $nextId, $padding, '0', STR_PAD_LEFT);
    }

    /**
     * Boot method
     */
    protected static function booted()
    {
        static::creating(function (CoreSupplier $supplier) {
            if (! $supplier->supplier_code) {
                $supplier->supplier_code = self::generateSupplierCode();
            }
        });
    }
}
