<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class NumberingFormat extends Model
{
    use HasFactory;

    protected $table = 'm_numbering_formats';
    
    protected $fillable = [
        'store_id',
        'spb_type',        // Regular atau Non-Regular
        'tipe_dokumen',    // DO, PO, atau PR
        'tipe_barang',     // Basah atau Kering
        'current_number',  // Nomor urut terakhir
        'last_reset_date', // Tanggal terakhir reset (untuk reset monthly)
        'is_active',
        'delete_flag',
        'created_by',
        'updated_by'
    ];

    protected $casts = [
        'current_number' => 'integer',
        'last_reset_date' => 'date',
        'is_active' => 'boolean',
        'delete_flag' => 'boolean'
    ];

    // SPB Types
    const SPB_TYPE_REGULAR = 'Regular';
    const SPB_TYPE_NON_REGULAR = 'Non-Regular';

    // Tipe Dokumen (dari mapping store-item)
    const TIPE_DOKUMEN_DO = 'DO';
    const TIPE_DOKUMEN_PO = 'PO';
    const TIPE_DOKUMEN_PR = 'PR';

    // Tipe Barang (dari raw material)
    const TIPE_BARANG_BASAH = 'Basah';
    const TIPE_BARANG_KERING = 'Kering';

    // Scope untuk data aktif
    public function scopeActive($query)
    {
        return $query->where('delete_flag', false);
    }

    // Scope untuk data yang aktif dan enabled
    public function scopeEnabled($query)
    {
        return $query->where('delete_flag', false)->where('is_active', true);
    }

    // Scope untuk store tertentu
    public function scopeForStore($query, $storeId)
    {
        return $query->where('store_id', $storeId);
    }

    // Scope untuk SPB type tertentu
    public function scopeForSpbType($query, $spbType)
    {
        return $query->where('spb_type', $spbType);
    }

    // Scope untuk tipe dokumen tertentu
    public function scopeForTipeDokumen($query, $tipeDokumen)
    {
        return $query->where('tipe_dokumen', $tipeDokumen);
    }

    // Scope untuk tipe barang tertentu
    public function scopeForTipeBarang($query, $tipeBarang)
    {
        return $query->where('tipe_barang', $tipeBarang);
    }

    // Relationship dengan store
    public function store()
    {
        return $this->belongsTo(Store::class, 'store_id');
    }

    // Relationship dengan user yang membuat
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    // Relationship dengan user yang mengupdate
    public function modificator()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    // Helper methods
    public function isEnabled()
    {
        return $this->is_active && !$this->delete_flag;
    }

    public function getStatusAttribute()
    {
        if ($this->delete_flag) {
            return 'Deleted';
        }
        return $this->is_active ? 'Active' : 'Inactive';
    }

    public function getStatusBadgeAttribute()
    {
        switch ($this->status) {
            case 'Active':
                return 'badge-success';
            case 'Inactive':
                return 'badge-secondary';
            case 'Deleted':
                return 'badge-danger';
            default:
                return 'badge-secondary';
        }
    }

    public function getDocumentTypeBadgeAttribute()
    {
        switch ($this->document_type) {
            case self::DOC_TYPE_SPB:
                return 'badge-primary';
            case self::DOC_TYPE_SO:
                return 'badge-info';
            case self::DOC_TYPE_PO:
                return 'badge-secondary';
            case self::DOC_TYPE_DO:
                return 'badge-success';
            default:
                return 'badge-secondary';
        }
    }

    // Check if reset is needed (always monthly for SPB)
    public function needsReset()
    {
        if (!$this->last_reset_date) {
            return true;
        }

        $now = Carbon::now();
        $lastReset = Carbon::parse($this->last_reset_date);

        // Reset setiap bulan berganti
        return $lastReset->month !== $now->month || $lastReset->year !== $now->year;
    }

    // Reset counter if needed
    public function resetIfNeeded()
    {
        if ($this->needsReset()) {
            $this->update([
                'current_number' => 0,
                'last_reset_date' => Carbon::now()->format('Y-m-d')
            ]);
        }
    }

    // Generate next SPB number
    public function generateNextNumber()
    {
        // Check if reset is needed
        $this->resetIfNeeded();

        // Increment counter
        $this->increment('current_number');
        
        // Generate formatted number
        return $this->formatNumber($this->current_number);
    }

    // Format SPB number: SPB-{SPBTYPE}-{DOCTYPE}-{ITEMTYPE}-{YYMM}-{NUMBER}
    public function formatNumber($number)
    {
        $now = Carbon::now();
        
        // SPB Type: REG atau NONREG
        $spbTypeCode = $this->spb_type === 'Regular' ? 'REG' : 'NONREG';
        
        // Tipe Dokumen: DO, PO, atau PR
        $docTypeCode = $this->tipe_dokumen; // DO, PO, PR
        
        // Tipe Barang: B (Basah) atau K (Kering)
        $itemTypeCode = $this->tipe_barang === 'Basah' ? 'B' : 'K';
        
        // YYMM: Tahun-Bulan
        $yearMonth = $now->format('ym'); // 2601 untuk Januari 2026
        
        // NUMBER: 4 digit dengan padding 0
        $paddedNumber = str_pad($number, 4, '0', STR_PAD_LEFT);
        
        // Format: SPB-REG-DO-B-2601-0001
        return "SPB-{$spbTypeCode}-{$docTypeCode}-{$itemTypeCode}-{$yearMonth}-{$paddedNumber}";
    }

    // Preview format with sample number
    public function previewFormat($sampleNumber = 1)
    {
        return $this->formatNumber($sampleNumber);
    }

    // Get next number preview without incrementing
    public function getNextNumberPreview()
    {
        $nextNumber = $this->current_number + 1;
        return $this->formatNumber($nextNumber);
    }

    // Static method to generate SPB number
    public static function generateSPBNumber($storeId, $spbType, $tipeDokumen, $tipeBarang)
    {
        $format = static::enabled()
            ->forStore($storeId)
            ->forSpbType($spbType)
            ->forTipeDokumen($tipeDokumen)
            ->forTipeBarang($tipeBarang)
            ->first();

        if (!$format) {
            // Create default format if not exists
            $format = static::createDefaultFormat($storeId, $spbType, $tipeDokumen, $tipeBarang);
        }

        return $format->generateNextNumber();
    }

    // Create default format
    public static function createDefaultFormat($storeId, $spbType, $tipeDokumen, $tipeBarang)
    {
        return static::create([
            'store_id' => $storeId,
            'spb_type' => $spbType,
            'tipe_dokumen' => $tipeDokumen,
            'tipe_barang' => $tipeBarang,
            'current_number' => 0,
            'last_reset_date' => Carbon::now()->format('Y-m-d'),
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => auth()->id()
        ]);
    }

    // Get available SPB types
    public static function getSpbTypes()
    {
        return [
            self::SPB_TYPE_REGULAR => 'Regular',
            self::SPB_TYPE_NON_REGULAR => 'Non-Regular'
        ];
    }

    // Get available tipe dokumen
    public static function getTipeDokumen()
    {
        return [
            self::TIPE_DOKUMEN_DO => 'DO (Delivery Order)',
            self::TIPE_DOKUMEN_PO => 'PO (Purchase Order)',
            self::TIPE_DOKUMEN_PR => 'PR (Purchase Request)'
        ];
    }

    // Get available tipe barang
    public static function getTipeBarang()
    {
        return [
            self::TIPE_BARANG_BASAH => 'Basah',
            self::TIPE_BARANG_KERING => 'Kering'
        ];
    }

    // Get format description
    public function getFormatDescriptionAttribute()
    {
        $spbTypeCode = $this->spb_type === 'Regular' ? 'REG' : 'NONREG';
        $itemTypeCode = $this->tipe_barang === 'Basah' ? 'B' : 'K';
        
        return "SPB-{$spbTypeCode}-{$this->tipe_dokumen}-{$itemTypeCode}-YYMM-XXXX";
    }
}