import {HttpException, Inject, Injectable} from "@nestjs/common";
import {TUploadableMedia, TwitterApi, UploadMediaV1Params} from 'twitter-api-v2';
import {TwitterApiAutoTokenRefresher} from '@twitter-api-v2/plugin-token-refresher'

import {EUploadMimeType, MediaStatusV1Result} from "twitter-api-v2/dist/esm/types";
import {MediaV2MediaCategory} from "twitter-api-v2/dist/esm/types/v2/media.v2.types";
import {XCacheService} from "../x-cache/x-cache.service";

//oauth2
// clientId: Rl9BU2xXUHVqWl9rcVdWSWFFYWg6MTpjaQ
// clientSecet: h0WgiG24dAdLC80NWf3u-_X0Wzilm8ejLwO-iZ8nZ7UOG-5G5m
// ====

//oath 1.0 Access Token and Secret?
//consumer key tfQh9yhtgx30zvfmTUwQ3o3rh
//comsumer sceret ysQtt8PI3lmEdtWx9oRtC0OpDC7fSwYYSwkE5J4v2NIdEcFUHU
//Access Token        2043937828644536320-JWM8czpnoadaqQYj8Xp62ZCrZuVlBt
//Access Token Secret 9EjIg8E5S44Fw1U84UqGBNPx6T1cHBEh00iC8YffDurMO


@Injectable()
export class TwitterClient {
    private clientId = process.env.TWITTER_CLIENT_ID + '';
    private clientSecret = process.env.TWITTER_CLIENT_SECRET;
    // private consumerAppKey = 'tfQh9yhtgx30zvfmTUwQ3o3rh';
    // private consumerAppSecret = 'ysQtt8PI3lmEdtWx9oRtC0OpDC7fSwYYSwkE5J4v2NIdEcFUHU';
    // private oath10AccessToken = '2043937828644536320-JWM8czpnoadaqQYj8Xp62ZCrZuVlBt';
    // private oath10AccessTokenSecret = '9EjIg8E5S44Fw1U84UqGBNPx6T1cHBEh00iC8YffDurMO';

    private readonly userClient: any;

    constructor(
        @Inject() private cacheService: XCacheService,
    ) {
    }

    // async getTwitterClient() {
    //     return new TwitterApi({
    //         appKey: this.consumerAppKey,
    //         appSecret: this.consumerAppSecret,
    //         // Following access tokens are not required if you are
    //         // at part 1 of user-auth process (ask for a request token)
    //         // or if you want a app-only client (see below)
    //         accessToken: this.oath10AccessToken,
    //         accessSecret: this.oath10AccessTokenSecret,
    //     })
    // }


    async getTwitterClientV2() {
        return new TwitterApi(
            {
                clientId: this.clientId,
                clientSecret: this.clientSecret,
            },
        )
    }

    async getTwitterClientV2ViaAccessToken() {
        const accessToken = await this.getCacheAccessToken() as string;
        const refreshToken = await this.getCacheRefreshToken() as string;
        // console.log({refreshToken});

        // @ts-ignore
        // @ts-ignore
        return new TwitterApi(accessToken,
            {
                plugins: [
                    new TwitterApiAutoTokenRefresher({
                        refreshCredentials: {
                            clientId: '' + this.clientId,
                            clientSecret: this.clientSecret,
                        },
                        refreshToken,
                        // Hàm này được gọi tự động khi token được refresh thành công
                        onTokenUpdate: async (newTokens) => {
                            console.log('===> Token đã được làm mới:', newTokens);
                            await this.setCacheRefreshToken('' + newTokens.refreshToken);
                            await this.setCacheAccessToken(newTokens.accessToken);
                        },
                        // Hàm xử lý khi refresh thất bại (ví dụ: refresh token cũng hết hạn)
                        onTokenRefreshError: async (error) => {
                            console.error('Không thể refresh token:', error);
                            throw error;
                        },
                    }),
                ],
            });
    }

    async uploadImageV1(media: Buffer,  options: {
        media_type: `${EUploadMimeType}` | EUploadMimeType;
        media_category?: MediaV2MediaCategory;
        additional_owners?: string[];
    }, chunkSize?: number): Promise<string> {
        const client = await this.getTwitterClientV2ViaAccessToken();
        // return client.v2.uploadMedia(media, options, chunkSize);
        return client.v2.uploadMedia(media, options, chunkSize);
    }

    async postSimpleTwitte(content) {
        const client = await this.getTwitterClientV2ViaAccessToken();
        return client.v2.tweet(content)
    }

    async postReply(content: string, tweetId: string) {
        const client = await this.getTwitterClientV2ViaAccessToken();
        return client.v2.reply(content, tweetId)
    }

    async qoute(content: string, tweetId: string) {
        const client = await this.getTwitterClientV2ViaAccessToken();

        // @ts-ignore
        if (content.indexOf(`https://x.com/${process.env.TWITTER_USERNAME}/status`) === -1) {
            //hacking, use tweet instead of quote, because limit x
            return client.v2.tweet(content)
        }
        return client.v2.quote(content, tweetId)
    }

    async setCacheAccessToken(accessToken: string) {
        return this.cacheService.setCachedKey('tw_accesstoken', '' + accessToken, 24 * 3600);
    }

    async delCacheAccessToken() {
        return this.cacheService.delCachedKey('tw_accesstoken');
    }

    async getCacheAccessToken() {
        return this.cacheService.getCachedData('tw_accesstoken')
    }

    async getCacheRefreshToken() {
        return this.cacheService.getCachedData('tw_refreshtoken')
    }

    async setCacheRefreshToken(refreshToken: string) {
        //30day
        return this.cacheService.setCachedKey('tw_refreshtoken', refreshToken, 30 * 24 * 3600);
    }

    async refreshAccessToken() {
        const client = new TwitterApi({clientId: this.clientId, clientSecret: this.clientSecret});
        const refreshToken = await this.getCacheRefreshToken();

        const {
            client: refreshedClient,
            accessToken,
            refreshToken: newRefreshToken
        } = await client.refreshOAuth2Token('' + refreshToken);

        await this.cacheService.setCachedKey('tw_accesstoken_time_add', Date.now(), 3 * 24 * 3600);
        await this.setCacheAccessToken(accessToken);
        await this.setCacheRefreshToken('' + refreshToken);
// Example request
        await refreshedClient.v2.me();
    }
}
