const THREADS_CLIENT_ID = 'YOUR_CLIENT_ID';
const THREADS_CLIENT_SECRET = 'YOUR_CLIENT_SECRET';
const THREADS_SCOPE = 'threads_basic,threads_content_publish';
const THREADS_AUTH_URL = 'https://threads.net/oauth/authorize';
const THREADS_TOKEN_URL = 'https://graph.threads.net/oauth/access_token';
const THREADS_SPREADSHEET_ID = 'YOUR_SPREADSHEET_ID';

function getServiceThreads() {
    return OAuth2.createService('threads')
        .setAuthorizationBaseUrl(THREADS_AUTH_URL)
        .setTokenUrl(THREADS_TOKEN_URL)
        .setClientId(THREADS_CLIENT_ID)
        .setClientSecret(THREADS_CLIENT_SECRET)
        .setCallbackFunction('authCallback')
        .setPropertyStore(PropertiesService.getUserProperties())
        .setScope(THREADS_SCOPE)
        .setParam('access_type', 'offline')
        .setParam('prompt', 'consent')
        .setTokenHeaders({
        'Authorization': 'Basic ' + Utilities.base64Encode(THREADS_CLIENT_ID + ':' + THREADS_CLIENT_SECRET)
        });
}

function authCallback(request) {
    var service = getServiceThreads();
    var isAuthorized = service.handleCallback(request);
    if (isAuthorized) {
        return HtmlService.createHtmlOutput('認証成功!このウィンドウを閉じて、スクリプトエディタに戻ってください。');
    } else {
        return HtmlService.createHtmlOutput('認証に失敗しました。もう一度お試しください。');
    }
}

function getAuthorizationUrl() {
    var service = getServiceThreads();
    if (!service.hasAccess()) {
        var authorizationUrl = service.getAuthorizationUrl();
        Logger.log('以下のURLにアクセスして認証を行ってください:');
        Logger.log(authorizationUrl);
        return authorizationUrl;
    } else {
        Logger.log('すでに認証されています。');
        return null;
    }
}

function getThreadsToken() {
    var service = getServiceThreads();
    if (service.hasAccess()) {
        var accessToken = service.getAccessToken();
        Logger.log('Access Token: ' + accessToken);

        var response = UrlFetchApp.fetch(
        'https://graph.threads.net/me?fields=id',
        {
            headers: {
            Authorization: 'Bearer ' + accessToken
            }
        }
        );
        var userId = JSON.parse(response.getContentText()).id;
        Logger.log('User ID: ' + userId);

        return {
            access_token: accessToken,
            user_id: userId
        };
    } else {
        Logger.log('認証が必要です。getAuthorizationUrl()を実行してください。');
        return null;
    }
}

function postToThreads() {
    if (!checkAndRefreshToken()) {
        Logger.log('トークンの更新に失敗しました。再認証が必要です。');
        return;
    }
    var tokenData = getThreadsToken();
    if (!tokenData) {
        Logger.log('トークンの取得に失敗しました。認証を確認してください。');
        return;
    }

    const CREATE_URL = `https://graph.threads.net/v1.0/${tokenData.user_id}/threads`;
    const PUBLISH_URL = `https://graph.threads.net/v1.0/${tokenData.user_id}/threads_publish`;
    const sheet = SpreadsheetApp.openById(THREADS_SPREADSHEET_ID).getActiveSheet();
    const data = sheet.getDataRange().getValues();

    let candidates = [];
    let minPostCount = Infinity;

    for (let i = 0; i < data.length; i++) {
        if (i === 0 && (data[i][0] === 'ID' || data[i][1] === '投稿内容')) {
            continue;
        }
        let postCount = data[i][2] || 0;
        if (typeof postCount === 'string') postCount = parseInt(postCount, 10) || 0;

        if (postCount <= minPostCount) {
            if (postCount < minPostCount) {
                candidates = [];
                minPostCount = postCount;
            }
            candidates.push({ content: data[i][1], rowIndex: i });
        }
    }
    if (candidates.length === 0) {
        Logger.log('投稿する内容がありません。');
        return;
    }
    const selected = candidates[Math.floor(Math.random() * candidates.length)];
    const content = selected.content;
    const createOptions = {
        method: "post",
        headers: {
            "Authorization": "Bearer " + tokenData.access_token,
            "Content-Type": "application/x-www-form-urlencoded"
        },
        payload: {
            text: content,
            media_type: "TEXT",
            access_token: tokenData.access_token
        }
    };
    try {
        const createResponse = UrlFetchApp.fetch(CREATE_URL, createOptions);
        if (createResponse.getResponseCode() === 200) {
            const creationId = JSON.parse(createResponse.getContentText()).id;
            const publishOptions = {
                method: "post",
                headers: {
                    "Authorization": "Bearer " + tokenData.access_token,
                    "Content-Type": "application/x-www-form-urlencoded"
                },
                payload: {
                    creation_id: creationId,
                    access_token: tokenData.access_token
                }
            };
            const publishResponse = UrlFetchApp.fetch(PUBLISH_URL, publishOptions);
            if (publishResponse.getResponseCode() === 200) {
                Logger.log("投稿成功: " + content);
                let currentCount = sheet.getRange(selected.rowIndex + 1, 3).getValue() || 0;
                sheet.getRange(selected.rowIndex + 1, 3).setValue(currentCount + 1);
                sheet.getRange(selected.rowIndex + 1, 4).setValue(new Date());
            } else {
                Logger.log("投稿の公開に失敗: " + content + ", ステータスコード: " + publishResponse.getResponseCode());
                Logger.log("レスポンス: " + publishResponse.getContentText());
            }
        } else {
            Logger.log("スレッドの作成に失敗: " + content + ", ステータスコード: " + createResponse.getResponseCode());
            Logger.log("レスポンス: " + createResponse.getContentText());
        }
    } catch (error) {
        Logger.log("エラー発生: " + error);
    }
}

function checkAndRefreshToken() {
    var service = getServiceThreads();
    if (service.hasAccess()) {
        Logger.log('トークンは有効です。');
        return true;
    } else {
        Logger.log('トークンが無効または期限切れです。更新を試みます。');
        try {
        if (service.refresh()) {
            Logger.log('トークンを更新しました。');
            return true;
        } else {
            Logger.log('トークンの更新に失敗しました。再認証が必要です。');
            return false;
        }
        } catch (e) {
        Logger.log('エラーが発生しました: ' + e.toString());
        Logger.log('再認証が必要です。getAuthorizationUrl()を実行してください。');
        return false;
        }
    }
}

function clearStoredToken() {
    PropertiesService.getUserProperties().deleteProperty('oauth2.threads');
    Logger.log('保存されていたトークンをクリアしました。');
}