%%-----------------------------------------------------------------------------
%% @Module  :       lib_custom_act_investment
%% @Author  :       zmh
%% @Created :       20201010
%% @Description:	投资
%%-----------------------------------------------------------------------------
-module (lib_custom_act_investment).

-compile(export_all).
-include("custom_act.hrl").
-include("common.hrl").
-include("server.hrl").
-include("errcode.hrl").
-include("figure.hrl").
-include("def_goods.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("predefine.hrl").

send_invest_act_info(Status, SubType) ->
    #player_status{id=RoleID}=Status,
    Type = ?CUSTOM_ACT_TYPE_INVESTMENT,
    InvestStatusList = pack_p_act_info(Status, Type, SubType),
    {ok, Bin} = pt_331:write(33141, [SubType, InvestStatusList]),
    lib_server_send:send_to_uid(RoleID, Bin),
    ok.

pack_p_act_info(Status, Type, SubType) ->
    case custom_act_personal:is_personal_act_open(Status, Type, SubType) of
        {true, _EndTime} ->
            #custom_act_personal{
                act_data = ActData
            } = custom_act_personal:get_custom_act_personal_open_info(Status, Type, SubType),
            RewardL = lib_custom_act_util:get_act_reward_cfg_list(Type, SubType),
            Fun = fun(RewardCfg = #custom_act_reward_cfg{grade = Grade}) ->
                {IsBuy,StatusList} = act_award_status(Grade,RewardCfg, ActData),
                {Grade, IsBuy, StatusList}
            end,
            AwardStatusList = [Fun(Cfg) || Cfg <- RewardL],
            AwardStatusList;
        _ ->
            []
    end.

act_award_status(Grade, AwardConfig, InvestList) ->
    #custom_act_reward_cfg{reward=AwardList} = AwardConfig,
    Now = utime:unixtime(),
    case lists:keyfind(Grade, #custom_act_invest.grade, InvestList) of
        #custom_act_invest{time=BuyTime,awards=OStatusList} ->
            DiffD = utime:day_span(Now,BuyTime),
            StatusList = do_act_award_status(DiffD,OStatusList,AwardList),
            {1,StatusList};
        _ ->
            StatusList = do_act_award_status(0,[{1,0}],AwardList),
            {0,StatusList}
    end.


do_act_award_status(_DiffD,StatusList,[])->
    StatusList;
do_act_award_status(DiffD,OStatusList,[{AwardId,_}|T])->
    case lists:keyfind(AwardId,1,OStatusList) of
        {_,2}->
            do_act_award_status(DiffD,OStatusList,T);
        {_,1}->
            do_act_award_status(DiffD,OStatusList,T);
        _->
            case DiffD>=AwardId of
                true->
                    do_act_award_status(DiffD,lists:keystore(AwardId,1,OStatusList,{AwardId,1}),T);
                _->
                    do_act_award_status(DiffD,lists:keystore(AwardId,1,OStatusList,{AwardId,0}),T)
            end
    end.



%% 购买投资
buy_investment(Status, SubType, Grade) ->
    #player_status{
        id = RoleID,
        figure = #figure{lv=RoleLv}
    } = Status,
    Type = ?CUSTOM_ACT_TYPE_INVESTMENT,
    ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
    Data = custom_act_personal:get_custom_act_personal_open_info(Status, Type, SubType),
    NowTime = utime:unixtime(),
    CheckList = [
        {check_open,ActInfo,NowTime},
        {check_already,Grade,Data},
        {check_cfg,Grade,RoleLv,Status,SubType}
    ],
     case util:check_lists(?MODULE,CheckList) of
        {ok,{NStatus0,BuyType}}->
            #act_info{stime=STime}=ActInfo,
            BuyTime = case BuyType of
                0->
                    NowTime;
                _->
                    STime
            end,
            DiffDay = utime:day_span(NowTime,BuyTime),
            #custom_act_personal{act_data = ActData} = Data,
            AwardConfig = lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, Grade),
            #custom_act_reward_cfg{reward=AwardList} = AwardConfig,
            StatusList = do_act_award_status(DiffDay,[{1,2}],AwardList),
            Invest = #custom_act_invest{grade=Grade,time=BuyTime,awards=StatusList},
            NewInvestList = lists:keystore(Grade, #custom_act_invest.grade, ActData, Invest),
            NewData = Data#custom_act_personal{act_data = NewInvestList},
            NStatus = custom_act_personal:save_personal_act(NStatus0, NewData),
            custom_act_personal:save_personal_act_db(RoleID, NewData),
            {_,Awards} = lists:keyfind(1,1,AwardList),
            Produce = #produce{type = invest_rewards, reward=Awards},
            {ok,NewStatus} = lib_goods_api:send_reward_with_mail(NStatus, Produce, ?MOD_AC_CUSTOM),
            lib_log_api:custom_act_reward_log(NewStatus, Status, Type, SubType, Grade, io_lib:format("Day:~w", [1]),Awards),
            {ok,NewStatus};
        {false,Err}->
            {false,Err}
    end.

fetch_invest_award(Status, SubType, Grade, Day)->
    #player_status{
        id = RoleID
    } = Status,
    Type = ?CUSTOM_ACT_TYPE_INVESTMENT,
    Data = custom_act_personal:get_custom_act_personal_open_info(Status, Type, SubType),
    Invest = case Data of
        #custom_act_personal{act_data = TemActData} ->
            lists:keyfind(Grade,#custom_act_invest.grade,TemActData);
        _->
            false
    end,
    NowTime = utime:unixtime(),
    AwardConfig = lib_custom_act_util:get_act_reward_cfg_info(Type,SubType,Grade),
    CheckList = [
        {check_invest,Invest},
        {check_day,Day,Invest,NowTime},
        {check_awards,Invest,AwardConfig,Day}
    ],
     case util:check_lists(?MODULE,CheckList) of
        {ok,[NInvest,Awards]}->
            #custom_act_personal{act_data = ActData}=Data,
            NewInvestList = lists:keystore(Grade, #custom_act_invest.grade, ActData, NInvest),
            NewData = Data#custom_act_personal{act_data = NewInvestList},
            NStatus = custom_act_personal:save_personal_act(Status, NewData),
            custom_act_personal:save_personal_act_db(RoleID, NewData),
            Produce = #produce{type = invest_rewards,reward=Awards},
            {ok,NewStatus} = lib_goods_api:send_reward_with_mail(NStatus, Produce, ?MOD_AC_CUSTOM),
            lib_log_api:custom_act_reward_log(NewStatus, NStatus, Type, SubType, Grade, io_lib:format("Day:~w", [Day]),Awards),
            {ok,NStatus};
        {false,Err}->
            {false,Err}
    end.


check({check_invest,Invest})->
    case Invest of
        #custom_act_invest{}->
            true;
        _->
            {false,?ERRCODE(err420_no_investment)}
    end;
check({check_day,Day,Invest,NowTime})->
    #custom_act_invest{time=BuyTime}=Invest,
    RDay = utime:day_span(NowTime,BuyTime),
    case RDay>=Day of
        true->
            true;
        _->
            {false,?ERRCODE(err331_need_more_day)}
    end;
check({check_awards,Invest,AwardConfig,Day})->
    #custom_act_invest{awards=StatusList}=Invest,
    case AwardConfig of
        #custom_act_reward_cfg{reward=AwardList}->
            case lists:keyfind(Day,1,StatusList) of
                {_,1}->
                    case lists:keyfind(Day,1,AwardList) of
                        {_,Awards}->
                            NStatusList = lists:keystore(Day,1,StatusList,{Day,2}),
                            {ok,[Invest#custom_act_invest{awards=NStatusList},Awards]};
                        _->
                            {false,?ERRCODE(err_config)}
                    end;
                {_,2}->
                    {false,?ERRCODE(err420_reward_is_got)};
                _->
                    {false,?ERRCODE(err331_need_more_day)}
            end;
        _->
            {false,?ERRCODE(err_config)}
    end;
check({check_cfg,Grade,RoleLv,Status,SubType})->
    Type =  ?CUSTOM_ACT_TYPE_INVESTMENT,
    CfgResult = case lib_custom_act_util:get_act_cfg_info(Type, SubType) of
        #custom_act_cfg{condition = Condition} ->
            case lib_custom_act_check:check_act_condtion([role_lv,type], Condition) of
                [TempLv,TempType] ->
                    {true,TempLv,TempType};
                 _ ->
                    false
            end;
        _ ->
            false
    end,
    case CfgResult of
        {true, NeedLv,_} when RoleLv<NeedLv->
            {false,?ERRCODE(err333_role_lev_less)};
        {true, _NeedLv,BuyType}->
            case lib_custom_act_util:get_act_reward_cfg_info(Type,SubType,Grade) of
                 #custom_act_reward_cfg{condition=Cfg}->
                    case lists:keyfind(limit_cost,1,Cfg) of
                        {_,CostV}->
                            Cost = [{?TYPE_GOLD,?GOODS_ID_GOLD,CostV}],
                            case lib_goods_api:cost_object_list_with_check(Status, Cost, custom_act_investment, integer_to_list(SubType)) of
                                {true, CostStatus,_} ->
                                    {ok,{CostStatus,BuyType}};
                                {false, Code, _} ->
                                    {false,Code}
                            end;
                        _->
                            {false,?ERRCODE(err_config)}
                    end;
                _->
                    {false,?ERRCODE(err_config)}
            end;
        _->
            {false,?ERRCODE(err_config)}
    end;
check({check_open,ActInfo,NowTime})->
    case ActInfo of
        #act_info{etime = Etime} when NowTime=<Etime->
            true;
        _->
            {false,?ERRCODE(err331_act_closed)}
    end;
check({check_already,Grade,Data})->
    case Data of
        #custom_act_personal{act_data = ActData}->
            case lists:keymember(Grade, #custom_act_invest.grade, ActData) of
                true->
                    {false,?ERRCODE(err331_invest_repeat)};
                _->
                    true
            end;
        _->
            {false,?ERRCODE(err331_act_closed)}
    end.

%%跨天
handle_event(Status, #event_callback{type_id = ?EVENT_ZERO_CLOCK}) ->
    {NStatus,Changes} = check_delay_fetch_mail(Status),
    [send_invest_act_info(NStatus, SubType)||SubType<-Changes],
    {ok,NStatus};
%%登录
handle_event(Status, #event_callback{type_id = ?EVENT_LOGIN_CAST}) ->
    {NStatus,_Changes} = check_delay_fetch_mail(Status),
    {ok,NStatus};
handle_event(Status, _) -> {ok, Status}.


%%检测玩家未领取2天 邮件发送
check_delay_fetch_mail(Status)->
    Now = utime:unixtime(),
    Type = ?CUSTOM_ACT_TYPE_INVESTMENT,
    SubList = lib_custom_act_util:get_subtype_list(Type),
    check_delay_fetch_mail(Status,Now,Type,SubList,[]).

check_delay_fetch_mail(Status,_Now,_Type,[],Changes)->
    {Status,Changes};
check_delay_fetch_mail(Status,Now,Type,[H|T],Changes)->
    case custom_act_personal:get_custom_act_personal_open_info(Status, Type, H) of
        Data = #custom_act_personal{act_data = ActData}->
            Len = length(ActData),
            [Awards,NewInvestList,OverN] = calc_overdue_awards(Type,H,Now,ActData),
            case Awards /= [] of
                true->
                    #player_status{id=RoleID}=Status,
                    NewData = Data#custom_act_personal{act_data = NewInvestList},
                    NStatus = custom_act_personal:save_personal_act(Status, NewData),
                    custom_act_personal:save_personal_act_db(RoleID, NewData),
                    #custom_act_cfg{name=Name}=lib_custom_act_util:get_act_cfg_info(Type, H),
                    lib_mail_api:send_sys_mail([RoleID], ?MOD_AC_CUSTOM, utext:get(3317501), utext:get(3317502,[Name]), Awards),
                    case OverN>=Len of
                        true->
                            {ok, Bin} = pt_331:write(33103, [[{Type,H}]]),
                            lib_server_send:send_to_uid(RoleID,Bin);
                        _->
                            skip
                    end,
                    check_delay_fetch_mail(NStatus,Now,Type,T,[H|Changes]);
                _->
                    %#player_status{id=RoleID}=Status,
                    NewData = Data#custom_act_personal{act_data = NewInvestList},
                    NStatus = custom_act_personal:save_personal_act(Status, NewData),
                    %custom_act_personal:save_personal_act_db(RoleID, NewData),
                    check_delay_fetch_mail(NStatus,Now,Type,T,[H|Changes])
            end;
        _->
            check_delay_fetch_mail(Status,Now,Type,T,Changes)
    end.

calc_overdue_awards(Type,SubType,Now,ActData)->
    calc_overdue_awards(Type,SubType,Now,ActData,[],[],0).
calc_overdue_awards(_Type,_SubType,_Now,[],Awards,InvestList,OverN)->
    [Awards,InvestList,OverN];
calc_overdue_awards(Type,SubType,Now,[Invest|T],Awards,InvestList,OverN)->
    #custom_act_invest{
       grade = Grade,
       time = BuyTime,
       awards = OStatusList
    }=Invest,
    AwardConfig = lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, Grade),
    #custom_act_reward_cfg{reward=AwardList} = AwardConfig,
    DiffDay    = utime:day_span(Now,BuyTime),
    StatusList = do_act_award_status(DiffDay,OStatusList,AwardList),
    case DiffDay-length(AwardList)>2 of
        true->
            [NStatusList,AddAwards] = do_check_status(StatusList,AwardList,[],[]),
            NInvest = Invest#custom_act_invest{awards=NStatusList},
            NAwards = AddAwards++Awards,
            calc_overdue_awards(Type,SubType,Now,T,NAwards,[NInvest|InvestList],OverN+1);
        _->
            NInvest = Invest#custom_act_invest{awards=StatusList},
            calc_overdue_awards(Type,SubType,Now,T,Awards,[NInvest|InvestList],OverN)
    end.


do_check_status([],_AwardList,StatusList,AddAwards)->
    [StatusList,AddAwards];
do_check_status([H|T],AwardList,StatusList,AddAwards)->
    case H of
        {Day,1}->
            {_,Add} = lists:keyfind(Day,1,AwardList),
            do_check_status(T,AwardList,[{Day,2}|StatusList],Add++AddAwards);
        _->
            do_check_status(T,AwardList,[H|StatusList],AddAwards)
    end.


%% ---------------------------------------------------------------------------
%% @doc 活动派发接口：定制活动开启或者关闭 默认处理
notify_other_module(?CUSTOM_ACT_STATUS_OPEN,ActInfo) ->
    case ActInfo of
        #act_info{key={?CUSTOM_ACT_TYPE_INVESTMENT,SubType},trigger_time = T} when T=:=1 ->
            db:execute(?delete_opening_custom_act_personal, [?CUSTOM_ACT_TYPE_INVESTMENT, SubType]);
        _->
            ok
    end;
notify_other_module(ActStatus,ActInfo)->
    lib_player:cast_online_role_apply(?APPLY_CAST_STATUS, ?MODULE, notify_other_module, [ActStatus,ActInfo]).

notify_other_module(Player,ActStatus,ActInfo)->
    #act_info{key = {ActType, SubType}} = ActInfo,
    case is_personal_act_open(Player,ActType,SubType) of
        false->
            lib_custom_act:broadcast_act_info(ActStatus, [ActInfo]);
        _->
            ok
    end,
    Player.

check_clean_invest(Player,ActInfo)->
    case ActInfo of
        #act_info{key={?CUSTOM_ACT_TYPE_INVESTMENT,SubType},trigger_time = T} when T=:=1 ->
           NPlayer = custom_act_personal:clear_personal_act_in_role(Player, ?CUSTOM_ACT_TYPE_INVESTMENT, SubType),
           NPlayer;
        _->
           Player
    end.

is_personal_act_open(Player,Type,SubType)->
    case custom_act_personal:get_custom_act_personal_open_info(Player, Type, SubType) of
        #custom_act_personal{s_time = STime, e_time = ETime, act_data = AwardList} ->
            Now = utime:unixtime(),
            Fun = fun(AwardInfo) ->
                #custom_act_invest{awards=StatusList} = AwardInfo,
                List = [Day||{Day,DayS}<-StatusList,DayS=:=?ACT_REWARD_CAN_GET],
                case length(List)=<0 of
                    true->
                        0;
                    _ ->
                        1 %% 购买了没有领取的话需要一直展示
                end
            end,
            CheckList = [Fun(AwardInfo) || AwardInfo <- AwardList],
            case lists:member(1,CheckList) of
                true->
                    {true, #act_info{
                        key = {Type, SubType},              %% {type, subtype}
                        stime = STime,
                        etime = ETime
                    }};
                _->
                    case Now>ETime of
                        true->
                            false;
                        _->
                            {true, #act_info{
                                key = {Type, SubType},              %% {type, subtype}
                                stime = STime,
                                etime = ETime
                            }}
                    end
            end;
        _ ->
            false
    end.
