#include "outlookauthenticator.h"
#include <QDebug>
#include <QUrlQuery>
#include <QDesktopServices>
#include <QNetworkReply>

// Microsoft Graph OAuth2 configuration
static const char* OUTLOOK_CLIENT_ID = "your-outlook-client-id";
static const char* OUTLOOK_CLIENT_SECRET = "your-outlook-client-secret";
static const char* OUTLOOK_AUTH_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
static const char* OUTLOOK_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
static const char* OUTLOOK_SCOPES = "offline_access Mail.ReadWrite Mail.Send User.Read";

OutlookAuthenticator::OutlookAuthenticator(QObject *parent)
    : Authenticator(parent)
    , m_callbackServer(new OAuthCallbackServer(8080, this))
{
    m_clientId = OUTLOOK_CLIENT_ID;
    m_clientSecret = OUTLOOK_CLIENT_SECRET;
    m_authEndpoint = OUTLOOK_AUTH_URL;
    m_tokenEndpoint = OUTLOOK_TOKEN_URL;
    m_scopes = OUTLOOK_SCOPES;

    connect(m_callbackServer, &OAuthCallbackServer::codeReceived,
            this, &OutlookAuthenticator::onAuthCodeReceived);
    connect(m_callbackServer, &OAuthCallbackServer::errorOccurred,
            [this](const QString &error) {
        emit authenticationFailed("OAuth callback error: " + error);
    });
}

void OutlookAuthenticator::authenticate(const QString &email)
{
    m_email = email;
    m_redirectUri = m_callbackServer->redirectUri();
    qDebug() << "[OutlookAuthenticator] Starting authentication for:" << email;

    if (!m_callbackServer->start()) {
        emit authenticationFailed("Could not start OAuth callback server on port 8080");
        return;
    }

    QUrl authUrl(m_authEndpoint);
    QUrlQuery query;
    query.addQueryItem("client_id", m_clientId);
    query.addQueryItem("redirect_uri", m_redirectUri);
    query.addQueryItem("response_type", "code");
    query.addQueryItem("scope", m_scopes);
    authUrl.setQuery(query);

    QDesktopServices::openUrl(authUrl);
}

void OutlookAuthenticator::onAuthCodeReceived(const QString &code, const QString &state)
{
    Q_UNUSED(state);
    qDebug() << "[OutlookAuthenticator] Authorization code received, exchanging for tokens...";

    m_callbackServer->stop();

    exchangeAuthorizationCode(code, m_redirectUri, m_email);
}

void OutlookAuthenticator::refreshToken(const Account &account)
{
    qDebug() << "[OutlookAuthenticator] Refreshing token for account:" << account.email();

    QUrlQuery params;
    params.addQueryItem("client_id", m_clientId);
    params.addQueryItem("client_secret", m_clientSecret);
    params.addQueryItem("refresh_token", account.refreshToken());
    params.addQueryItem("grant_type", "refresh_token");
    params.addQueryItem("scope", m_scopes);

    QNetworkRequest request = createTokenRequest(QUrl(m_tokenEndpoint));
    QNetworkReply *reply = m_networkManager->post(request, params.toString(QUrl::FullyEncoded).toUtf8());
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        handleTokenResponse(reply->readAll(), m_email, "outlook");
        reply->deleteLater();
    });
}

void OutlookAuthenticator::onTokenReply(QNetworkReply *reply) {
    qDebug() << "[OutlookAuthenticator] onTokenReply called";
    reply->deleteLater();
}

#include "outlookauthenticator.moc"