%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%
%%% @end
%%%-------------------------------------------------------------------
-module(seckill_logic).
-author("liushl").

-include("seckill.hrl").
-include("custom_act.hrl").
-include("common.hrl").
-include("errcode.hrl").

%% API
-export([]).
-compile(export_all).

%% 打开秒杀界面-同时发送一次场次数据
handle({ask_seckill_info, Sid, RoleId, Lv}, SubType, State, ZoneInfo) ->
    #seckill_center{round_begin = RoundBegin, round_end = RoundEnd, round = Round} = State,
    RoundCfg =
        [
            {Id, util:term_to_bitstring(Time), Duration, Label}
            || {Id, Time, Duration, Label} <- data_custom_act:get_seckill_round()
        ],
    {ok, Bin} = pt_331:write(33187, [SubType, Round, RoundBegin, RoundEnd, RoundCfg]),
    lib_server_send:send_to_sid(Sid, Bin),
    handle({ask_seckill_info, Sid, RoleId, Lv, Round}, SubType, State, ZoneInfo);

%% 打开秒杀界面-某场次数据
handle({ask_seckill_round_info, Sid, RoleId, Lv, Round}, SubType, _State, ZoneInfo) ->
    #seckill_zone{
        goods_info = GoodsInfo,
        role_info  = RoleInfo
    } = ZoneInfo,
    %% 商品个人购买情况
    #seckill_role{buy_count = RoleBuyInfo}
        = maps:get(RoleId, RoleInfo, #seckill_role{role_id = RoleId}),
    GoodsList =
        lists:foldl(
            fun(Id, Temp) ->
                #custom_act_reward_cfg{
                    condition = Condition,
                    reward = Reward
                } = lib_custom_act_util:get_act_reward_cfg_info(?CUSTOM_ACT_TYPE_SECKILL, SubType, Id),
                case lists:keyfind(round, 1, Condition) of
                    {round, TheRound} when TheRound =:= Round ->
                        case lists:keyfind(show_level_range, 1, Condition) of
                            {show_level_range, LvMin, LvMax} when Lv >= LvMin andalso Lv =< LvMax ->
                                %% 商品总购买情况
                                case lists:keyfind(Id, #seckill_goods_info.grade_id, GoodsInfo) of
                                    #seckill_goods_info{buy_count = BuyCount} ->
                                        BuyCount;
                                    _ ->
                                        BuyCount = 0
                                end,
                                %% 个人对该商品的购买情况
                                case lists:keyfind(Id, 1, RoleBuyInfo) of
                                    {_, RoleBuyCount} -> RoleBuyCount;
                                    _ -> RoleBuyCount = 0
                                end,
                                [{Id, util:term_to_string(Reward), util:term_to_string(Condition), BuyCount, RoleBuyCount}|Temp];
                            _ ->
                                Temp
                        end;
                    _ ->
                        Temp
                end
            end, [], lib_custom_act_util:get_act_reward_grade_list(?CUSTOM_ACT_TYPE_SECKILL, SubType)
        ),
    {ok, Bin} = pt_331:write(33188, [Round, GoodsList]),
    lib_server_send:send_to_sid(Sid, Bin),
    ok;

%% 抢购-秒杀
handle({buy_seckill_goods, Node, RoleId, ServerNum, Name, GradeId}, SubType, State, ZoneInfo) ->
    #seckill_center{
        buy_log       = BuyLogs
        , round         = Round
        , round_begin   = RoundBegin
        , round_end     = RoundEnd
    } = State,
    #seckill_zone{
        zone_id = ZoneId
        , goods_info  = GoodsInfo
        , role_info   = RoleInfo
    } = ZoneInfo,
    Type = ?CUSTOM_ACT_TYPE_SECKILL,
    Config = custom_act_seckill:get_reward_config(Type, SubType, GradeId),
    %% 商品期数
    GoodsRound = custom_act_seckill:keyfind_reward_condition(Config, round, 0),
    %% 商品总购买情况
    GradeInfo =
        case lists:keyfind(GradeId, #seckill_goods_info.grade_id, GoodsInfo) of
            #seckill_goods_info{} = _GradeInfo ->
                _GradeInfo;
            _ ->
                #seckill_goods_info{grade_id = GradeId}
        end,
    %% 商品个人购买情况
    #seckill_role{buy_count = RoleBuyInfo} = OneRole
        = maps:get(RoleId, RoleInfo, #seckill_role{role_id = RoleId}),
    %% 个人该商品购买次数
    RoleBuyCount =
        case lists:keyfind(GradeId, 1, RoleBuyInfo) of
            {_, _RoleBuyCount} -> _RoleBuyCount;
            _ ->  0
        end,
    %% 总限购次数
    TotalLimit = custom_act_seckill:keyfind_reward_condition(Config, kfserver_limit, 0),
    %% 个人限购次数
    RoleLimit  = custom_act_seckill:keyfind_reward_condition(Config, personal_limit, 0),
    Now = utime:unixtime(),
    Res =
        if
            Config#custom_act_reward_cfg.reward == [] -> {false, ?ERRCODE(err331_no_act_reward_cfg)};
            GoodsRound < Round -> {false, ?ERRCODE(err331_seckill_closed)};
            GoodsRound > Round -> {false, ?ERRCODE(err331_seckill_not_open)};
            Now < RoundBegin -> {false, ?ERRCODE(err331_seckill_not_open)};
            Now > RoundEnd -> {false, ?ERRCODE(err331_seckill_closed)};
            RoleBuyCount >= RoleLimit -> {false, ?ERRCODE(err331_seckill_role_limit)};
            GradeInfo#seckill_goods_info.buy_count >= TotalLimit -> {false, ?ERRCODE(err331_seckill_total_limit)};
            true -> true
        end,
    case Res of
        {false, Error} ->
            {ok, Bin} = pt_331:write(33191, [GradeId, Error, 0]),
            lib_server_send:send_to_uid(Node, RoleId, Bin),
            ok;
        true ->
            #custom_act_reward_cfg{reward = [{_, GoodsId, Num}|_]} = Config,
            %% 更新单个商品购买情况
            NewGradeInfo = GradeInfo#seckill_goods_info{
                buy_count = GradeInfo#seckill_goods_info.buy_count + 1,
                time = Now
            },
            %% 更新玩家个人购买情况
            NewOneRole   = OneRole#seckill_role{
                buy_count = lists:keystore(GradeId, 1, OneRole#seckill_role.buy_count, {GradeId, RoleBuyCount + 1})
            },
            NewZoneInfo = ZoneInfo#seckill_zone{
                goods_info = lists:keystore(GradeId, #seckill_goods_info.grade_id, GoodsInfo, NewGradeInfo),
                role_info  = RoleInfo#{RoleId => NewOneRole}
            },
    
            %% 新增一条购买记录
            %% 固定一个传闻id
            TvId = urand:list_rand([19, 20, 21]),
            OneLog = #seckill_buy_log{
                server      = ServerNum,
                name        = Name,
                goods_id    = GoodsId,
                num         = Num,
                tv_id       = TvId,
                time        = Now
            },
            Logs = maps:get(ZoneId, BuyLogs, []),
            NewLogs = lists:sublist([OneLog|Logs], ?SECKILL_LOG_LENGTH),
            NewState = State#seckill_center{buy_log = maps:put(ZoneId, NewLogs, BuyLogs)},
    
            %% 发到玩家进程去扣钱+发奖
            custom_act_seckill:buy_seckill_success(Node, RoleId, SubType, GradeId, Round),
            %% 通知游戏服-广播传闻/订阅玩家刷新数据
            IsTv = custom_act_seckill:keyfind_reward_condition(Config, is_tv, 0),
            seckill_local:somebody_buy_seckill(SubType, ZoneId, OneLog, GradeId, IsTv, Round, TvId),
            {NewState,  NewZoneInfo}
    end;

handle(_Msg, _SubType, _State, _ZoneInfo) ->
    ok.