<?php

namespace App\Models;

use CodeIgniter\Model;

class MessageParticipantModel extends Model
{
    protected $table         = 'message_participants';
    protected $primaryKey    = 'id';
    protected $returnType    = 'array';
    protected $useTimestamps = false;

    protected $allowedFields = [
        'conversation_id', 'user_id', 'last_read_at', 'joined_at',
    ];

    public function isMember(int $conversationId, int $userId): bool
    {
        return $this->where('conversation_id', $conversationId)
            ->where('user_id', $userId)
            ->countAllResults() > 0;
    }

    public function addMember(int $conversationId, int $userId): void
    {
        if ($this->isMember($conversationId, $userId)) {
            return;
        }

        $this->insert([
            'conversation_id' => $conversationId,
            'user_id'         => $userId,
            'joined_at'       => date('Y-m-d H:i:s'),
        ]);
    }

    public function removeMember(int $conversationId, int $userId): void
    {
        $this->where('conversation_id', $conversationId)
            ->where('user_id', $userId)
            ->delete();
    }

    public function syncMembers(int $conversationId, array $userIds): void
    {
        $userIds = array_values(array_unique(array_map('intval', $userIds)));
        $userIds = array_filter($userIds, static fn (int $id) => $id > 0);

        $existing = $this->where('conversation_id', $conversationId)->findAll();
        $existingIds = array_map(static fn (array $r) => (int) $r['user_id'], $existing);

        foreach ($userIds as $uid) {
            if (! in_array($uid, $existingIds, true)) {
                $this->addMember($conversationId, $uid);
            }
        }

        foreach ($existingIds as $uid) {
            if (! in_array($uid, $userIds, true)) {
                $this->removeMember($conversationId, $uid);
            }
        }
    }

    public function markRead(int $conversationId, int $userId): void
    {
        $row = $this->where('conversation_id', $conversationId)
            ->where('user_id', $userId)
            ->first();

        if ($row) {
            $this->update($row['id'], ['last_read_at' => date('Y-m-d H:i:s')]);

            return;
        }

        // Public channel: create a lightweight participant row for read tracking
        $this->insert([
            'conversation_id' => $conversationId,
            'user_id'         => $userId,
            'joined_at'       => date('Y-m-d H:i:s'),
            'last_read_at'    => date('Y-m-d H:i:s'),
        ]);
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function getMembersWithNames(int $conversationId): array
    {
        return $this->select('message_participants.*, users.first_name, users.last_name, users.username, users.email, users.status')
            ->join('users', 'users.id = message_participants.user_id')
            ->where('message_participants.conversation_id', $conversationId)
            ->where('users.deleted_at', null)
            ->orderBy('users.first_name', 'ASC')
            ->findAll();
    }

    public function unreadTotalForUser(int $userId): int
    {
        $sql = "
            SELECT COUNT(*) AS cnt
            FROM messages m
            JOIN message_conversations c ON c.id = m.conversation_id
            JOIN message_participants mp
                ON mp.conversation_id = c.id AND mp.user_id = ?
            WHERE m.deleted_at IS NULL
              AND m.sender_id != ?
              AND (mp.last_read_at IS NULL OR m.created_at > mp.last_read_at)
        ";

        $row = $this->db->query($sql, [$userId, $userId])->getRowArray();

        return (int) ($row['cnt'] ?? 0);
    }
}
