%%%------------------------------------
%%% @Module  : lib_growth_score
%%% @Author  :  ywf
%%% @Created :  2019-4-24
%%% @Description: 成长积分活动
%%%------------------------------------

-module(lib_growth_score).

-include("common.hrl").
-include("growth_score.hrl").
-include("custom_act.hrl").
-include("errcode.hrl").
-include("def_fun.hrl").
-include("server.hrl").
-include("goods.hrl").

-export ([
        init/0
        ,add_score/3
        ,add_score/6
        ,recieve_reward/5
        ,act_info/4
        ,clean_subtype/2
    ]).

init() ->
    AllScore = db:get_all(io_lib:format(?sql_select_custom_act_growth_score, [])),
    Fun1 = fun([RoleId, SubType, Score], ScoreMap) ->
            MemberMap = maps:get(SubType, ScoreMap, #{}),
            NewMemberMap = maps:put(RoleId, Score, MemberMap),
            maps:put(SubType, NewMemberMap, ScoreMap)
    end,
    ScoreMap = lists:foldl(Fun1, #{}, AllScore),
    AllReceived = db:get_all(io_lib:format(?sql_select_custom_act_growth_score_reward, [])),
    Fun2 = fun([RoleId, SubType, RecievedB], RecievedMap) ->
            Recieved = util:bitstring_to_term(RecievedB),
            MemberMap = maps:get(SubType, RecievedMap, #{}),
            NewMemberMap = maps:put(RoleId, Recieved, MemberMap),
            maps:put(SubType, NewMemberMap, RecievedMap)
    end,
    RecievedMap = lists:foldl(Fun2, #{}, AllReceived),
    #growth_score_status{score_map = ScoreMap, receive_reward_map = RecievedMap}.

%% 加分接口
add_score(PS, GoodsId, Num) ->
    OpenSubList = lib_custom_act_util:get_open_subtype_list(?CUSTOM_ACT_TYPE_GROWTH_SCORE),
    if
        OpenSubList =/= [] -> % 有还开着的活动则进入mod_growth_score去判断
            RwParam = lib_custom_act:make_rwparam(PS),
            mod_growth_score:add_score(PS#player_status.id, RwParam, GoodsId, Num, OpenSubList);
        true -> ok
    end.

%% 加分
add_score(State, RoleId, RwParam, GoodsId, Num, OpenSubList) ->
    ScoreMap = State#growth_score_status.score_map,
    {SqlArgs, NewScoreMap} = do_add_score(ScoreMap, RoleId, GoodsId, Num, [], OpenSubList),
    if
        SqlArgs == [] ->
            NeedSend = false;
        true ->
            NeedSend = true,
            db:insert_batch("REPLACE INTO `custom_act_growth_score` (`role_id`, `sub_type`, `score`)", SqlArgs)
    end,
    NewState = State#growth_score_status{score_map = NewScoreMap},
    if
        NeedSend ->
            [act_info(NewState, RoleId, RwParam, SubType) || [_, SubType, _]<-SqlArgs];
        true -> ok
    end,
    NewState.

do_add_score(ScoreMap, _RoleId, _GoodsId, _Num, SqlArgs, []) -> {SqlArgs, ScoreMap};
do_add_score(ScoreMap, RoleId, GoodsId, Num, SqlArgs, [#act_info{key = {_, SubType}}|OpenSubList]) ->
    case lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_GROWTH_SCORE, SubType, score) of
        {score, ScoreList} ->
            case lists:keyfind(GoodsId, 1, ScoreList) of
                {GoodsId, OneScore} ->
                    AddScore = OneScore * Num,
                    MemberMap = maps:get(SubType, ScoreMap, #{}),
                    OldScore = maps:get(RoleId, MemberMap, 0),
                    NewScore = OldScore + AddScore,
                    NewMemberMap = maps:put(RoleId, NewScore, MemberMap),
                    NewScoreMap = maps:put(SubType, NewMemberMap, ScoreMap),
                    NewSqlArgs = [[RoleId, SubType, NewScore]|SqlArgs];
                _ ->
                    NewSqlArgs = SqlArgs,
                    NewScoreMap = ScoreMap
            end;
        _ ->
            NewSqlArgs = SqlArgs,
            NewScoreMap = ScoreMap
    end,
    do_add_score(NewScoreMap, RoleId, GoodsId, Num, NewSqlArgs, OpenSubList).

%% 领取奖励
recieve_reward(State, RoleId, RwParam, SubType, RewardId) ->
    %% 判断是否可以领取奖励
    case lib_custom_act_util:get_act_reward_cfg_info(?CUSTOM_ACT_TYPE_GROWTH_SCORE, SubType, RewardId) of
        #custom_act_reward_cfg{condition = Condition} = RewardCfg ->
            case lib_custom_act_check:check_act_condtion([score], Condition) of
                [NeedScore] ->
                    Score = get_score(State, SubType, RoleId),
                    AlreadyReceivedReward = already_received_reward(State, SubType, RoleId, RewardId),
                    if
                        Score >= NeedScore ->
                            if
                                AlreadyReceivedReward =/= true -> %% 可领取
                                    Code = ?SUCCESS,
                                    NewState = do_recieve_reward(State, RoleId, RwParam, SubType, RewardCfg);
                                true -> % 已经领取过
                                    Code = ?ERRCODE(err331_already_get_reward),
                                    NewState = State
                            end;
                        true -> % 分数不够
                            Code = ?ERRCODE(err331_score_not_enough),
                            NewState = State
                    end;
                _ -> %% 配置有误
                    Code = ?ERRCODE(err331_no_act_reward_cfg),
                    NewState = State

            end;
        _ -> %% 配置有误
            Code = ?ERRCODE(err331_no_act_reward_cfg),
            NewState = State
    end,
    lib_server_send:send_to_uid(RoleId, pt_332, 33207, [SubType, Code]),
    NewState.

do_recieve_reward(State, RoleId, RwParam, SubType, RewardCfg) ->
    RewardId = RewardCfg#custom_act_reward_cfg.grade,
    ActType = ?CUSTOM_ACT_TYPE_GROWTH_SCORE,
    RewardList = lib_custom_act_util:count_act_reward(RwParam, RewardCfg),
    ActName = lib_custom_act_api:get_act_name(ActType, SubType),
    Produce = #produce{
        type    = custom_act,
        subtype = ActType,
        reward  = RewardList,
        remark  = util:term_to_string(SubType),
        title   = utext:get(3310009, [ActName]),
        content = utext:get(3310010, [ActName])
    },
    lib_goods_api:send_reward_with_mail(RoleId, Produce),
    RewardMap = State#growth_score_status.receive_reward_map,
    MemberMap = maps:get(SubType, RewardMap, #{}),
    OldReceivedList = maps:get(RoleId, MemberMap, []),
    NewReceivedList = [RewardId | OldReceivedList],
    NewMemberMap = maps:put(RoleId, NewReceivedList, MemberMap),
    NewRewardMap = maps:put(SubType, NewMemberMap, RewardMap),
    db:execute(io_lib:format(?sql_replace_custom_act_growth_score_reward, [RoleId, SubType, util:term_to_bitstring(NewReceivedList)])),
    %lib_log_api:log_custom_act_reward(RoleId, ActType, SubType, RewardId, RwParam#reward_param.wlv, RewardList, io_lib:format("grade:~p, score:~p", [RewardId, get_score(State, SubType, RoleId)]), utime:unixtime()),
    State#growth_score_status{receive_reward_map = NewRewardMap}.


get_score(State, SubType, RoleId) ->
    ScoreMap = State#growth_score_status.score_map,
    MemberMap = maps:get(SubType, ScoreMap, #{}),
    maps:get(RoleId, MemberMap, 0).

already_received_reward(State, SubType, RoleId, RewardId) ->
    RewardMap = State#growth_score_status.receive_reward_map,
    MemberMap = maps:get(SubType, RewardMap, #{}),
    RewardList = maps:get(RoleId, MemberMap, []),
    lists:member(RewardId, RewardList).

act_info(State, RoleId, _RwParam, SubType) ->
    ActType = ?CUSTOM_ACT_TYPE_GROWTH_SCORE,
    Score = get_score(State, SubType, RoleId),
    GradeIds = lib_custom_act_util:get_act_reward_grade_list(ActType, SubType),
    Fun = fun(GradeId, RewardInfo) ->
            case lib_custom_act_util:get_act_reward_cfg_info(ActType, SubType, GradeId) of
                #custom_act_reward_cfg{desc = Desc, condition = Condition, reward= RewardList} ->
                    case lib_custom_act_check:check_act_condtion([score], Condition) of
                        [NeedScore] ->
                            AlreadyReceivedReward = already_received_reward(State, SubType, RoleId, GradeId),
                            RewardState = ?IF(AlreadyReceivedReward, ?ACT_REWARD_HAS_GET, ?IF(Score >= NeedScore, ?ACT_REWARD_CAN_GET, ?ACT_REWARD_CAN_NOT_GET)),
                            RewardStr = util:term_to_string(RewardList),
                            [{GradeId, NeedScore, RewardStr, Desc, RewardState}|RewardInfo];
                        _ -> RewardInfo
                    end;
                _ -> RewardInfo
            end
    end,
    RewardInfo = lists:foldl(Fun, [], GradeIds),
    lib_server_send:send_to_uid(RoleId, pt_332, 33206, [SubType, Score, RewardInfo]).

%% 活动结束清理数据
clean_subtype(State, SubType) ->
    db:execute(io_lib:format(?sql_delete_custom_act_growth_score, [SubType])),
    db:execute(io_lib:format(?sql_delete_custom_act_growth_score_reward, [SubType])),
    ScoreMap = State#growth_score_status.score_map,
    RewardMap = State#growth_score_status.receive_reward_map,
    NewScoreMap = maps:remove(SubType, ScoreMap),
    NewRewardMap = maps:remove(SubType, RewardMap),
    State#growth_score_status{score_map = NewScoreMap, receive_reward_map = NewRewardMap}.
