<?php
class ProfessionalMessage
{
    public static function send(int $senderId, array $data): array
    {
        Database::migrate();
        $recipientId = (int)($data['recipient_id'] ?? 0);
        $subject = trim((string)($data['subject'] ?? ''));
        $body = trim((string)($data['message_body'] ?? ''));
        $password = (string)($data['message_password'] ?? '');

        if ($recipientId <= 0 || $subject === '' || $body === '') {
            return ['ok' => false, 'message' => 'Selecione o instrutor e preencha assunto e mensagem.'];
        }
        if ($recipientId === $senderId) {
            return ['ok' => false, 'message' => 'Selecione outro instrutor para receber a mensagem.'];
        }
        $recipient = Professional::find($recipientId);
        if (!$recipient || (int)($recipient['is_active'] ?? 0) !== 1) {
            return ['ok' => false, 'message' => 'Instrutor destinatário não encontrado ou inativo.'];
        }
        if (strlen($subject) > 180) {
            return ['ok' => false, 'message' => 'O assunto deve ter no máximo 180 caracteres.'];
        }
        if (strlen($body) > 10000) {
            return ['ok' => false, 'message' => 'A mensagem deve ter no máximo 10.000 caracteres.'];
        }
        if ($password !== '' && strlen($password) < 4) {
            return ['ok' => false, 'message' => 'A senha da mensagem deve ter no mínimo 4 caracteres.'];
        }

        $stmt = Database::pdo()->prepare('INSERT INTO professional_messages (sender_id, recipient_id, subject, message_body, password_hash, is_read, created_at) VALUES (?, ?, ?, ?, ?, 0, ?)');
        $stmt->execute([
            $senderId,
            $recipientId,
            $subject,
            $body,
            $password !== '' ? password_hash($password, PASSWORD_DEFAULT) : null,
            date('Y-m-d H:i:s'),
        ]);
        return ['ok' => true, 'message' => $password !== '' ? 'Mensagem protegida por senha enviada.' : 'Mensagem enviada ao instrutor.'];
    }

    public static function inbox(int $professionalId): array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare("SELECT m.*, s.name AS sender_name, r.name AS recipient_name
            FROM professional_messages m
            INNER JOIN professionals s ON s.id = m.sender_id
            INNER JOIN professionals r ON r.id = m.recipient_id
            WHERE m.recipient_id = ? AND m.recipient_deleted_at IS NULL
            ORDER BY m.created_at DESC");
        $stmt->execute([$professionalId]);
        $rows = $stmt->fetchAll();

        $plainIds = [];
        foreach ($rows as &$row) {
            $row['is_locked'] = !empty($row['password_hash']);
            $row['is_unlocked'] = !$row['is_locked'] || self::isUnlocked($professionalId, (int)$row['id']);
            if (!$row['is_locked'] && empty($row['is_read'])) {
                $plainIds[] = (int)$row['id'];
                $row['is_read'] = 1;
                $row['read_at'] = date('Y-m-d H:i:s');
            }
        }
        unset($row);
        self::markManyRead($professionalId, $plainIds);
        return $rows;
    }

    public static function sent(int $professionalId): array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare("SELECT m.*, s.name AS sender_name, r.name AS recipient_name
            FROM professional_messages m
            INNER JOIN professionals s ON s.id = m.sender_id
            INNER JOIN professionals r ON r.id = m.recipient_id
            WHERE m.sender_id = ? AND m.sender_deleted_at IS NULL
            ORDER BY m.created_at DESC");
        $stmt->execute([$professionalId]);
        return $stmt->fetchAll();
    }

    public static function unlock(int $professionalId, int $messageId, string $password): array
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare('SELECT * FROM professional_messages WHERE id = ? AND recipient_id = ? AND recipient_deleted_at IS NULL LIMIT 1');
        $stmt->execute([$messageId, $professionalId]);
        $message = $stmt->fetch();
        if (!$message) {
            return ['ok' => false, 'message' => 'Mensagem não encontrada.'];
        }
        if (empty($message['password_hash'])) {
            self::rememberUnlocked($professionalId, $messageId);
            self::markRead($professionalId, $messageId);
            return ['ok' => true, 'message' => 'Mensagem aberta.'];
        }
        if (!password_verify($password, (string)$message['password_hash'])) {
            return ['ok' => false, 'message' => 'Senha da mensagem incorreta.'];
        }
        self::rememberUnlocked($professionalId, $messageId);
        self::markRead($professionalId, $messageId);
        return ['ok' => true, 'message' => 'Mensagem desbloqueada com sucesso.'];
    }

    public static function deleteForProfessional(int $professionalId, int $messageId): array
    {
        Database::migrate();
        $pdo = Database::pdo();
        $stmt = $pdo->prepare('SELECT id, sender_id, recipient_id, sender_deleted_at, recipient_deleted_at FROM professional_messages WHERE id = ? AND (sender_id = ? OR recipient_id = ?) LIMIT 1');
        $stmt->execute([$messageId, $professionalId, $professionalId]);
        $message = $stmt->fetch();
        if (!$message) {
            return ['ok' => false, 'message' => 'Mensagem não encontrada ou sem permissão para apagar.'];
        }

        $now = date('Y-m-d H:i:s');
        if ((int)$message['sender_id'] === $professionalId) {
            $update = $pdo->prepare('UPDATE professional_messages SET sender_deleted_at = ? WHERE id = ? AND sender_id = ?');
            $update->execute([$now, $messageId, $professionalId]);
        }
        if ((int)$message['recipient_id'] === $professionalId) {
            $update = $pdo->prepare('UPDATE professional_messages SET recipient_deleted_at = ? WHERE id = ? AND recipient_id = ?');
            $update->execute([$now, $messageId, $professionalId]);
            unset($_SESSION['professional_message_unlocks'][$professionalId][$messageId]);
        }

        // Quando remetente e destinatário já apagaram suas cópias, remove o registro definitivo.
        $cleanup = $pdo->prepare('DELETE FROM professional_messages WHERE id = ? AND sender_deleted_at IS NOT NULL AND recipient_deleted_at IS NOT NULL');
        $cleanup->execute([$messageId]);
        return ['ok' => true, 'message' => 'Mensagem apagada da sua caixa.'];
    }

    public static function unreadCount(int $professionalId): int
    {
        Database::migrate();
        $stmt = Database::pdo()->prepare('SELECT COUNT(*) FROM professional_messages WHERE recipient_id = ? AND is_read = 0 AND recipient_deleted_at IS NULL');
        $stmt->execute([$professionalId]);
        return (int)$stmt->fetchColumn();
    }

    private static function isUnlocked(int $professionalId, int $messageId): bool
    {
        return !empty($_SESSION['professional_message_unlocks'][$professionalId][$messageId]);
    }

    private static function rememberUnlocked(int $professionalId, int $messageId): void
    {
        $_SESSION['professional_message_unlocks'][$professionalId][$messageId] = true;
    }

    private static function markRead(int $professionalId, int $messageId): void
    {
        $stmt = Database::pdo()->prepare('UPDATE professional_messages SET is_read = 1, read_at = COALESCE(read_at, ?) WHERE id = ? AND recipient_id = ? AND recipient_deleted_at IS NULL');
        $stmt->execute([date('Y-m-d H:i:s'), $messageId, $professionalId]);
    }

    private static function markManyRead(int $professionalId, array $ids): void
    {
        $ids = array_values(array_unique(array_filter(array_map('intval', $ids))));
        if (!$ids) {
            return;
        }
        $placeholders = implode(',', array_fill(0, count($ids), '?'));
        $params = array_merge([date('Y-m-d H:i:s'), $professionalId], $ids);
        $stmt = Database::pdo()->prepare("UPDATE professional_messages SET is_read = 1, read_at = COALESCE(read_at, ?) WHERE recipient_id = ? AND recipient_deleted_at IS NULL AND id IN ({$placeholders})");
        $stmt->execute($params);
    }
}
