<?php

namespace ZenoChatbot\Model;

use ZenoChatbot\Framework\Database\Model;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Message Model
 *
 * Represents individual messages within conversations.
 * Each message has exactly ONE meta record for storing context data.
 *
 * User messages store: ip_address, user_agent, referer, language
 * AI messages store: source, provider, model, tokens, raw_response, etc.
 */
class Message extends Model
{
    /**
     * Meta key constant (single key for all message meta)
     */
    public const META_KEY = 'data';

    /**
     * Table name
     */
    protected $table = 'zenochatbot_messages';

    /**
     * Primary key
     */
    protected $primaryKey = 'id';

    /**
     * Disable updated_at timestamp
     */
    public $timestamps = false;

    /**
     * Fillable attributes
     */
    protected $fillable = [
        'conversation_id',
        'sender_type',
        'sender_id',
        'message',
        'prompt_tokens',
        'completion_tokens',
        'token_usage',
        'sent_via'
    ];

    /**
     * Attributes that should be cast
     */
    protected $casts = [
        'id' => 'int',
        'conversation_id' => 'int',
        'sender_id' => 'int',
        'prompt_tokens' => 'int',
        'completion_tokens' => 'int',
        'token_usage' => 'int',
        'created_at' => 'datetime'
    ];

    /**
     * Get the conversation this message belongs to
     */
    public function conversation()
    {
        return $this->belongsTo(Conversation::class);
    }

    /**
     * Get the admin sender (if sender_type is admin)
     */
    public function admin()
    {
        return $this->belongsTo(User::class, 'sender_id');
    }

    /**
     * Get meta relation (one-to-one)
     *
     * @return \ZenoChatbot\Framework\Database\Relations\HasOne
     */
    public function meta()
    {
        return $this->hasOne(Meta::class, 'entity_id', 'id')
            ->where('entity_type', self::class)
            ->where('meta_key', self::META_KEY);
    }

    /**
     * Set meta data for this message (create or update)
     *
     * @param array $value Meta data array
     * @return Meta
     */
    public function setMeta(array $value): Meta
    {
        $meta = $this->meta;
        $serialized = maybe_serialize($value);

        if ($meta) {
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
            $meta->update(['meta_value' => $serialized]);
            // Invalidate relation cache so next access fetches fresh data
            $this->unsetRelation('meta');
            return $meta;
        }

        $newMeta = Meta::create([
            'entity_type' => self::class,
            'entity_id'   => $this->id,
            'meta_key'    => self::META_KEY, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
            'meta_value'  => $serialized, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
        ]);

        // Set the relation cache with the new meta
        $this->setRelation('meta', $newMeta);

        return $newMeta;
    }

    /**
     * Get meta data for this message
     *
     * @return array|null
     */
    public function getMeta(): ?array
    {
        $meta = $this->meta;
        return $meta ? maybe_unserialize($meta->meta_value) : null;
    }
}
