%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     满减折扣券
%%% @end
%%%-------------------------------------------------------------------
-module(lib_custom_act_do_discount_mall).
-author("liushl").

-include("server.hrl").
-include("custom_act.hrl").
-include("def_goods.hrl").
-include("errcode.hrl").
-include("figure.hrl").
-include("common.hrl").
%% API
-export([]).
-compile(export_all).

-define(DISCOUNT_COUPON_DIS,     1).    %% 折扣券类型
-define(DISCOUNT_COUPON_AB_DIS,  2).    %% 满减券类型

%% @doc 活动派发接口
count_receive_times(#player_status{status_custom_act = StatusCustom}, ActInfo, #custom_act_reward_cfg{grade = GradeId}) ->
    count_receive_times(StatusCustom#status_custom_act.reward_map, ActInfo, GradeId);
count_receive_times(RewardMap, ActInfo, GradeId) ->
    #act_info{key = {Type, SubType}, stime = Stime, etime = Etime} = ActInfo,
    case maps:get({Type, SubType, GradeId}, RewardMap, []) of
        #reward_status{utime = Utime, receive_times = ReceiveTimes} ->
            case Utime >= Stime andalso Utime =< Etime of
                true  ->
                    ReceiveTimes;
                false ->
                    0
            end;
        _ -> 0
    end.

%% @doc 查看活动信息
get_discount_mall_info(_Player, Type, SubType) ->
    #custom_act_discount_mall{
        free_count = FreeCount
    } = get_discount_mall_act_info(Type, SubType),
    [SubType, FreeCount].

%% @doc 购买记录
get_discount_mall_log(_Player, Type, SubType) ->
    #custom_act_discount_mall{
        log = Log
    } = get_discount_mall_act_info(Type, SubType),
    [
        {Time, Discount, AbDiscount, Money, GoodsList}||
        #discount_mall_log{
            time = Time,
            coupon_discount = Discount,
            coupon_ab_discount = AbDiscount,
            money = Money,
            goods_list = GoodsList
        } <- Log
    ].

%% @doc 抽奖
discount_mall_lottery(Player, Type, SubType) ->
    IsActOpen = lib_custom_act_api:is_open_act(Type, SubType),
    ActData = lib_custom_act_data:custom_act_data(Type, SubType),
    DiscountMall = get_discount_mall_act_data(ActData),
    if
        not IsActOpen -> {false, ?ERRCODE(err331_act_closed)};
        DiscountMall#custom_act_discount_mall.free_count =:= 0 ->
            discount_mall_lottery_do(Player, ActData, DiscountMall);
        true ->
            case lib_goods_api:cost_object_list_with_check(Player, [{?TYPE_GOODS, ?GOODS_ID_DISCOUNT_LOTTERY, 1}], discount_mall_lottery, "") of
                {true, _, _}  ->
                    discount_mall_lottery_do(Player, ActData, DiscountMall);
                {false, Error, _} ->
                    {false, Error}
            end
    end.
discount_mall_lottery_do(Player, ActData, DiscountMall) ->
    WeightList = calc_lottery_candidates(DiscountMall),
    case urand:rand_with_weight(WeightList) of
        Coupon when is_integer(Coupon) ->
            NewDiscountMall = DiscountMall#custom_act_discount_mall{count = DiscountMall#custom_act_discount_mall.count + 1, free_count = 1},
            lib_custom_act_data:save_custom_data(
                Player#player_status.id,
                ActData#custom_act_data{act_data = NewDiscountMall}
            ),
            NewPlayer = lib_goods_api:send_reward(Player, [{?TYPE_GOODS, Coupon, 1}], discount_mall_lottery),
            {true, NewPlayer, Coupon};
        _ ->
            {false, 0}
    end.

%% @doc 转盘内容
ask_lottery_candidates(Type, SubType) ->
    DiscountMall = get_discount_mall_act_info(Type, SubType),
    WeightList = calc_lottery_candidates(DiscountMall),
    GoodsList = [GoodsId || {_Weight, GoodsId} <- WeightList],
    L = length(GoodsList),
    case L < 8 of
        true  ->
            %% 如果不够8个，从所有列表中找出补齐
            AllCouponGoods = data_custom_act:get_all_coupon_goods(),
            StillNeed = 8 - L,
            lists:sublist(AllCouponGoods -- GoodsList, StillNeed) ++ GoodsList;
        false ->
            GoodsList
    end.

calc_lottery_candidates(DiscountMall) ->
    #custom_act_discount_mall{count = Count} = DiscountMall,
    CheckCount = Count + 1,
    Ids = data_custom_act:get_all_coupon_rate_id(),
    WeighList =
    lists:foldl(
        fun(Id, Temp) ->
            #discount_mall_coupon_rate_cfg{
                goods_id = GoodsId,            %% 优惠券id
                weight = Weight,               %% 权重
                min_count = MinCount,          %% 入库次数下限
                max_count = MaxCount           %% 入库次数上限
            }
                = data_custom_act:get_discount_mall_coupon_rate(Id),
            case CheckCount >= MinCount andalso CheckCount =< MaxCount andalso Weight > 0 of
                true  ->
                    [{Weight, GoodsId}|Temp];
                false ->
                    Temp
            end
        end, [], Ids
    ),
    lists:sublist(WeighList, 8).

%% @doc 购买商品
discount_mall_buy(Player, Type, SubType, BuyList, DiscountId, AbDiscountId) ->
    ActInfo = lib_custom_act_util:get_custom_act_open_info(Type, SubType),
    if
        ActInfo =:= false -> {false, ?ERRCODE(err331_act_closed)};
        true ->
            %% 计算原价和商品
            case format_goods(Player, ActInfo, BuyList, 0, []) of
                {false, Error} -> {false, Error};
                {true, TotalPrice, RewardList} ->
                    %% 计算满减
                    case calc_discount(Player, BuyList, TotalPrice, AbDiscountId, ?DISCOUNT_COUPON_AB_DIS) of
                        {false, Error} -> {false, Error};
                        {true, PriceThen, Cost1} ->
                            %% 计算折扣
                            case calc_discount(Player, BuyList, PriceThen, DiscountId, ?DISCOUNT_COUPON_DIS) of
                                {false, Error} -> {false, Error};
                                {true, PriceFinal, Cost2} ->
                                    FinalCost = [{?TYPE_GOLD, 0, PriceFinal}] ++ Cost1 ++ Cost2,
                                    case lib_goods_api:cost_object_list_with_check(Player, FinalCost, discount_mall_buy, "") of
                                        {false, Error, _} -> {false, Error};
                                        {true, Player1, _} ->
                                            %% 保存购买次数
                                            StatusCustomAct = Player#player_status.status_custom_act,
                                            Figure = Player#player_status.figure,
                                            RewardMap = StatusCustomAct#status_custom_act.reward_map,
                                            Player2 =
                                            lists:foldl(
                                                fun({GradeId, Num}, TempPlayer) ->
                                                    ReceiveTimes = count_receive_times(RewardMap, ActInfo, GradeId),
                                                    lib_custom_act:update_receive_times(TempPlayer, Type, SubType, GradeId, ReceiveTimes + Num)
                                                end, Player1, BuyList
                                            ),
                                            
                                            Player3 = lib_goods_api:send_reward(Player2, RewardList, discount_mall_buy),
                                            
                                            Now = utime:unixtime(),
                                            
                                            lib_log_api:log_custom_act_reward(Player#player_status.id, Type, SubType, 0, 0, RewardList, util:term_to_bitstring(BuyList), Figure#figure.vip, Figure#figure.lv,
                                                Player#player_status.gold, Player3#player_status.gold, Player#player_status.bgold, Player3#player_status.bgold, Now),
                                            
                                            %% 保存购买记录
                                            ActData = lib_custom_act_data:custom_act_data(Type, SubType),
                                            DiscountMall = get_discount_mall_act_data(ActData),
                                            OneLog = #discount_mall_log{
                                                time = Now,
                                                coupon_discount = DiscountId,
                                                coupon_ab_discount = AbDiscountId,
                                                money = PriceFinal,
                                                goods_list = [{GoodsId, GoodsNum} || {_, GoodsId, GoodsNum}<- RewardList]
                                            },
                                            NewDiscountMall = DiscountMall#custom_act_discount_mall{
                                                log = lists:sublist([OneLog|DiscountMall#custom_act_discount_mall.log], 10)
                                            },
                                            lib_custom_act_data:save_custom_data(
                                                Player#player_status.id,
                                                ActData#custom_act_data{act_data = NewDiscountMall}
                                            ),
                                            
                                            {true, Player3}
                                    end
                            end
                    end
            end
    end.

%%%-------------------------------------------------------------------
%%% Internal Function
%%%-------------------------------------------------------------------
%% 遍历购买的商品，返回购买价格和商品内容
format_goods(Player, #act_info{key = {ActType, SubType}} = ActInfo, [{GradeId, Num}|T], TotalPrice, GoodsList) ->
    case lib_custom_act_util:get_act_reward_cfg_info(ActType, SubType, GradeId) of
        #custom_act_reward_cfg{condition = Condition, reward = Reward} ->
            case check_buy_condition(Condition, Player, ActInfo, GradeId, Num) of
                {false, Error} -> {false, Error};
                {true, Price} ->
                    Goods = lib_goods_util:goods_object_multiply_by(Reward, Num),
                    format_goods(Player, ActInfo, T, TotalPrice + Price, Goods ++ GoodsList)
            end;
        _ ->
            {false, ?ERRCODE(err331_no_act_reward_cfg)}
    end;
format_goods(_Player, _ActInfo, [], TotalPrice, GoodsList) ->
    {true, TotalPrice, GoodsList}.

%% 计算满减折扣
calc_discount(_Player, _BuyList, Price, 0, _Type) -> {true, Price, []};
calc_discount(_Player, BuyList, Price, DiscountId, Type) ->
    Cost = [{?TYPE_GOODS, DiscountId, 1}],
    case data_custom_act:get_discount_mall_coupon(DiscountId) of
        #discount_mall_cfg{type = Type, condition = Condition, discount = Discount, ab_discount = AbDiscount} ->
            case check_discount_condition(Condition, BuyList, Price) of
                true  ->
                    FinalPrice =
                        case Type of
                            ?DISCOUNT_COUPON_DIS  -> umath:floor(Price * Discount);
                            ?DISCOUNT_COUPON_AB_DIS -> Price - AbDiscount
                        end,
                    {true, FinalPrice, Cost};
                {false, Error} ->
                    {false, Error}
            end;
        _ ->
            {false, ?ERRCODE(err331_discount_coupon_error)}
    end.

%% 获得活动数据
get_discount_mall_act_info(Type, SubType) ->
    case lib_custom_act_api:is_open_act(Type, SubType) of
        true ->
            get_act_data(Type, SubType);
        false ->
            #custom_act_discount_mall{}
    end.
get_act_data(Type, SubType) ->
    #custom_act_data{act_data = ActData} =
        lib_custom_act_data:custom_act_data(Type, SubType),
    case is_record(ActData, custom_act_discount_mall) of
        true ->
            ActData;
        false ->
            #custom_act_discount_mall{}
    end.
get_discount_mall_act_data(#custom_act_data{act_data = ActData}) ->
    case is_record(ActData, custom_act_discount_mall) of
        true ->
            ActData;
        false ->
            #custom_act_discount_mall{}
    end.

%% 检查购买条件，返回购买价格
check_buy_condition(Condition, Player, ActInfo, GradeId, Num) ->
    check_buy_condition(Condition, Player, ActInfo, GradeId, Num, -1).
check_buy_condition([], _Player, _ActInfo, _GradeId, _Num, Price)
    when Price >= 0 ->
    {true, Price};
check_buy_condition([], _Player, _ActInfo, _GradeId, _Num, _Price) ->
    {false, ?ERRCODE(err331_discount_price_error)};
check_buy_condition([{cost, Price}|T], Player, ActInfo, GradeId, Num, _) ->
    check_buy_condition(T, Player, ActInfo, GradeId, Num, Price * Num);
check_buy_condition([{limit, Limit}|T], Player, ActInfo, GradeId, Num, Price) ->
    StatusCustomAct = Player#player_status.status_custom_act,
    RewardMap = StatusCustomAct#status_custom_act.reward_map,
    ReceiveTimes = count_receive_times(RewardMap, ActInfo, GradeId),
    case ReceiveTimes + Num =< Limit of
        true  ->
            check_buy_condition(T, Player, ActInfo, GradeId, Num, Price);
        false ->
            {false, ?ERRCODE(err331_discount_times_limit)}
    end;
check_buy_condition([{role_lv, LvLimit}|T], Player, ActInfo, GradeId, Num, Price) ->
    case Player#player_status.figure#figure.lv >= LvLimit of
        true  ->
            check_buy_condition(T, Player, ActInfo, GradeId, Num, Price);
        false ->
            {false, ?ERRCODE(err331_discount_lv_limit)}
    end;
check_buy_condition([_|T], Player, ActInfo, GradeId, Num, Price) ->
    check_buy_condition(T, Player, ActInfo, GradeId, Num, Price).

%% 判断优惠券使用条件
check_discount_condition([], _, _) -> true;
check_discount_condition([{item, Num}|T], BuyList, Price) ->
    Total = lists:sum([N || {_, N} <- BuyList]),
    case Total >= Num of
        true  -> check_discount_condition(T, BuyList, Price);
        false -> {false, ?ERRCODE(err331_discount_condition)}
    end;
check_discount_condition([{gold, Gold}|T], BuyList, Price) ->
    case Price >= Gold of
        true  -> check_discount_condition(T, BuyList, Price);
        false -> {false, ?ERRCODE(err331_discount_ab_condition)}
    end;
check_discount_condition([_|T], BuyList, Price) ->
    check_discount_condition(T, BuyList, Price).