<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

/**
 * Model: RPublication (Research Publication)
 * 
 * Represents a research publication in the Research and Innovation Centre.
 * Supports full-text search, peer review workflow, and public showcase.
 * 
 * @property int $id
 * @property int $user_id
 * @property string $title
 * @property string $abstract
 * @property string|null $methodology
 * @property string|null $findings
 * @property string|null $references
 * @property string $category
 * @property string $status
 * @property bool $is_featured
 * @property string|null $cover_image
 * @property \Carbon\Carbon|null $submitted_at
 * @property \Carbon\Carbon|null $approved_at
 * @property int|null $approved_by
 * @property \Carbon\Carbon $created_at
 * @property \Carbon\Carbon $updated_at
 * @property \Carbon\Carbon|null $deleted_at
 * 
 * @property-read User $user
 * @property-read User|null $approver
 * @property-read \Illuminate\Database\Eloquent\Collection|RPublicationFile[] $files
 * @property-read \Illuminate\Database\Eloquent\Collection|RReviewFeedback[] $reviews
 * 
 * @author SSHIA Development Team
 * @version 1.0.0
 */
class RPublication extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * The table associated with the model.
     */
    protected $table = 'r_publications';

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'user_id',
        'title',
        'abstract',
        'methodology',
        'findings',
        'references',
        'category',
        'status',
        'is_featured',
        'cover_image',
        'submitted_at',
        'approved_at',
        'approved_by',
    ];

    /**
     * The attributes that should be cast.
     */
    protected $casts = [
        'is_featured' => 'boolean',
        'submitted_at' => 'datetime',
        'approved_at' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Status constants for easy reference.
     */
    const STATUS_DRAFT = 'draft';
    const STATUS_UNDER_REVIEW = 'under_review';
    const STATUS_REVISION_REQUIRED = 'revision_required';
    const STATUS_APPROVED = 'approved';
    const STATUS_FEATURED = 'featured';

    /**
     * Category constants.
     */
    const CATEGORY_CLINICAL = 'clinical';
    const CATEGORY_TECH = 'tech';
    const CATEGORY_SOCIAL = 'social';

    /**
     * Get the author of the publication.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * Get the user who approved the publication.
     */
    public function approver(): BelongsTo
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    /**
     * Get all files attached to this publication.
     */
    public function files(): HasMany
    {
        return $this->hasMany(RPublicationFile::class, 'publication_id');
    }

    /**
     * Get all review feedbacks for this publication.
     */
    public function reviews(): HasMany
    {
        return $this->hasMany(RReviewFeedback::class, 'publication_id');
    }

    /**
     * Scope: Published publications (for public view).
     */
    public function scopePublished($query)
    {
        return $query->whereIn('status', [self::STATUS_APPROVED, self::STATUS_FEATURED]);
    }

    /**
     * Scope: Featured publications (published only).
     * Returns publications that are either marked is_featured=true OR have status=featured,
     * but only when they are in a publicly visible status.
     */
    public function scopeFeatured($query)
    {
        return $query->whereIn('status', [self::STATUS_APPROVED, self::STATUS_FEATURED])
                     ->where(function ($q) {
                         $q->where('is_featured', true)
                           ->orWhere('status', self::STATUS_FEATURED);
                     });
    }

    /**
     * Scope: Publications under review.
     */
    public function scopeUnderReview($query)
    {
        return $query->where('status', self::STATUS_UNDER_REVIEW);
    }

    /**
     * Scope: Publications requiring revision.
     */
    public function scopeRevisionRequired($query)
    {
        return $query->where('status', self::STATUS_REVISION_REQUIRED);
    }

    /**
     * Scope: Publications by user.
     */
    public function scopeByUser($query, int $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * Scope: Filter by category.
     */
    public function scopeByCategory($query, string $category)
    {
        return $query->where('category', $category);
    }

    /**
     * Scope: Full-text search (MySQL).
     */
    public function scopeSearch($query, string $term)
    {
        if (config('database.default') === 'mysql') {
            return $query->whereRaw(
                "MATCH(title, abstract, methodology, findings) AGAINST(? IN BOOLEAN MODE)",
                [$term . '*']
            );
        }
        
        // Fallback for SQLite/other databases
        return $query->where(function ($q) use ($term) {
            $q->where('title', 'LIKE', "%{$term}%")
              ->orWhere('abstract', 'LIKE', "%{$term}%")
              ->orWhere('methodology', 'LIKE', "%{$term}%")
              ->orWhere('findings', 'LIKE', "%{$term}%");
        });
    }

    /**
     * Check if publication is editable.
     */
    public function isEditable(): bool
    {
        return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_REVISION_REQUIRED]);
    }

    /**
     * Check if publication can be submitted (or resubmitted) for review.
     */
    public function canSubmit(): bool
    {
        return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_REVISION_REQUIRED]);
    }

    /**
     * Check if publication can be reviewed.
     */
    public function canReview(): bool
    {
        return $this->status === self::STATUS_UNDER_REVIEW;
    }

    /**
     * Check if user is the author.
     */
    public function isAuthor(int $userId): bool
    {
        return $this->user_id === $userId;
    }

    /**
     * Get author's credential badge.
     */
    public function getAuthorBadgeAttribute(): string
    {
        $author = $this->user;
        if (!$author) {
            return 'Contributor';
        }

        // Get the user's primary role
        $role = $author->roles->first();
        return $role ? $role->name : 'Contributor';
    }

    /**
     * Get status badge color.
     */
    public function getStatusColorAttribute(): string
    {
        return match($this->status) {
            self::STATUS_DRAFT => 'gray',
            self::STATUS_UNDER_REVIEW => 'blue',
            self::STATUS_REVISION_REQUIRED => 'yellow',
            self::STATUS_APPROVED => 'green',
            self::STATUS_FEATURED => 'purple',
            default => 'gray',
        };
    }

    /**
     * Get category label.
     */
    public function getCategoryLabelAttribute(): string
    {
        return match($this->category) {
            self::CATEGORY_CLINICAL => 'Clinical Research',
            self::CATEGORY_TECH => 'Technology & Innovation',
            self::CATEGORY_SOCIAL => 'Social Sciences',
            default => ucfirst($this->category),
        };
    }

    /**
     * Generate a slug for the publication.
     */
    public function generateSlug(): string
    {
        return Str::slug($this->title) . '-' . $this->id;
    }
}
