#include "server.h"
#include <iostream>
#include <fstream>

namespace scar {

Server::Server(const ServerConfig& config)
    : ssl_context_(boost::asio::ssl::context::tlsv12_server),
      acceptor_(io_context_),
      config_(config) {
    
    // Load SSL certificate and key
    try {
        std::ifstream cert_file(config_.certPath());
        std::ifstream key_file(config_.keyPath());
        
        if (!cert_file.is_open()) {
            throw std::runtime_error("Cannot open certificate file: " + config_.certPath());
        }
        if (!key_file.is_open()) {
            throw std::runtime_error("Cannot open key file: " + config_.keyPath());
        }
        
        ssl_context_.use_certificate_chain_file(config_.certPath());
        ssl_context_.use_private_key_file(config_.keyPath(), boost::asio::ssl::context::pem);
    } catch (const std::exception& e) {
        std::cerr << "SSL configuration error: " << e.what() << std::endl;
        throw;
    }
    
    // Initialize database
    database_ = std::make_shared<Database>(config_.dbPath());
    if (!database_->initialize()) {
        throw std::runtime_error("Failed to initialize database");
    }
    
    // Create authenticator
    authenticator_ = std::make_shared<Authenticator>(database_, config_.jwtSecret());
    
    // Setup acceptor
    boost::asio::ip::tcp::endpoint endpoint(
        boost::asio::ip::make_address(config_.host()),
        config_.port()
    );
    
    acceptor_.open(endpoint.protocol());
    acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    acceptor_.bind(endpoint);
    acceptor_.listen();
    
    std::cout << "Server listening on " << config_.host() << ":" << config_.port() << std::endl;
}

void Server::run() {
    doAccept();
    io_context_.run();
}

void Server::stop() {
    io_context_.stop();
}

void Server::doAccept() {
    acceptor_.async_accept(
        [this](const boost::system::error_code& error, boost::asio::ip::tcp::socket socket) {
            if (!error) {
                std::cout << "New connection from " << socket.remote_endpoint() << std::endl;
                
                auto ssl_socket = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(
                    std::move(socket), ssl_context_
                );
                
                auto session = std::make_shared<Session>(
                    std::move(ssl_socket),
                    authenticator_,
                    this
                );
                
                session->start();
            }
            
            doAccept();
        });
}

void Server::addSession(std::shared_ptr<Session> session) {
    std::lock_guard<std::mutex> lock(sessions_mutex_);
    sessions_.insert(session);
    std::cout << "Session added. Total sessions: " << sessions_.size() << std::endl;
}

void Server::removeSession(std::shared_ptr<Session> session) {
    std::lock_guard<std::mutex> lock(sessions_mutex_);
    sessions_.erase(session);
    std::cout << "Session removed. Total sessions: " << sessions_.size() << std::endl;
}

void Server::broadcastMessage(const TextMessage& message) {
    std::lock_guard<std::mutex> lock(sessions_mutex_);
    
    for (auto& session : sessions_) {
        if (session->isAuthenticated()) {
            session->send(message);
        }
    }
}

void Server::broadcastToOthers(const Message& message, std::shared_ptr<Session> exclude) {
    std::lock_guard<std::mutex> lock(sessions_mutex_);
    
    for (auto& session : sessions_) {
        if (session != exclude && session->isAuthenticated()) {
            session->send(message);
        }
    }
}

} // namespace scar
