%%-----------------------------------------------------------------------------
%% @Module  :       mod_cloud_buy.erl
%% @Author  :       hyh
%% @Email   :       huyihao@suyougame.com
%% @Created :       2018-03-20
%% @Description:    众仙云购/幸运之星
%%-----------------------------------------------------------------------------

-module(mod_cloud_buy).

-include("common.hrl").
-include("custom_act.hrl").
-include("cloud_buy.hrl").
-include("vip.hrl").
-include("errcode.hrl").
-include("def_module.hrl").
-include("def_fun.hrl").

-behaviour(gen_server).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]).
-export([
    start_link/1
]).
%% define
-define (SERVER, ?MODULE).

%% API
start_link(SubType) ->
    gen_server:start_link(?SERVER, [SubType], []).

%% private
init([SubType]) ->
    State = do_init(SubType),
    {ok, State}.

handle_call(Msg, From, State) ->
    case catch do_handle_call(Msg, From, State) of
        {'EXIT', Error} ->
            ?ERR("handle_call error: ~p~nMsg=~p~n", [Error, Msg]),
            {reply, error, State};
        Return  ->
            Return
    end.

handle_cast(Msg, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = ActType
    } = State,
    case ActType > 0 of
        true ->
            case catch do_handle_cast(Msg, State) of
                {'EXIT', Error} ->
                    ?ERR("handle_cast error: ~p~nMsg=~p~n", [Error, Msg]),
                    {noreply, State};
                Return  ->
                    Return
            end;
        false ->
            {noreply, State}
    end.

handle_info(Info, State) ->
    case catch do_handle_info(Info, State) of
        {'EXIT', Error} ->
            ?ERR("handle_info error: ~p~nInfo=~p~n", [Error, Info]),
            {noreply, State};
        Return  ->
            Return
    end.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

terminate(_Reason, _State) ->
    ok.

do_handle_call(_Msg, _From, State) ->
    {reply, ok, State}.

%% 下订单
do_handle_cast({order, Args}, State) ->
    [Node, PlatForm, Server, RoleId, RoleName, Sid, Count, VipType, VipLv, IfAutoBuy, Career] = Args,
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        unfinished_orders = UnFinishedOrders,
        done_orders = DoneOrders,
        big_award_id = BigAwardId,
        clear_unfinished_ref = ClearRef,
        unlimited_time = UnlimitedTime,
        cur_count = CurCount
    } = State,
    {Code, Order, NewState} =
    case data_cloud_buy:get(BigAwardId) of
        #cloud_award_config{total_count = TotalCount} ->
            if
                Count + CurCount =< TotalCount ->
                    case lists:keyfind(RoleId, #cloud_order.customer_uid, UnFinishedOrders) of
                        false ->
                            Now = utime:unixtime(),
                            case Now > UnlimitedTime orelse check_personal_count_limit(SubType, DoneOrders, RoleId, VipType, VipLv, Count) of
                                true ->
                                    case catch create_a_order(BigAwardId, RoleId, RoleName, PlatForm, Server, Count, Now, SubType, Career) of
                                        {ok, O} ->
                                            NewUnFinishedOrders = [O|UnFinishedOrders],
                                            NewCurCount = CurCount + Count,
                                            NewClearRef
                                            = if
                                                is_reference(ClearRef) ->
                                                    ClearRef;
                                                true ->
                                                    make_clear_ref(NewUnFinishedOrders, Now)
                                            end,
                                            State1 = State#cloud_buy_kf_state{unfinished_orders = NewUnFinishedOrders, cur_count = NewCurCount, clear_unfinished_ref = NewClearRef},
                                            {ok, O, State1};
                                        _ ->
                                            {?FAIL, [], State}
                                    end;
                                _ ->
                                    {?ERRCODE(err331_cloud_buy_personal_limit), [], State}
                            end;
                        _ ->
                            {?ERRCODE(err331_cloud_buy_order_unfinished), [], State}
                    end;
                true ->
                    {?ERRCODE(err331_cloud_buy_not_enough), [], State}
            end;
        _ ->
            {?FAIL, [], State}
    end,
    if
        Code =/= ok ->
            unode:apply(Node, lib_server_send, send_to_sid, [Sid, pt_331, 33113, [Code, SubType, []]]);
        true ->
            unode:apply(Node, lib_cloud_buy, order_success, [RoleId, SubType, Order, IfAutoBuy, self()])
    end,
    {noreply, NewState};

do_handle_cast({pay_order_done, Node, RoleId, OldOrder, Reward, Res}, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        unfinished_orders = UnFinishedOrders,
        done_orders = DoneOrders, cur_count = CurCount
    } = State,
    OrderId = OldOrder#cloud_order.order_id,
    case lists:keytake(OrderId, #cloud_order.order_id, UnFinishedOrders) of
        {value, Order, OthersList} ->
            if
                Res =:= ok -> %% 扣款成功
                    NewCurCount = CurCount,
                    DoneOrder = Order#cloud_order{state = ?ORDER_STATE_PAID},
                    spawn(fun () ->log_order_done(SubType, DoneOrder, Reward) end),
                    NewDoneOrders = [DoneOrder|DoneOrders];
                true ->
                    NewCurCount = CurCount - Order#cloud_order.count,
                    DoneOrder = Order#cloud_order{state = ?ORDER_STATE_FAIL},
                    NewDoneOrders = DoneOrders
            end,
            save_order(DoneOrder),
            {noreply, State#cloud_buy_kf_state{unfinished_orders = OthersList, done_orders = NewDoneOrders, cur_count = NewCurCount}};
        _ -> %% 未查询到该订单，返还扣除的物品（然而之前已经发送了保底奖励，这里再返还，感觉会出问题）
            if
                Res =:= ok ->
                    spawn(fun () -> log_order_fail(SubType, OldOrder, Reward) end),
                    unode:apply(Node, lib_cloud_buy, pay_order_error, [RoleId, SubType, OrderId]);
                true ->
                    skip
            end,
            {noreply, State}
    end;

%% 获取最终大奖得主的信息
do_handle_cast({get_last_lucky_orders, Node, Sid}, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        last_lucky_orders = LastLuckyOrders,
        last_big_award_id = BigAwardId
    } = State,
    LastLuckyOrdersSendList = [begin
        {Platform, Server, util:make_sure_binary(RoleName), RoleUnique}
    end || #cloud_order{platform = Platform, server = Server, customer_name = RoleName, customer_uid = RoleUnique} <- LastLuckyOrders],
    {ok, BinData} = pt_331:write(33114, [SubType, BigAwardId, LastLuckyOrdersSendList]),
    unode:apply(Node, lib_server_send, send_to_sid, [Sid, BinData]),
    {noreply, State};

%% 获取活动信息
do_handle_cast({get_info, Node, RoleId, Sid, _VipType, _VipLv}, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        done_orders = Orders,
        award_time = AwardTime,
        cur_count = CurCount,
        unlimited_time = UnlimitedTime,
        big_award_id = BigAwardId
    } = State,
    VipLvCount = 0,
    % VipLvCount = lib_vip:get_vip_privilege(VipType, VipLv, ?MOD_AC_CUSTOM, ?CUSTOM_ACT_TYPE_CLOUD_BUY),
    case {lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType, award_time),
          lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType, unlimited_time),
          lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType, if_kf)} of
        {{award_time,[Hour,Minute]}, {unlimited_time,[UnlimitedHour, UnlimitedMinute]}, {if_kf, IfKf}} ->
            NowTime = utime:unixtime(),
            NowDate = utime:unixdate(),
            ConAwardTime = Hour*60*60 + Minute*60,
            {BeforeAwardTime, NextAwardTime} = get_between_award_time(Hour, Minute, NowTime, NowDate),
            %% 计算自己的购买数量和全服购买数量
            F = fun(O, {SelfBuyNum1, TodayBuyNum1}) ->
                #cloud_order{
                    customer_uid = CustomerUid,
                    count = Count,
                    time = OrderTime
                } = O,
                case CustomerUid of
                    RoleId ->
                        case OrderTime >= BeforeAwardTime andalso OrderTime < NextAwardTime of
                            true ->
                                SelfBuyNum2 = SelfBuyNum1 + Count,
                                TodayBuyNum2 = TodayBuyNum1 + Count;
                            false -> %% 不是当天奖励的订单
                                SelfBuyNum2 = SelfBuyNum1,
                                TodayBuyNum2 = TodayBuyNum1
                        end;
                    _ ->
                        SelfBuyNum2 = SelfBuyNum1,
                        TodayBuyNum2 = TodayBuyNum1
                end,
                {SelfBuyNum2, TodayBuyNum2}
            end,
            {SelfBuyNum, TodayBuyNum} = lists:foldl(F, {0, 0}, Orders),
            %% 解禁时间和开奖时间
            TodayUnlimitedTime = NowDate + UnlimitedHour*60*60 + UnlimitedMinute*60,
            TodayAwardTime = NowDate + ConAwardTime,
            %% 剩余购买次数
            case data_cloud_buy:get(BigAwardId) of
                #cloud_award_config{total_count = TotalCount} -> ok;
                _ -> ?ERR("BigAward Wrong Id:~p", [BigAwardId]), TotalCount = 0
            end,
            AllLessBuyNum = max(0, (TotalCount - CurCount)),
            case NowTime >= TodayUnlimitedTime andalso NowTime < TodayAwardTime of
                true ->
                    LessBuyNum = AllLessBuyNum;
                false ->
                    SelfLessBuyNum = max(0, (VipLvCount - TodayBuyNum)),
                    LessBuyNum = ?IF(AllLessBuyNum < SelfLessBuyNum, AllLessBuyNum, SelfLessBuyNum)
            end,
            %% 订单记录
            OrderRecs = lists:sublist(Orders, 10),
            OrderSendList =[{Platform, Server, RoleName, Count} || #cloud_order{platform = Platform, server = Server,customer_name = RoleName,count = Count} <- OrderRecs],
            {ok, BinData} = pt_331:write(33112, [?SUCCESS, SubType, IfKf, AwardTime, UnlimitedTime, CurCount, BigAwardId, OrderSendList, SelfBuyNum, LessBuyNum]),
            unode:apply(Node, lib_server_send, send_to_sid, [Sid, BinData]);
        _ ->
            ok
    end,
    {noreply, State};

%% 获取当前大奖信息
do_handle_cast({get_cur_award_info, Node, RoleId, Count, IfAutoBuy, Num}, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        award_time = AwardTime,
        big_award_id = BigAwardId
    } = State,
    unode:apply(Node, lib_cloud_buy, set_cur_award_info, [RoleId, SubType, AwardTime, BigAwardId, Count, IfAutoBuy, Num]),
    {noreply, State};

%% 活动关闭，清理数据
do_handle_cast({close}, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        start_time = StartTime,
        award_open_ref = AwardOpenRef,
        unlimited_ref = UnlimitedRef,
        clear_unfinished_ref = ClearRef
    } = State,
    util:cancel_timer(AwardOpenRef),
    util:cancel_timer(UnlimitedRef),
    util:cancel_timer(ClearRef),
    ?IF(StartTime > 0, db:execute(io_lib:format("DELETE FROM `cloud_buy_kf` WHERE `subtype` = ~p", [SubType])), ok),
    {stop, normal, State};

%% 秘籍开奖
do_handle_cast({gm_award}, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType,
        done_orders = DoneOrders,
        big_award_id = BigAwardId,
        cur_count = CurCount,
        award_time = AwardTime,
        award_open_ref = AwardOpenRef,
        unlimited_ref = UnlimitedRef
    } = State,
    util:cancel_timer(AwardOpenRef),
    util:cancel_timer(UnlimitedRef),
    #cloud_award_config{award_count = AwardCount, total_count = TotalCount} = data_cloud_buy:get(BigAwardId),
    if
        CurCount >= TotalCount ->
            LuckyOrders = handle_awards(DoneOrders, AwardCount, AwardTime, BigAwardId, SubType),
            case util:is_cls() of
                true ->
                    clusters_center:apply_to_all_node(mod_cloud_buy_local, send_award_tv, [LuckyOrders, SubType], 50);
                false ->
                    mod_cloud_buy_local:send_award_tv(LuckyOrders, SubType)
            end;
        true ->
            LuckyOrders = handle_awards(DoneOrders, 0, AwardTime, BigAwardId, SubType)
    end,
    NewState = State#cloud_buy_kf_state{
        done_orders = [],
        unfinished_orders = [],
        last_lucky_orders = LuckyOrders,
        last_big_award_id = BigAwardId,
        award_open_ref = [],
        unlimited_ref = [],
        end_time = 0
    },
    do_handle_cast({close}, NewState);

do_handle_cast(_Msg, State) ->
    {noreply, State}.

%% 定时清理未成功的订单（60s过期）
do_handle_info(clear_unfinished, State) ->
    #cloud_buy_kf_state{unfinished_orders = UnFinishedOrders, cur_count = CurCount} = State,
    Now = utime:unixtime(),
    {TimeoutOrders, NewUnFinishedOrders} = lists:partition(fun
        (#cloud_order{time = Time}) ->
            Time + 60 =< Now
    end, UnFinishedOrders),
    NewClearRef = make_clear_ref(NewUnFinishedOrders, Now),
    {noreply, State#cloud_buy_kf_state{unfinished_orders = NewUnFinishedOrders, clear_unfinished_ref = NewClearRef, cur_count = CurCount - calc_order_count(TimeoutOrders)}};

%% 解除购买限制，广播
do_handle_info(unlimited_open, State) ->
    #cloud_buy_kf_state{
        custom_act_subtype = SubType
    } = State,
    case util:is_cls() of
        true ->
            clusters_center:apply_to_all_node(mod_cloud_buy_local, send_unlimited_tv, [SubType], 50);
        false ->
            mod_cloud_buy_local:send_unlimited_tv(SubType)
    end,
    {noreply, State};

 %% 开奖时间到！
do_handle_info(award, State) ->
    #cloud_buy_kf_state{
        custom_act_type = Type,
        custom_act_subtype = SubType,
        done_orders = DoneOrders,
        big_award_id = BigAwardId,
        cur_count = CurCount,
        award_time = AwardTime,
        award_open_ref = AwardOpenRef,
        unlimited_time = UnlimitedTime,
        unlimited_ref = UnlimitedRef,
        end_time = EndTime
    } = State,
    NextAwardTime = AwardTime + 86400,
    NextUnlimitedTime = UnlimitedTime + 86400,
    #cloud_award_config{award_count = AwardCount, total_count = TotalCount} = data_cloud_buy:get(BigAwardId),
    if
        CurCount >= TotalCount -> %% 购买份数达到开奖份数
            LuckyOrders = handle_awards(DoneOrders, AwardCount, AwardTime, BigAwardId, SubType), %% 计算大奖得主
            if
                NextAwardTime =< EndTime -> %% 本次活动尚未关闭
                    AwardOpenRef1 = util:send_after(AwardOpenRef, (NextAwardTime - AwardTime) * 1000, self(), award), %% 下一次开奖计时器
                    UnlimitedRef1 = util:send_after(UnlimitedRef, (NextUnlimitedTime - UnlimitedTime) * 1000, self(), unlimited_open), %% 解除购买限制计时器
                    NewState = State#cloud_buy_kf_state{
                        done_orders = [],
                        unfinished_orders = [],
                        award_time = NextAwardTime,
                        award_open_ref = AwardOpenRef1,
                        last_lucky_orders = LuckyOrders,
                        last_big_award_id = BigAwardId,
                        big_award_id = get_next_big_award_id(Type, SubType, BigAwardId),
                        unlimited_time = NextUnlimitedTime,
                        unlimited_ref = UnlimitedRef1,
                        cur_count = 0
                    };
                true ->%% 活动关闭
                    NewState = State#cloud_buy_kf_state{
                        done_orders = [],
                        unfinished_orders = [],
                        last_lucky_orders = LuckyOrders,
                        last_big_award_id = BigAwardId
                    }
            end,
            case util:is_cls() of
                true ->
                    clusters_center:apply_to_all_node(mod_cloud_bu_ylocal, send_award_tv, [LuckyOrders, SubType], 50);
                false ->
                    mod_cloud_buy_local:send_award_tv(LuckyOrders, SubType)
            end;
        NextAwardTime > EndTime -> %% 还没卖完，不开奖,下次开奖时间超过了活动结束时间不仅如此下一轮
            LuckyOrders = handle_awards(DoneOrders, 0, AwardTime, BigAwardId, SubType),
            NewState = State#cloud_buy_kf_state{
                done_orders = [],
                unfinished_orders = [],
                last_lucky_orders = LuckyOrders,
                last_big_award_id = BigAwardId
            };
        true -> %% 还没卖完，不开奖, 进入下一轮云购
            AwardOpenRef1 = util:send_after(AwardOpenRef, (NextAwardTime - AwardTime) * 1000, self(), award),
            UnlimitedRef1 = util:send_after(UnlimitedRef, (NextUnlimitedTime - UnlimitedTime) * 1000, self(), unlimited_open),
            LuckyOrders = handle_awards(DoneOrders, 0, AwardTime, BigAwardId, SubType),
            NewState = State#cloud_buy_kf_state{
                done_orders = [],
                unfinished_orders = [],
                award_time = NextAwardTime,
                award_open_ref = AwardOpenRef1,
                last_lucky_orders = LuckyOrders,
                last_big_award_id = BigAwardId,
                big_award_id = get_next_big_award_id(Type, SubType, BigAwardId),
                unlimited_time = NextUnlimitedTime,
                unlimited_ref = UnlimitedRef1,
                cur_count = 0
            }
    end,
    db:execute(io_lib:format("DELETE FROM `cloud_buy_kf` WHERE `time`<~p AND `subtype` = ~p", [(AwardTime-24*60*60), SubType])),
    {noreply, NewState};

do_handle_info(_Msg, State) ->
    {noreply, State}.

%% internal
do_init(SubType) ->
    ActType = ?CUSTOM_ACT_TYPE_CLOUD_BUY,
    ZeroTime = utime:unixdate(),
    Now = utime:unixtime(),
    {StartTime, EndTime} = lib_custom_act_util:get_act_time_range_by_type(ActType, SubType),
    case lib_custom_act_util:keyfind_act_condition(ActType, SubType, award_time) of
        {award_time,[Hour,Minute]} -> % 当天的开奖时间
            TodayAwardTime = ZeroTime + Hour * 3600 + Minute * 60,
            if
                Now < TodayAwardTime orelse TodayAwardTime + 86400 =< EndTime -> % 活动开启中
                    {AwardId, Orders} = load(TodayAwardTime, Now, SubType), %% 载入当前奖励和订单
                    if
                        AwardId =:= 0 -> %% 启动之前活动未开启，从配置中读取大奖id
                            case lib_custom_act_util:keyfind_act_condition(ActType, SubType, big_award_ids) of
                                {big_award_ids, [BigAwardId|_]} -> ok;
                                _ -> [BigAwardId|_] = data_cloud_buy:get_big_award_ids()
                            end;
                        true ->
                            BigAwardId = AwardId
                    end,
                    %% 设置不限购买次数和开奖时间的定时器
                    case lib_custom_act_util:keyfind_act_condition(ActType, SubType, unlimited_time) of
                        {unlimited_time,[UH,UM]} ->
                            UnlimitedTime0 = ZeroTime + UH*3600 + UM * 60;
                        _A ->
                            UnlimitedTime0 = 0
                    end,
                    if
                        Now < TodayAwardTime ->
                            UnlimitedTime = UnlimitedTime0,
                            AwardDelay = TodayAwardTime - Now;
                        true ->
                            UnlimitedTime = UnlimitedTime0 + 86400,
                            AwardDelay = TodayAwardTime + 86400 - Now
                    end,
                    if
                        UnlimitedTime > Now ->
                            UnlimitedRef = erlang:send_after((UnlimitedTime - Now) * 1000, self(), unlimited_open);
                        true ->
                            UnlimitedRef = undefined
                    end,
                    AwardOpenRef1 = erlang:send_after(AwardDelay * 1000, self(), award),
                    %% 加载大奖得主
                    {LastBigAwardId, LastLuckyOrders} = load_last_lucky_orders(Now + AwardDelay, BigAwardId, SubType),
                    State = #cloud_buy_kf_state{
                        custom_act_type = ActType,
                        custom_act_subtype = SubType,
                        start_time = StartTime,
                        end_time = EndTime,
                        done_orders = Orders,
                        big_award_id = BigAwardId,
                        cur_count = calc_order_count(Orders),
                        award_time = Now + AwardDelay,
                        unlimited_time = UnlimitedTime,
                        unlimited_ref = UnlimitedRef,
                        award_open_ref = AwardOpenRef1,
                        last_big_award_id = LastBigAwardId,
                        last_lucky_orders = LastLuckyOrders
                    };
                true ->
                    case lib_custom_act_util:keyfind_act_condition(ActType, SubType, big_award_ids) of
                        {big_award_ids, [BigAwardId|_]} -> ok;
                        _ -> [BigAwardId|_] = data_cloud_buy:get_big_award_ids()
                    end,
                    State = #cloud_buy_kf_state{
                        custom_act_type = ActType,
                        custom_act_subtype = SubType,
                        start_time = StartTime,
                        end_time = EndTime,
                        big_award_id = BigAwardId,
                        award_time = TodayAwardTime
                    }
            end;
        _ ->
            ?ERR("Start Err SubType:~p~n", [SubType]),
            State = #cloud_buy_kf_state{}
    end,
    State.

% 加载当日订单数据和大奖数据
load(TodayAwardTime, Now, SubType) ->
    if
        TodayAwardTime > Now ->
            TimeBegin = TodayAwardTime - 86400;
        true ->
            TimeBegin = TodayAwardTime
    end,
    SQL = io_lib:format("SELECT `order_id`, `big_award_id`,`role_id`, `career`, `role_name`, `platform`, `server_num`, `count`, `state`, `time` FROM `cloud_buy_kf` WHERE `time` >= ~p AND `state`=~p AND `subtype` = ~p ORDER BY `time` DESC", [TimeBegin, ?ORDER_STATE_PAID, SubType]),
    case db:get_all(SQL) of
        [[_, BigAwardId|_]|_] = All ->
            Orders = [db_data_2_order(D) || D <- All],
            {BigAwardId, Orders};
        _ ->
            SQL2 = io_lib:format("SELECT `big_award_id` FROM `cloud_buy_kf` WHERE `time` >= ~p AND `subtype` = ~p LIMIT 1", [TimeBegin - 24*60*60, SubType]),
            case db:get_one(SQL2) of
                null ->
                    {0, []};
                BigAwardId ->
                    {BigAwardId, []}
            end
    end.

%% 计算订单数量
calc_order_count(Orders) ->
    lists:sum([Count || #cloud_order{count = Count} <- Orders]).

%% 检测购买次数是否达到上限
check_personal_count_limit(_SubType, _DoneOrders, _RoleId, _VipType, _VipLv, _BuyCount) -> 
    false.
    % case lib_vip:get_vip_privilege(VipType, VipLv, ?MOD_AC_CUSTOM, ?CUSTOM_ACT_TYPE_CLOUD_BUY) of
    %     0 ->
    %         false;
    %     VipLvCount ->
    %         %% 检测开奖时间
    %         case lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_CLOUD_BUY, SubType, award_time) of
    %             {award_time,[Hour,Minute]} ->
    %                 {BeforeAwardTime, NextAwardTime} = get_between_award_time(Hour, Minute),
    %                 F = fun(O, TodayBuyNum1) ->
    %                     #cloud_order{
    %                         customer_uid = CustomerUid,
    %                         count = Count,
    %                         time = OrderTime
    %                     } = O,
    %                     case CustomerUid of
    %                         RoleId ->
    %                             ?IF(OrderTime >= BeforeAwardTime andalso OrderTime < NextAwardTime, TodayBuyNum1 + Count, TodayBuyNum1);
    %                         _ ->
    %                             TodayBuyNum1
    %                     end
    %                 end,
    %                 TodayBuyNum = lists:foldl(F, 0, DoneOrders),
    %                 BuyCount + TodayBuyNum =< VipLvCount;
    %             _ -> false
    %         end
    % end.

%% 创建订单
create_a_order(BigAwardId, RoleId, RoleName, PlatForm, Server, Count, Now, SubType, Career) ->
    F = fun
        () ->
            SQL = io_lib:format("INSERT INTO `cloud_buy_kf` (`big_award_id`, `role_id`, `career`, `role_name`, `platform`, `server_num`, `count`, `state`, `time`, `subtype`) VALUES (~p, ~p, ~p, '~ts', '~ts', ~p, ~p, ~p, ~p, ~p)", [BigAwardId, RoleId, Career, RoleName, PlatForm, Server, Count, ?ORDER_STATE_NONE, Now, SubType]),
            db:execute(SQL),
            OId = db:get_one("SELECT LAST_INSERT_ID()"),
            Order = #cloud_order{
                order_id = OId,
                big_award_id = BigAwardId,
                customer_uid = RoleId,
                customer_name = RoleName,
                platform = PlatForm,
                server = Server,
                state = ?ORDER_STATE_NONE,
                count = Count,
                time = Now,
                career = Career
            },
            {ok, Order}
    end,
    db:transaction(F).

save_order(#cloud_order{order_id = OId, state = State}) ->
    SQL = io_lib:format("UPDATE `cloud_buy_kf` SET `state` = ~p WHERE `order_id` = ~p", [State, OId]),
    db:execute(SQL).

make_clear_ref([], _) -> undefined;
make_clear_ref(UnFinishedOrders, Now) ->
    MinTime = lists:min([T || #cloud_order{time = T} <- UnFinishedOrders]),
    Delay = max(1, MinTime - Now + 5),
    erlang:send_after(Delay* 1000, self(), clear_unfinished).

%% 开大奖
handle_awards(DoneOrders, AwardCount, AwardTime, BigAwardId, SubType) ->
    {LuckyOrders, NewDoneOrders} = calc_award(DoneOrders, AwardCount, [], []),
    PrevAwardTime = AwardTime - 86400,
    case [Id || #cloud_order{order_id = Id} <- LuckyOrders] of
        [] ->
            SQL = io_lib:format("UPDATE `cloud_buy_kf` SET `state`=3 WHERE `time` >= ~p AND `subtype` = ~p", [PrevAwardTime, SubType]);
        LuckyIds ->
            IsdStr = ulists:list_to_string(LuckyIds, ","),
            SQL = io_lib:format("UPDATE `cloud_buy_kf` SET `state`=if(`order_id` IN(~s), 2,3) WHERE `time` >= ~p AND `subtype` = ~p", [IsdStr, PrevAwardTime, SubType])
    end,
    db:execute(SQL),
    if length(LuckyOrders) > 0 -> spawn(fun() -> log_lucky_orders(SubType, LuckyOrders, BigAwardId) end); true -> ok end,
    F = fun
        (#cloud_order{customer_uid = RoleId, count = Count, state = State, career = Career}, Acc) ->
            case lists:keyfind(RoleId, 1, Acc) of
                {RoleId, AccCount, AccState, _} ->
                    NewAccState = if State =:= ?ORDER_STATE_AWARD -> ?ORDER_STATE_AWARD; true -> AccState end,
                    lists:keystore(RoleId, 1, Acc, {RoleId, AccCount + Count, NewAccState, Career});
                _ ->
                    [{RoleId, Count, State, Career}|Acc]
            end
    end,
    Baunch = lists:foldl(F, [], NewDoneOrders),
    LuckyOrderNameList = [io_lib:format("~s", [O#cloud_order.customer_name]) || O <- LuckyOrders],
    case util:is_cls() of
        true ->
            clusters_center:apply_to_all_node(lib_cloud_buy, award_result_handler, [BigAwardId, Baunch, LuckyOrderNameList], 50);
        false ->
            lib_cloud_buy:award_result_handler(BigAwardId, Baunch, LuckyOrderNameList)
    end,
    LuckyOrders.

%% 计算谁获得大奖
calc_award(DoneOrders, AwardCount, LuckyOrders, SetupOrders) when AwardCount > 0 andalso length(DoneOrders) > 0 ->
    WeightList = [{Weight, Order} || #cloud_order{count = Weight} = Order <- DoneOrders],
    #cloud_order{order_id = Id, customer_uid = RoleId} = Order = urand:rand_with_weight(WeightList),
    {PersonalList, OthersList} = lists:partition(fun
        (#cloud_order{customer_uid = U}) ->
            U =:= RoleId
    end, DoneOrders),
    PersonalList1 = [O#cloud_order{state = ?IF(OId =:= Id, ?ORDER_STATE_AWARD, ?ORDER_STATE_LOSE)} || #cloud_order{order_id = OId} = O <- PersonalList],
    NewLuckyOders = [Order|LuckyOrders],
    NewSetupOrders = PersonalList1 ++ SetupOrders,
    calc_award(OthersList, AwardCount - 1, NewLuckyOders, NewSetupOrders);

calc_award(DoneOrders, 0, LuckyOrders, SetupOrders) ->
    NewSetupOrders = [O#cloud_order{state = ?ORDER_STATE_LOSE} || O <- DoneOrders] ++ SetupOrders,
    {LuckyOrders, NewSetupOrders};

calc_award([], _, LuckyOrders, SetupOrders) ->
    {LuckyOrders, SetupOrders}.

%% 获取上一个大奖的得主
load_last_lucky_orders(NextAwardTime, NowBigAwardId, SubType) ->
    LastBeginTime = NextAwardTime - 86400*2,
    LastEndTime = LastBeginTime + 86400,
    SQL = io_lib:format("SELECT `order_id`, `big_award_id`,`role_id`, `career`, `role_name`, `platform`, `server_num`, `count`, `state`, `time` FROM `cloud_buy_kf` WHERE `state` = ~p AND `time` >= ~p AND `time` < ~p AND `subtype` = ~p", [?ORDER_STATE_AWARD, LastBeginTime, LastEndTime, SubType]),
    case db:get_all(SQL) of
        [[_, BigAwardId|_]|_] = All ->
            Orders = [db_data_2_order(D) || D <- All],
            {BigAwardId, Orders};
        _ ->
            {NowBigAwardId, []}
    end.

db_data_2_order([Id, BigAwardId, RoleId, Career, NStr, PStr, S, Count, State, Time]) ->
    #cloud_order{
        order_id = Id,
        customer_uid = RoleId,
        customer_name = NStr,
        platform = PStr,
        server = S,
        state = State,
        time = Time,
        count = Count,
        big_award_id = BigAwardId,
        career = Career
    }.

get_next_big_award_id(Type, SubType, BigAwardId) ->
    case lib_custom_act_util:keyfind_act_condition(Type, SubType, big_award_ids) of
        {big_award_ids, Ids} -> ok;
        _ -> Ids = data_cloud_buy:get_big_award_ids()
    end,
    case Ids of
        [Id|OthersList] ->
            get_next_id_circle(BigAwardId, Id, OthersList, Id);
        _ ->
            BigAwardId
    end.


get_next_id_circle(_BigAwardId, _NextId, [], FirstId) ->
    FirstId;
get_next_id_circle(BigAwardId, BigAwardId, [NextId|_], _FirstId) ->
    NextId;
get_next_id_circle(BigAwardId, _NextId, [NextId2|OthersList], FirstId) ->
    get_next_id_circle(BigAwardId, NextId2, OthersList, FirstId).

log_order_done(SubType, DoneOrder, Reward) ->
    #cloud_order{order_id = OId, customer_uid = RoleId, customer_name = RoleName, platform = PlatForm, server = Server, count = Count} = DoneOrder,
    Time = utime:unixtime(),
    Event = 1,
    Values = [[OId, RoleId, RoleName, PlatForm, Server, Count, Event, SubType, util:term_to_bitstring(Reward), Time]],
    lib_log_api:log_cloud_buy_kf(Values).

log_lucky_orders(SubType, Orders, Reward) ->
    Time = utime:unixtime(),
    Event = 2, %% 订单中奖
    Values = [
        [OId, RoleId, RoleName, PlatForm, Server, Count, Event, SubType, util:term_to_bitstring(Reward), Time] ||
        #cloud_order{order_id = OId, customer_uid = RoleId, customer_name = RoleName, platform = PlatForm, server = Server, count = Count} <- Orders
    ],
    lib_log_api:log_cloud_buy_kf(Values).

log_order_fail(SubType, OldOrder, Reward) ->
    #cloud_order{order_id = OId, customer_uid = RoleId, customer_name = RoleName, platform = PlatForm, server = Server, count = Count} = OldOrder,
    Time = utime:unixtime(),
    Event = 3,
    Values = [[OId, RoleId, RoleName, PlatForm, Server, Count, Event, SubType, util:term_to_bitstring(Reward), Time]],
    lib_log_api:log_cloud_buy_kf(Values).

%% 获取上次开奖时间和下次开奖时间
% get_between_award_time(AwardHour, AwardMinute) ->
%     NowTime = utime:unixtime(),
%     NowDate = utime:unixdate(),
%     get_between_award_time(AwardHour, AwardMinute, NowTime, NowDate).
get_between_award_time(AwardHour, AwardMinute, NowTime, NowDate) ->
    ConAwardTime = AwardHour*60*60 + AwardMinute*60,
    case (NowTime-NowDate) >= ConAwardTime of
        true ->
            BeforeAwardTime = NowDate + ConAwardTime,
            NextAwardTime = NowDate + 24*60*60 + ConAwardTime;
        false ->
            BeforeAwardTime = max(0, (NowDate - (24*60*60 - ConAwardTime))),
            NextAwardTime = NowDate + ConAwardTime
    end,
    {BeforeAwardTime, NextAwardTime}.

