<?php

namespace App\Models;

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

class Dispute extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'reference',
        'booking_id',
        'booking_item_id',
        'raised_by',
        'against_user_id',
        'media_owner_id',
        'reason',
        'reason_label',
        'description',
        'status',
        'resolution_notes',
        'resolution_outcome',
        'refund_amount',
        'penalty_amount',
        'assigned_to',
        'resolved_at',
        'resolved_by',
        'payout_held',
        'payout_held_at',
        'payout_released_at',
    ];

    protected $casts = [
        'refund_amount'       => 'decimal:2',
        'penalty_amount'      => 'decimal:2',
        'payout_held'         => 'boolean',
        'resolved_at'         => 'datetime',
        'payout_held_at'      => 'datetime',
        'payout_released_at'  => 'datetime',
    ];

    // ============================================================
    // Boot — auto generate reference
    // ============================================================
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($dispute) {
            if (empty($dispute->reference)) {
                $latest = static::withTrashed()->latest('id')->first();
                $next   = $latest ? $latest->id + 1 : 1;
                $dispute->reference = 'DSP-' . str_pad($next, 6, '0', STR_PAD_LEFT);
            }
        });
    }

    // ============================================================
    // Scopes
    // ============================================================
    public function scopeOpen($query)
    {
        return $query->where('status', 'open');
    }

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

    public function scopeResolved($query)
    {
        return $query->whereIn('status', [
            'resolved_advertiser',
            'resolved_owner',
            'resolved_split',
            'closed',
        ]);
    }

    public function scopeUnresolved($query)
    {
        return $query->whereIn('status', [
            'open',
            'under_review',
            'awaiting_response',
        ]);
    }

    public function scopeAssignedTo($query, int $userId)
    {
        return $query->where('assigned_to', $userId);
    }

    // ============================================================
    // Helpers
    // ============================================================
    public function isOpen(): bool
    {
        return $this->status === 'open';
    }

    public function isUnderReview(): bool
    {
        return $this->status === 'under_review';
    }

    public function isResolved(): bool
    {
        return in_array($this->status, [
            'resolved_advertiser',
            'resolved_owner',
            'resolved_split',
            'closed',
        ]);
    }

    public function isPayoutHeld(): bool
    {
        return $this->payout_held === true;
    }

    public function getReasonLabel(): string
    {
        return match($this->reason) {
            'proof_missing'      => 'Proof Missing',
            'proof_late'         => 'Proof Late',
            'wrong_creative'     => 'Wrong Creative',
            'obstructed'         => 'Obstructed',
            'poor_visibility'    => 'Poor Visibility',
            'placement_mismatch' => 'Placement Mismatch',
            'no_deployment'      => 'No Deployment',
            default              => 'Other',
        };
    }

    public function getStatusLabel(): string
    {
        return match($this->status) {
            'open'                 => 'Open',
            'under_review'         => 'Under Review',
            'awaiting_response'    => 'Awaiting Response',
            'resolved_advertiser'  => 'Resolved — Advertiser',
            'resolved_owner'       => 'Resolved — Owner',
            'resolved_split'       => 'Resolved — Split',
            'closed'               => 'Closed',
            default                => ucfirst($this->status),
        };
    }

    public function getStatusBadgeClass(): string
    {
        return match($this->status) {
            'resolved_advertiser',
            'resolved_owner',
            'resolved_split',
            'closed'           => 'nx-badge-good',
            'open',
            'awaiting_response'=> 'nx-badge-warn',
            'under_review'     => 'nx-badge-accent',
            default            => 'nx-badge',
        };
    }

    public function getOutcomeLabel(): string
    {
        return match($this->resolution_outcome) {
            'full_refund'      => 'Full Refund',
            'partial_refund'   => 'Partial Refund',
            'payout_released'  => 'Payout Released',
            'no_action'        => 'No Action',
            'penalty_applied'  => 'Penalty Applied',
            default            => 'N/A',
        };
    }

    // ============================================================
    // Relationships
    // ============================================================
    public function booking()
    {
        return $this->belongsTo(Booking::class);
    }

    public function bookingItem()
    {
        return $this->belongsTo(BookingItem::class);
    }

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

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

    public function mediaOwner()
    {
        return $this->belongsTo(MediaOwner::class);
    }

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

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

    public function messages()
    {
        return $this->hasMany(DisputeMessage::class);
    }

    public function publicMessages()
    {
        return $this->hasMany(DisputeMessage::class)
                    ->where('is_internal', false);
    }
}