%%-----------------------------------------------------------------------------
%% @Module  :       lib_cloud_buy.erl
%% @Author  :       hyh
%% @Email   :       huyihao@suyougame.com
%% @Created :       2018-03-20
%% @Description:    众仙云购
%%-----------------------------------------------------------------------------

-module(lib_cloud_buy).

-include("cloud_buy.hrl").
-include("server.hrl").
-include("errcode.hrl").
-include("predefine.hrl").
-include("language.hrl").
-include("def_module.hrl").
-include("figure.hrl").
-include("custom_act.hrl").
-include("common.hrl").
-include("goods.hrl").

-export ([
    order_success/5             %% 订单成功，预扣款
    ,pay_for_order/5            %%
    ,pay_order_error/3
    ,return_error_order_cost/3
    ,award_result_handler/3
    ,set_cur_award_info/7
    ,set_cur_award_info_1/7
    ,order/5                    %% 下订单
    % ,get_order_first_code/1
    % ,format_orders_code/1
    ]).

order_success(RoleId, SubType, Order, IfAutoBuy, SubPid) ->
    lib_player:apply_cast(RoleId, ?APPLY_CALL_SAVE, ?NOT_HAND_OFFLINE, lib_cloud_buy, pay_for_order, [SubType, Order, IfAutoBuy, SubPid]).

%% 订单下成功，随机得到保底奖励
pay_for_order(Ps, SubType, Order, IfAutoBuy, SubPid) ->
    #player_status{
        id = RoleId,
        sid = Sid,
        figure = #figure{career = Career},
        cloud_buy_list = CloudBuyDataList
    } = Ps,
    BuyData = lists:keyfind(SubType, #cloud_buy_status.subtype, CloudBuyDataList),
    #cloud_order{
        big_award_id = BigAwardId,
        count = Count
    } = Order,
    #cloud_award_config{
        cost = CostList,
        happy_awards = HappyAwardsWeightList
    } = data_cloud_buy:get(BigAwardId),
    %% 获取随机奖励
    {NewHappyAwards, AwardSendList} = cloud_rand_rewards(Count, HappyAwardsWeightList, [], [], Career),
    NewCostList = lib_goods_util:goods_object_multiply_by(CostList, Count),
    Node = clusters_node:get_node(),
    case lib_goods_api:can_give_goods(Ps, NewHappyAwards) of
        false -> %% 背包空间不足
            NewPs1 = Ps,
            gen_server:cast(SubPid, {pay_order_done, Node, RoleId, Order, NewHappyAwards, error}),
            lib_server_send:send_to_sid(Sid, pt_331, 33113, [?ERRCODE(err153_bag_not_enough), SubType, []]),
            NewBuyData = BuyData#cloud_buy_status{cur_order = undefined};
        true ->
            Result = case IfAutoBuy of
                0 -> lib_goods_api:cost_object_list_with_check(Ps, NewCostList, cloud_buy, "");
                _ -> lib_goods_api:cost_objects_with_auto_buy(Ps, NewCostList, cloud_buy, "")
            end,
            case Result of
                {true, CostPs1, _RealCostList} ->
                    NewPs1 = lib_goods_api:send_reward(CostPs1, NewHappyAwards, cloud_buy_happy, 0),
                    lib_server_send:send_to_sid(Sid, pt_331, 33113, [?SUCCESS, SubType, AwardSendList]),
                    gen_server:cast(SubPid, {pay_order_done, Node, RoleId, Order, NewHappyAwards, ok}),
                    NewBuyData = BuyData#cloud_buy_status{
                        cur_order = Order
                    };
                {false, ErrCode, NewPs1} -> %% 扣款失败
                    gen_server:cast(SubPid, {pay_order_done, Node, RoleId, Order, NewHappyAwards, error}),
                    lib_server_send:send_to_sid(Sid, pt_331, 33113, [ErrCode, SubType, []]),
                    NewBuyData = BuyData#cloud_buy_status{
                        cur_order = undefined
                    }
            end
    end,
    NewCloudBuyDataList = lists:keyreplace(SubType, #cloud_buy_status.subtype, CloudBuyDataList, NewBuyData),
    NewPs1#player_status{
        cloud_buy_list = NewCloudBuyDataList
    }.

cloud_rand_rewards(0, _HappyAwardsWeightList, NewHappyAwards, AwardSendList, _Career) ->
    {NewHappyAwards, AwardSendList};
cloud_rand_rewards(Count, HappyAwardsWeightList, NewHappyAwards, AwardSendList, Career) ->
    HappyAwardsId = urand:rand_with_weight(HappyAwardsWeightList),
    HappyAwardsCon = data_cloud_buy:get_cloud_buy_reward_con(HappyAwardsId),
    #cloud_buy_reward_con{
        reward_type = RewardType,
        reward_list = HappyAwards
    } = HappyAwardsCon,
    case RewardType of
        1 -> % 普通奖励
            TmpReward = HappyAwards;
        2 -> %% 按职业区分
            case lists:keyfind(Career, 1, HappyAwards) of
                {Career, TmpReward} -> ok;
                _ -> TmpReward = []
            end;
        _ -> TmpReward = []
    end,
    case TmpReward of
        [{GoodsType, GoodsTypeId, GoodsNum}|_] ->
            case lists:keyfind(GoodsTypeId, 2, NewHappyAwards) of
                false ->
                    NewHappyAwards1 = [{GoodsType, GoodsTypeId, GoodsNum}|NewHappyAwards];
                {_, _, GoodsNum1} ->
                    NewHappyAwards1 = lists:keyreplace(GoodsTypeId, 2, NewHappyAwards, {GoodsType, GoodsTypeId, GoodsNum1+GoodsNum})
            end,
            case lists:keyfind(HappyAwardsId, 1, AwardSendList) of
                false ->
                    AwardSendList1 = [{HappyAwardsId, 1}|AwardSendList];
                {_, RewardNum} ->
                    AwardSendList1 = lists:keyreplace(HappyAwardsId, 1, AwardSendList, {HappyAwardsId, RewardNum+1})
            end,
            cloud_rand_rewards(Count-1, HappyAwardsWeightList, NewHappyAwards1, AwardSendList1, Career);
        _ ->
            ?ERR("cloud_rand_rewards wrong :(~p)~n", [{Career, HappyAwardsId}]),
            cloud_rand_rewards(Count-1, HappyAwardsWeightList, NewHappyAwards, AwardSendList, Career)
    end.

%% 成功扣除东西下订单后没找到订单数据，返还订单扣除的道具
pay_order_error(RoleId, SubType, OrderId) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, ?NOT_HAND_OFFLINE, ?MODULE, return_error_order_cost, [SubType, OrderId]).

return_error_order_cost(Ps, SubType, OrderId) ->
    #player_status{
        cloud_buy_list = CloudBuyDataList
    } = Ps,
    Data = lists:keyfind(SubType, #cloud_buy_status.subtype, CloudBuyDataList),
    case Data of
        #cloud_buy_status{cur_order = #cloud_order{order_id = OrderId, big_award_id = _BigAwardId, count = _Count}} ->
            % #cloud_award_config{cost = CostList} = data_cloud_buy:get(BigAwardId),
            % Return = [{GoodsType, GoodsId, GoodsNum*Count} || {GoodsType, GoodsId, GoodsNum} <- CostList],
            % ActName = lib_custom_act_api:get_act_name(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType),
            % Produce = #produce{reward = Return, type = cloud_buy_error, title = utext:get(3310049, [ActName]), content = utext:get(3310050, [ActName])},
            % {ok, NewPs} = lib_goods_api:send_reward_with_mail(Ps, Produce, ?MOD_AC_CUSTOM),
            % 这里暂且改成不返还，避免保底奖励被刷，可根据物品消费日志和云购订单日志追溯
            NewData = Data#cloud_buy_status{cur_order = undefined},
            NewCloudBuyDataList = lists:keyreplace(SubType, #cloud_buy_status.subtype, CloudBuyDataList, NewData),
            Ps#player_status{cloud_buy_list = NewCloudBuyDataList};
        _ ->
            Ps
    end.

%% 大奖结果出来给所有参与者发邮件
award_result_handler(BigAwardId, Bunch, LuckyOrderNameList) ->
    Config = data_cloud_buy:get(BigAwardId),
    spawn(fun () ->
        [begin
            send_reward_mail(RoleId, AwardState, Config, LuckyOrderNameList, Career),
            timer:sleep(1000)
        end|| {RoleId, _AllBuyCount, AwardState, Career} <- Bunch]
    end).

send_reward_mail(RoleId, State, Config, LuckyOrderNameList, Career) ->
    #cloud_award_config{reward_type = RewardType, rewards = Rewards} = Config,
    case RewardType of
        1 -> NewRewards = Rewards;
        2 ->
            case lists:keyfind(Career, 1, Rewards) of
                {Career, NewRewards} -> ok;
                _ -> NewRewards = []
            end;
        _ -> NewRewards = []
    end,
    SMsg = ulists:list_to_string(LuckyOrderNameList, ","),
    Msg = util:make_sure_binary(SMsg),
    if
        LuckyOrderNameList == [] -> %% 没开出奖
            Title = ?LAN_MSG(?LAN_TITLE_CLOUD_BUY_NOMAL),
            Content = utext:get(?LAN_CONTENT_CLOUD_BUY_NO_LUCKY_ORDER, []),
            AllRewards = [];
        State =:= ?ORDER_STATE_AWARD -> %% 中奖了
            Title = ?LAN_MSG(?LAN_TITLE_CLOUD_BUY_LUCKY),
            Content = utext:get(?LAN_CONTENT_CLOUD_BUY_LUCKY, [Msg]),
            AllRewards = NewRewards;
        true ->  %% 有大奖得主但不是你
            Title = ?LAN_MSG(?LAN_TITLE_CLOUD_BUY_NOMAL),
            Content = utext:get(?LAN_CONTENT_CLOUD_BUY_NOMAL, [Msg]),
            AllRewards = []
    end,
    lib_mail_api:send_sys_mail([RoleId], ?MOD_AC_CUSTOM, ?CUSTOM_ACT_TYPE_CLOUD_BUY, Title, Content, AllRewards).

set_cur_award_info(RoleId, SubType, AwardTime, BigAwardId, Count, IfAutoBuy, Num) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, ?NOT_HAND_OFFLINE, ?MODULE, set_cur_award_info_1, [SubType, AwardTime, BigAwardId, Count, IfAutoBuy, Num]).

set_cur_award_info_1(PS, SubType, AwardTime, BigAwardId, Count, IfAutoBuy, Num) ->
    #player_status{cloud_buy_list = CloudBuyDataList} = PS,
    CloudBuyStatus =  lists:keyfind(SubType, #cloud_buy_status.subtype, CloudBuyDataList),
    NewCloudStatus = CloudBuyStatus#cloud_buy_status{
        req_times = 0,
        big_award_id = BigAwardId,
        award_time = AwardTime
    },
    NewCloudBuyDataList = lists:keyreplace(SubType, #cloud_buy_status.subtype, CloudBuyDataList, NewCloudStatus),
    NewPs = PS#player_status{cloud_buy_list = NewCloudBuyDataList},
    case order(NewPs, SubType, Count, IfAutoBuy, Num + 1) of
        {ok, NewPs1} ->
            NewPs1;
        _ ->
            NewPs
    end.

% get_order_first_code(#cloud_order{order_id = Id, big_award_id = BigAwardId}) ->
%     io_lib:format("~-4.16.0B~4.16.0B~8.16.0B", [BigAwardId, 1, Id]).

% format_orders_code(Orders) ->
%     [pt:write_string(io_lib:format("~-4.16.0B~4.16.0B~8.16.0B", [BigAwardId, I, Id])) || #cloud_order{order_id = Id, count = Count, big_award_id = BigAwardId} <- Orders, I <- lists:seq(1, Count)].

order(Ps, SubType, Count, IfAutoBuy, Num) ->
    if
        Num > 1 -> skip; %% 避免同步活动数据失败导致改函数反复调用
        true ->
            #player_status{
                id = RoleId,
                sid = Sid,
                platform = Platform,
                server_num = Server,
                figure = Figure,
                cloud_buy_list = CloudBuyDataList
            } = Ps,
            #figure{
                name = Name,
                lv = Lv,
                career = Career
            } = Figure,
            CloudOpenLv = lib_module:get_open_lv(?MOD_AC_CUSTOM, ?CUSTOM_ACT_TYPE_CLOUD_BUY),
            case Lv >= CloudOpenLv of
                false ->
                    lib_server_send:send_to_sid(Sid, pt_331, 33113, [?LEVEL_LIMIT, SubType, []]);
                true ->
                    case lib_custom_act_util:get_custom_act_open_info(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType) of
                        #act_info{etime = EndTime} ->
                            Now = utime:unixtime(),
                            Node = clusters_node:get_node(),
                            case lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType, if_kf) of
                                false ->
                                    lib_server_send:send_to_sid(Sid, pt_331, 33113, [?MISSING_CONFIG, SubType, []]);
                                {if_kf, IfKf} ->
                                    case lists:keyfind(SubType, #cloud_buy_status.subtype, CloudBuyDataList) of
                                        #cloud_buy_status{award_time = Time} when Now >= Time andalso Time + 60*60*24 > EndTime -> %% 已开奖且活动结束
                                            lib_server_send:send_to_sid(Sid, pt_331, 33113, [?ERRCODE(err331_cloud_buy_end), SubType, []]);
                                        #cloud_buy_status{big_award_id = BigAwardId, award_time = Time} when Time > Now -> % 还没开奖
                                            case data_cloud_buy:get(BigAwardId) of
                                                #cloud_award_config{cost = CostList} ->
                                                    Result = case IfAutoBuy of
                                                        0 -> lib_goods_api:check_object_list(Ps, CostList);
                                                        _ -> lib_goods_api:check_object_list_with_auto_buy(Ps, CostList)
                                                    end,
                                                    case Result of
                                                        true ->
                                                            % {VipType, VipLv} = lib_vip_api:get_valid_vip_lv(Ps),
                                                            Args = [Node, Platform, Server, RoleId, Name, Sid, Count, _VipType = 0, _VipLv = 0, IfAutoBuy, Career],
                                                            case IfKf of
                                                                0 ->
                                                                    mod_cloud_buy_mgr:order(SubType, Node, Sid, Args);
                                                                _ ->
                                                                    clusters_node:apply_cast(mod_cloud_buy_mgr, order, [SubType, Node, Sid, Args])
                                                            end;
                                                        {false, ErrCode} ->
                                                            lib_server_send:send_to_sid(Sid, pt_331, 33113, [ErrCode, SubType, []])
                                                    end;
                                                _ ->
                                                    lib_server_send:send_to_sid(Sid, pt_331, 33113, [?MISSING_CONFIG, SubType, []])
                                            end;
                                        UnInitual -> %% 未同步活动数据到玩家身上 已开奖且活动尚未结束，更新玩家身上的云购信息并且重新跑一次购买流程
                                            if
                                                is_record(UnInitual, cloud_buy_status) ->
                                                    ReqTimes = UnInitual#cloud_buy_status.req_times rem 1, %% req_times什么意思，请求数据的次数？目前好像没用到了
                                                    CloudStatus = UnInitual;
                                                true ->
                                                    ReqTimes = 0,
                                                    CloudStatus = #cloud_buy_status{subtype = SubType}
                                            end,
                                            if %% 看上面的操作这里不是永远为0了么
                                                ReqTimes =:= 0 ->
                                                    case IfKf of
                                                        0 -> mod_cloud_buy_mgr:get_cur_award_info(Node, SubType, RoleId, Count, IfAutoBuy, Num);
                                                        _ -> clusters_node:apply_cast(mod_cloud_buy_mgr, get_cur_award_info, [Node, SubType, RoleId, Count, IfAutoBuy, Num])
                                                    end;
                                                true -> skip
                                            end,
                                            NewCloudStatus = CloudStatus#cloud_buy_status{
                                                req_times = ReqTimes + 1
                                            },
                                            {ok, Ps#player_status{cloud_buy_list = [NewCloudStatus|CloudBuyDataList]}}
                                    end
                            end;
                        _ ->
                            lib_server_send:send_to_sid(Sid, pt_331, 33113, [?ERRCODE(err331_act_closed), SubType, []])
                    end
            end
    end.
