# ログインボーナス!やったね!
# セガ秘 内部使用のみ(トレードマーク)

import json
from loguru import logger

from Static_Settings import *
from API_TitleServer import apiSDGB, calcSpecialNumber, WahlapServerBoomedError, Request500Error
from HelperLogInOut import apiLogin, apiLogout, generateTimestamp
from HelperGetUserThing import implGetUser_
from HelperUploadUserPlayLog import apiUploadUserPlaylog
from HelperUserAll import generateFullUserAll

def implLoginBonus(userId: int, currentLoginTimestamp:int, currentLoginResult, bonusGenerateMode=2):
    '''
    ログインボーナスデータをアップロードする
    '''
    musicDataToBeUploaded = {
    "musicId": 229, #ぐるぐるWASH
    "level": 0,
    "playCount": 2,
    "achievement": 0,
    "comboStatus": 0,
    "syncStatus": 0,
    "deluxscoreMax": 0,
    "scoreRank": 0,
    "extNum1": 0
}
    
    # UserData を取得
    currentUserData = implGetUser_("Data", userId)
    currentUserData2 = currentUserData['userData']

    # UserPlayLog を構築してアップロード
    currentUploadUserPlaylogApiResult = apiUploadUserPlaylog(userId, musicDataToBeUploaded, currentUserData2, currentLoginResult['loginId'])
    logger.debug(f"上传 UserPlayLog 结果: {currentUploadUserPlaylogApiResult}")

    # ログインボーナスリストを生成
    finalBonusList = generateLoginBonusList(userId,bonusGenerateMode)
    if not finalBonusList:
        return False
    
    # UserAllを構築してアップロード
    retries = 0
    while retries < 3:
        currentSpecialNumber = calcSpecialNumber()
        currentUserAll = generateFullUserAll(userId, currentLoginResult, currentLoginTimestamp, currentUserData2, currentSpecialNumber)

        currentUserAll['upsertUserAll']["userMusicDetailList"] = [musicDataToBeUploaded]
        currentUserAll['upsertUserAll']['userLoginBonusList'] = finalBonusList
        currentUserAll['upsertUserAll']['isNewMusicDetailList'] = "1"
        currentUserAll['upsertUserAll']['isNewLoginBonusList'] = "0" * len(finalBonusList)
        data = json.dumps(currentUserAll)

        try:
            currentUserAllResult = json.loads(apiSDGB(data, "UpsertUserAllApi", userId))
        except Request500Error:
            logger.warning("500エラーが発生しました。データを再構築します。")
            retries += 1
            continue
        except Exception:
            raise WahlapServerBoomedError("不明なエラー")
        break
    else:
        raise Request500Error("500エラーが発生しました。UserAllをアップロードできませんでした。")
    

    ###### Debug 機能:ログインボーナスをもう一度取得(確認用)
    apiLogout(currentLoginTimestamp, userId)
    apiLogin(currentLoginTimestamp, userId)
    data = json.dumps({
        "userId": int(userId),
        "nextIndex": 0,
        "maxCount": 2000
    })
    logger.debug(json.loads(apiSDGB(data, "GetUserLoginBonusApi", userId)))
    ###### PRODUCTION 用には、上記のコードを削除してください

    return currentUserAllResult

def generateLoginBonusList(userId, generateMode=1):
    '''
    ログインボーナスリストを生成します。
    generateMode は、ログインボーナスを生成する方法を指定します。
    1: 全部 MAX にする
    2: 選択したボーナスのみ MAX にする(選択したボーナスはないの場合は False を返す)
    '''
    # HDDから、ログインボーナスデータを読み込む
    # アップデートがある場合、このファイルを更新する必要があります
    # 必ず最新のデータを使用してください
    with open('loginBonus.json') as file:
        cache = json.load(file)
    loginBonusIdList = [item['id'] for item in cache]
    logger.debug(f"ログインボーナスIDリスト: {loginBonusIdList}")

    # ログインボーナスの MAX POINT は5の場合があります
    # その全部のボーナスIDをこのリストに追加してください
    # 必ず最新のデータを使用してください
    Bonus5Id = [12, 29, 30, 38, 43, 604]

    # サーバーからUserのログインボーナスデータを取得
    data = json.dumps({
        "userId": int(userId),
        "nextIndex": 0,
        "maxCount": 2000
    })
    UserLoginBonusResponse = json.loads(apiSDGB(data, "GetUserLoginBonusApi", userId))
    UserLoginBonusList = UserLoginBonusResponse['userLoginBonusList']
    
    # UserBonusList から bonusId を取得
    UserLoginBonusIdList = [item['bonusId'] for item in UserLoginBonusList]
    
    # 存在しないボーナス
    NonExistingBonuses = list(set(loginBonusIdList) - set(UserLoginBonusIdList))
    logger.debug(f"存在しないボーナス: {NonExistingBonuses}")

    bonusList = []
    if generateMode == 1: # AllMax Mode
        # 存在しているボーナスを追加
        for item in UserLoginBonusList:
            if not item['isComplete']:
                data = {
                    "bonusId": item['bonusId'],
                    "point": 4 if item['bonusId'] in Bonus5Id else 9,
                    "isCurrent": item['isCurrent'],
                    "isComplete": False
                }
                bonusList.append(data)
            elif item['bonusId'] == 999:
                data = {
                    "bonusId": 999,
                    "point": (item['point'] // 10) * 10 + 9,
                    "isCurrent": item['isCurrent'],
                    "isComplete": False
                }
                bonusList.append(data)
        # 存在しないボーナスを追加
        for bonusId in NonExistingBonuses:
            data = {
                "bonusId": bonusId,
                "point": 4 if bonusId in Bonus5Id else 9,
                "isCurrent": False,
                "isComplete": False
            }
            bonusList.append(data)
    elif generateMode == 2: # OnlyCurrent Mode
        for item in UserLoginBonusList:
            if item['isCurrent'] and not item['isComplete']:
                point = 4 if item['bonusId'] in Bonus5Id else 9
                data = {
                    "bonusId": item['bonusId'],
                    "point": point,
                    "isCurrent": True,
                    "isComplete": False
                }
                bonusList.append(data)
        if len(bonusList) == 0:
            logger.warning("このユーザーはログインボーナスを選択していませんから失敗")
            return False
    
    logger.debug(f"ログインボーナスリスト: {bonusList}")
    return bonusList

if __name__ == "__main__":
    userId = testUid
    currentLoginTimestamp = generateTimestamp()
    loginResult = apiLogin(currentLoginTimestamp, userId)

    if loginResult['returnCode'] != 1:
        logger.info("登录失败")
        exit()
    try:
        # Remember to change the mode to 1 if you want to give all bonuses
        logger.info(implLoginBonus(userId, currentLoginTimestamp, loginResult, 1))
        logger.info(apiLogout(currentLoginTimestamp, userId))
    except:
        logger.info(apiLogout(currentLoginTimestamp, userId))
        logger.warning("Error")