<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Builder;

/**
 * EmailTemplate Model
 * 
 * Represents a reusable email template.
 * Managed by Super Manager and Manager roles.
 * 
 * Requirements: 3.1, 3.8
 * 
 * @property int $id
 * @property string $name
 * @property string $slug
 * @property string $subject
 * @property string|null $preheader
 * @property string $html_content
 * @property string|null $text_content
 * @property string|null $description
 * @property bool $is_active
 * @property bool $is_system
 * @property int|null $created_by
 * @property int $usage_count
 * @property array|null $placeholders
 */
class EmailTemplate extends Model
{
    use SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'slug',
        'subject',
        'preheader',
        'html_content',
        'text_content',
        'description',
        'is_active',
        'is_system',
        'created_by',
        'usage_count',
        'placeholders',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'is_active' => 'boolean',
        'is_system' => 'boolean',
        'usage_count' => 'integer',
        'placeholders' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * Common placeholders available in templates.
     */
    public static function availablePlaceholders(): array
    {
        return [
            '{name}' => 'Recipient full name',
            '{first_name}' => 'Recipient first name',
            '{last_name}' => 'Recipient last name',
            '{email}' => 'Recipient email address',
            '{company}' => 'Company name',
            '{sender_name}' => 'Sender name',
            '{unsubscribe_link}' => 'Unsubscribe link',
            '{view_online_link}' => 'View online link',
            '{current_year}' => 'Current year',
            '{current_date}' => 'Current date',
        ];
    }

    /**
     * Get the user who created this template.
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get messages that used this template.
     */
    public function messages()
    {
        return $this->hasMany(EmailMessage::class, 'template_id');
    }

    /**
     * Scope for active templates only.
     */
    public function scopeActive(Builder $query): Builder
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope for system templates.
     */
    public function scopeSystem(Builder $query): Builder
    {
        return $query->where('is_system', true);
    }

    /**
     * Scope for non-system (custom) templates.
     */
    public function scopeCustom(Builder $query): Builder
    {
        return $query->where('is_system', false);
    }

    /**
     * Scope for searching templates.
     */
    public function scopeSearch(Builder $query, string $search): Builder
    {
        return $query->where(function ($q) use ($search) {
            $q->where('name', 'like', "%{$search}%")
              ->orWhere('subject', 'like', "%{$search}%")
              ->orWhere('description', 'like', "%{$search}%");
        });
    }

    /**
     * Parse subject with given variables.
     */
    public function parseSubject(array $variables): string
    {
        $subject = $this->subject;
        
        foreach ($variables as $key => $value) {
            $placeholder = '{' . $key . '}';
            $subject = str_replace($placeholder, $value, $subject);
        }

        // Remove any remaining placeholders
        $subject = preg_replace('/\{[a-zA-Z_]+\}/', '', $subject);

        return $subject;
    }

    /**
     * Parse HTML content with given variables.
     */
    public function parseHtmlContent(array $variables): string
    {
        $content = $this->html_content;
        
        foreach ($variables as $key => $value) {
            $placeholder = '{' . $key . '}';
            $content = str_replace($placeholder, $value, $content);
        }

        // Remove any remaining placeholders
        $content = preg_replace('/\{[a-zA-Z_]+\}/', '', $content);

        return $content;
    }

    /**
     * Parse text content with given variables.
     */
    public function parseTextContent(array $variables): string
    {
        $content = $this->text_content ?? '';
        
        foreach ($variables as $key => $value) {
            $placeholder = '{' . $key . '}';
            $content = str_replace($placeholder, $value, $content);
        }

        // Remove any remaining placeholders
        $content = preg_replace('/\{[a-zA-Z_]+\}/', '', $content);

        return $content;
    }

    /**
     * Increment usage count.
     */
    public function incrementUsage(): void
    {
        $this->increment('usage_count');
    }

    /**
     * Activate the template.
     */
    public function activate(): void
    {
        $this->update(['is_active' => true]);
    }

    /**
     * Deactivate the template.
     */
    public function deactivate(): void
    {
        $this->update(['is_active' => false]);
    }

    /**
     * Check if template can be deleted.
     */
    public function canBeDeleted(): bool
    {
        return !$this->is_system;
    }

    /**
     * Check if template contains placeholders.
     */
    public function hasPlaceholders(): bool
    {
        return preg_match('/\{[a-zA-Z_]+\}/', $this->html_content) === 1 ||
               preg_match('/\{[a-zA-Z_]+\}/', $this->subject) === 1;
    }

    /**
     * Extract all unique placeholders from subject and content.
     */
    public function extractPlaceholders(): array
    {
        $allContent = $this->subject . ' ' . $this->html_content;
        preg_match_all('/\{([a-zA-Z_]+)\}/', $allContent, $matches);
        return array_unique($matches[1] ?? []);
    }

    /**
     * Get the preview of the email (stripped HTML).
     */
    public function getPreviewAttribute(): string
    {
        return strip_tags($this->html_content);
    }

    /**
     * Get word count of HTML content.
     */
    public function getWordCountAttribute(): int
    {
        return str_word_count(strip_tags($this->html_content));
    }

    /**
     * Check if template has plain text version.
     */
    public function hasTextVersion(): bool
    {
        return !empty($this->text_content);
    }
}
