<?php

namespace Modules\SystemCore\App\Models;

use App\Helpers\FormattingHelper;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Modules\SystemCore\App\Services\PostingLogService;

class PostingLog extends Model
{
    protected $table = 'posting_logs';

    protected $fillable = [
        'source_module',
        'source_entity_type',
        'source_entity_id',
        'target_module',
        'target_entity_type',
        'target_entity_id',
        'action',
        'status',
        'description',
        'amount',
        'old_values',
        'new_values',
        'error_message',
        'retry_count',
        'posted_by',
        'posted_at',
    ];

    protected function casts(): array
    {
        return [
            'old_values' => 'array',
            'new_values' => 'array',
            'posted_at' => 'datetime',
            'amount' => 'decimal:2',
            'retry_count' => 'integer',
        ];
    }

    /**
     * Scope for today's postings
     */
    public function scopeToday(Builder $query): Builder
    {
        return $query->whereDate('posted_at', today());
    }

    /**
     * Scope for date range
     */
    public function scopeForDateRange(Builder $query, $startDate, $endDate): Builder
    {
        return $query->whereBetween('posted_at', [$startDate, $endDate]);
    }

    /**
     * Check if posting can be retried
     */
    public function canRetry(): bool
    {
        $maxRetries = app(PostingLogService::class)->getMaxRetryAttempts();

        return $this->status === 'failed' && $this->retry_count < $maxRetries;
    }

    /**
     * Increment retry count
     */
    public function incrementRetry(): void
    {
        $this->increment('retry_count');
    }

    /**
     * Get formatted amount
     */
    public function getFormattedAmountAttribute(): ?string
    {
        if ($this->amount === null) {
            return null;
        }

        return FormattingHelper::formatCurrency($this->amount);
    }

    /**
     * Get formatted posted date
     */
    public function getFormattedPostedAtAttribute(): string
    {
        return $this->posted_at->format('M d, Y H:i');
    }

    /**
     * Get status badge HTML
     */
    public function getStatusBadgeAttribute(): string
    {
        $badges = [
            'success' => 'bg-label-success',
            'failed' => 'bg-label-danger',
            'pending' => 'bg-label-warning',
        ];

        $class = $badges[$this->status] ?? 'bg-label-secondary';
        $label = ucfirst($this->status);

        return sprintf(
            '<span class="badge %s">%s</span>',
            $class,
            __($label)
        );
    }

    /**
     * Get action badge HTML
     */
    public function getActionBadgeAttribute(): string
    {
        $badges = [
            'create' => 'bg-label-success',
            'update' => 'bg-label-info',
            'delete' => 'bg-label-danger',
        ];

        $class = $badges[$this->action] ?? 'bg-label-secondary';
        $label = ucfirst($this->action);

        return sprintf(
            '<span class="badge %s">%s</span>',
            $class,
            __($label)
        );
    }

    /**
     * Get source reference string
     */
    public function getSourceReferenceAttribute(): string
    {
        return sprintf(
            '%s / %s / #%d',
            $this->source_module,
            $this->source_entity_type,
            $this->source_entity_id
        );
    }

    /**
     * Get target reference string
     */
    public function getTargetReferenceAttribute(): string
    {
        if (! $this->target_entity_id) {
            return sprintf(
                '%s / %s',
                $this->target_module,
                $this->target_entity_type
            );
        }

        return sprintf(
            '%s / %s / #%d',
            $this->target_module,
            $this->target_entity_type,
            $this->target_entity_id
        );
    }

    /**
     * Get posting statistics
     */
    public static function getStatistics(): array
    {
        return [
            'total' => self::count(),
            'successful' => self::successful()->count(),
            'failed' => self::failed()->count(),
            'pending' => self::pending()->count(),
            'today' => self::today()->count(),
        ];
    }

    /**
     * Get the user who posted this log
     */
    public function postedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'posted_by');
    }

    /**
     * Scope for successful postings
     */
    public function scopeSuccessful(Builder $query): Builder
    {
        return $query->where('status', 'success');
    }

    /**
     * Scope for failed postings
     */
    public function scopeFailed(Builder $query): Builder
    {
        return $query->where('status', 'failed');
    }

    /**
     * Scope for pending postings
     */
    public function scopePending(Builder $query): Builder
    {
        return $query->where('status', 'pending');
    }

    /**
     * Scope for a specific module (source or target)
     */
    public function scopeForModule(Builder $query, string $module): Builder
    {
        return $query->where(function ($q) use ($module) {
            $q->where('source_module', $module)
                ->orWhere('target_module', $module);
        });
    }

    /**
     * Scope for source module
     */
    public function scopeFromModule(Builder $query, string $module): Builder
    {
        return $query->where('source_module', $module);
    }

    /**
     * Scope for target module
     */
    public function scopeToModule(Builder $query, string $module): Builder
    {
        return $query->where('target_module', $module);
    }

    /**
     * Scope for a specific entity type (source or target)
     */
    public function scopeForEntityType(Builder $query, string $type): Builder
    {
        return $query->where(function ($q) use ($type) {
            $q->where('source_entity_type', $type)
                ->orWhere('target_entity_type', $type);
        });
    }

    /**
     * Scope for source entity type
     */
    public function scopeForSourceEntityType(Builder $query, string $type): Builder
    {
        return $query->where('source_entity_type', $type);
    }

    /**
     * Scope for target entity type
     */
    public function scopeForTargetEntityType(Builder $query, string $type): Builder
    {
        return $query->where('target_entity_type', $type);
    }

    /**
     * Check if this posting was successful
     */
    public function isSuccessful(): bool
    {
        return $this->status === 'success';
    }

    /**
     * Check if this posting failed
     */
    public function isFailed(): bool
    {
        return $this->status === 'failed';
    }

    /**
     * Check if this posting is pending
     */
    public function isPending(): bool
    {
        return $this->status === 'pending';
    }
}
