from decimal import Decimal, ROUND_HALF_UP

import pandas

from utils.pandas_extension import save_as_workbook

dataset = {}

# 机构绩效基础数据
sheets = pandas.ExcelFile("基础数据.xlsx")

for sheet_name in sheets.sheet_names:
    dataset[sheet_name] = pandas.read_excel(sheets, sheet_name=sheet_name, dtype=str)


# 根据年度达成率映射为年终奖
def mapped_as_regional_year_end_bonus(x: Decimal) -> str:

    # noinspection PyUnreachableCode
    match x:
        case x if x < 70:
            z = "0薪"
        case x if 70 <= x < 80:
            z = "4薪"
        case x if 80 <= x < 90:
            z = "5薪"
        case x if 90 <= x < 100:
            z = "6薪"
        case x if 100 <= x < 110:
            z = "7薪"
        case x if 110 <= x < 120:
            z = "8薪"
        case x if 120 <= x < 130:
            z = "9薪"
        case x if 130 <= x < 140:
            z = "10薪"
        case x if 140 <= x < 150:
            z = "11薪"
        case x if x >= 150:
            z = "12薪"
        case _:
            z = "年度达成率未匹配年终奖"

    return z


# 大区年终薪酬
# 就大区机构周报，筛选大区/机构名称包含大区的行、年度消费目标（万）/累计消费规模（万）/年度达成率，根据年度达成率匹配年终奖基准额度
regional_year_end_bonus = (
    dataset["大区机构达成率1"]
    .loc[
        dataset["大区机构达成率1"]["大区/机构名称"].str.contains("大区"),
        ["大区/机构名称", "年度消费目标（万）", "累计消费规模（万）", "年度达成率"],
    ]
    .assign(
        年度达成率=lambda dataframe: dataframe["年度达成率"].apply(
            lambda cell: (Decimal(cell) * 100).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            ),
        )
    )
    .assign(
        年终奖=lambda dataframe: dataframe["年度达成率"].apply(
            lambda cell: mapped_as_regional_year_end_bonus(cell)
        )
    )
    .sort_values(by="年度达成率", ascending=False)
    .reset_index(drop=True)
)


def mapped_as_institutional_year_end_bonus(x: pandas.Series) -> str | None:

    if x["年度达成率"] < 70:
        if (
            x["大区/机构名称"]
            in "安徽、河南、浙江、上海、云南、湖北、广东、广西、河北、江苏、江西、甘肃、黑吉、辽宁、山西、新疆、四川"
        ):
            z = "0薪"
        else:
            z = None
    elif 70 <= x["年度达成率"] < 80:
        if (
            x["大区/机构名称"]
            in "安徽、河南、浙江、上海、云南、湖北、广东、广西、河北、江苏、江西、甘肃"
        ):
            z = "0薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "2薪"
        else:
            z = None
    elif 80 <= x["年度达成率"] < 90:
        if x["大区/机构名称"] in "安徽、河南、浙江、上海、云南、湖北、广东、广西":
            z = "0薪"
        elif x["大区/机构名称"] in "河北、江苏、江西、甘肃":
            z = "2薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "3薪"
        else:
            z = None
    elif 90 <= x["年度达成率"] < 100:
        if x["大区/机构名称"] in "安徽、河南、浙江、上海、云南、湖北、广东、广西":
            z = "2薪"
        elif x["大区/机构名称"] in "河北、江苏、江西、甘肃":
            z = "3薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "4薪"
        else:
            z = None
    elif 100 <= x["年度达成率"] < 120:
        if x["大区/机构名称"] in "安徽、河南、浙江、上海、云南、湖北、广东、广西":
            z = "3薪"
        elif x["大区/机构名称"] in "河北、江苏、江西、甘肃":
            z = "4薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "5薪"
        else:
            z = None
    elif 120 <= x["年度达成率"] < 140:
        if x["大区/机构名称"] in "安徽、河南、浙江、上海、云南、湖北、广东、广西":
            z = "4薪"
        elif x["大区/机构名称"] in "河北、江苏、江西、甘肃":
            z = "5薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "6薪"
        else:
            z = None
    elif 140 <= x["年度达成率"] < 160:
        if x["大区/机构名称"] in "安徽、河南、浙江、上海、云南、湖北、广东、广西":
            z = "5薪"
        elif x["大区/机构名称"] in "河北、江苏、江西、甘肃":
            z = "6薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "7薪"
        else:
            z = None
    elif 160 <= x["年度达成率"] < 180:
        if x["大区/机构名称"] in "安徽、河南、浙江、上海、云南、湖北、广东、广西":
            z = "6薪"
        elif x["大区/机构名称"] in "河北、江苏、江西、甘肃":
            z = "7薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "8薪"
        else:
            z = None
    elif 180 <= x["年度达成率"] < 200:
        if (
            x["大区/机构名称"]
            in "安徽、河南、浙江、上海、云南、湖北、广东、广西、河北、江苏、江西、甘肃"
        ):
            z = "8薪"
        elif x["大区/机构名称"] in "黑吉、辽宁、山西、新疆、四川":
            z = "9薪"
        else:
            z = None
    else:
        if (
            x["大区/机构名称"]
            in "安徽、河南、浙江、上海、云南、湖北、广东、广西、河北、江苏、江西、甘肃、黑吉、辽宁、山西、新疆、四川"
        ):
            z = "10薪"
        else:
            z = None

    return z


# 机构年终薪酬
institutional_year_end_bonus = (
    dataset["大区机构达成率1"]
    .loc[
        ~dataset["大区机构达成率1"]["大区/机构名称"].str.contains("大区")
        & ~dataset["大区机构达成率1"]["大区/机构名称"].isin(["宁夏(只宁煤)"]),
        ["大区/机构名称", "年度消费目标（万）", "累计消费规模（万）", "年度达成率"],
    ]
    .assign(
        年度达成率=lambda dataframe: dataframe["年度达成率"].apply(
            lambda cell: (Decimal(cell) * 100).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            ),
        )
    )
    .assign(
        年终奖=lambda dataframe: dataframe[["大区/机构名称", "年度达成率"]].apply(
            lambda row: mapped_as_institutional_year_end_bonus(row), axis="columns"
        )
    )
    .dropna(subset=["年终奖"])
    .sort_values(by="年度达成率", ascending=False)
    .reset_index(drop=True)
)


# 根据机构所在省份匹配为机构名称
def mapped_as_institution_name(x):

    # noinspection PyUnreachableCode
    match x:
        case "北京市" | "天津市":
            z = "京津"
        case "河北省":
            z = "河北"
        case "山西省":
            z = "山西"
        case "内蒙古自治区":
            z = "内蒙"
        case "辽宁省":
            z = "辽宁"
        case "吉林省" | "黑龙江省":
            z = "黑吉"
        case "上海市":
            z = "上海"
        case "江苏省":
            z = "江苏"
        case "浙江省":
            z = "浙江"
        case "安徽省":
            z = "安徽"
        case "福建省":
            z = "福建"
        case "江西省":
            z = "江西"
        case "山东省":
            z = "山东"
        case "河南省":
            z = "河南"
        case "湖北省":
            z = "湖北"
        case "湖南省":
            z = "湖南"
        case "广东省" | "海南省":
            z = "广东"
        case "广西壮族自治区":
            z = "广西"
        case "重庆市" | "四川省" | "西藏自治区":
            z = "四川"
        case "贵州省":
            z = "贵州"
        case "云南省":
            z = "云南"
        case "新疆维吾尔自治区":
            z = "新疆"
        case "陕西省" | "青海省":
            z = "陕西"
        case "甘肃省":
            z = "甘肃"
        case "宁夏回族自治区":
            z = "宁夏"
        case "总部":
            z = "总部"
        case _:
            z = ""

    return z


# 根据发卡金额映射为奖励
def mapped_as_card_issuance_reward(x: Decimal) -> int:

    # noinspection PyUnreachableCode
    match x:
        case x if 50 <= x < 100:
            z = 500
        case x if 100 <= x < 300:
            z = 800
        case x if 300 <= x < 500:
            z = 1000
        case x if 500 <= x < 1000:
            z = 2000
        case x if 1000 <= x < 3000:
            z = 4000
        case x if 3000 <= x < 5000:
            z = 10000
        case x if 5000 <= x < 10000:
            z = 20000
        case x if x >= 10000:
            z = 30000
        case _:
            z = 0

    return z


# 自主经营发卡奖励
card_issuance_reward = (
    dataset["25年发卡"]
    .loc[~dataset["25年发卡"]["投保公司"].isin(dataset["24年发卡"]["投保公司"])]
    .merge(
        dataset["保单机构分配"],
        how="left",
        on="保单编号",
        suffixes=("", "_duplication"),
    )  # 若有发卡无消费则无保单机构分配方案
    .fillna("0")
    .assign(
        发卡金额=lambda dataframe: dataframe["发卡金额"].apply(
            lambda cell: (Decimal(cell) / 10000).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            )
        )  # 发卡金额单位为万元
    )
    .assign(
        奖励金额=lambda dataframe: dataframe["发卡金额"].apply(
            lambda cell: mapped_as_card_issuance_reward(cell)
        )
    )  # 先计算奖励金额在根据机构分配比例拆分
    .assign(总部="总部")
    .assign(
        # 整合机构
        机构名称=lambda dataframe: dataframe.apply(
            lambda x: [x["落地机构"], x["出单机构"], x["总部"]], axis="columns"
        ),
        # 整合分配比例
        分配比例=lambda dataframe: dataframe.apply(
            lambda x: [
                x["落地机构分配比例"],
                x["出单机构分配比例"],
                x["总部分配比例"],
            ],
            axis="columns",
        ),
    )
    .explode(["机构名称", "分配比例"])
    .assign(
        分配后奖励金额=lambda dataframe: dataframe.apply(
            lambda row: (
                Decimal(row["奖励金额"]) * Decimal(row["分配比例"]) / 100
            ).quantize(Decimal("0.00"), rounding=ROUND_HALF_UP),
            axis="columns",
        ),
    )
    .assign(
        机构=lambda dataframe: dataframe["机构名称"].apply(
            lambda cell: mapped_as_institution_name(cell)
        )
    )
    .loc[lambda dataframe: dataframe["机构"] != "总部"]  # 过滤总部
    .sort_values(by="分配后奖励金额", ascending=False)
    .reset_index(drop=True)
)[["保单编号", "投保公司", "保险总公司", "保险分公司", "发卡金额", "奖励金额", "机构", "分配比例", "分配后奖励金额"]]


# 根据转化率提升映射为奖励比例
def mapped_as_increase_reward_ratio(x: Decimal) -> Decimal:

    # noinspection PyUnreachableCode
    match x:
        case x if 5 <= x < 10:
            z = Decimal("0.1")
        case x if 10 <= x < 15:
            z = Decimal("0.2")
        case x if 15 <= x < 20:
            z = Decimal("0.3")
        case x if 20 <= x < 30:
            z = Decimal("0.4")
        case x if x >= 30:
            z = Decimal("0.5")
        case _:
            z = Decimal("0")

    return z


# 重点存量业务消费提升奖励
increase_reward = (
    dataset["投保公司"]
    .loc[dataset["投保公司"]["项目名称"].isin(dataset["重点项目"]["项目名称"])]
    .merge(
        dataset["24年数据"], how="left", on="投保公司", suffixes=("", "_duplication")
    )
    .merge(
        dataset["25年数据"], how="left", on="投保公司", suffixes=("", "_duplication")
    )
    .fillna("0")
    .assign(
        转化率25年=lambda dataframe: dataframe["25年转化率"].apply(
            lambda row: (Decimal(row) * 100).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            )
        ),
        转化率24年=lambda dataframe: dataframe["24年转化率"].apply(
            lambda row: (Decimal(row) * 100).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            )
        ),
    )
    .assign(
        转化率提升=lambda dataframe: dataframe.apply(
            lambda row: (row["转化率25年"] - row["转化率24年"]).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            ),
            axis="columns",
        )
    )
    .assign(
        奖励比例=lambda dataframe: dataframe["转化率提升"].apply(
            lambda cell: mapped_as_increase_reward_ratio(cell)
        )
    )
    .assign(
        消费金额提升=lambda dataframe: dataframe.apply(
            lambda row: (
                Decimal(row["25年消费金额"]) - Decimal(row["24年消费金额"])
            ).quantize(Decimal("0.00"), rounding=ROUND_HALF_UP),
            axis="columns",
        )
    )
    .assign(
        奖励金额=lambda dataframe: dataframe.apply(
            lambda row: (row["消费金额提升"] * row["奖励比例"] / 100).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            ),
            axis="columns",
        )
    )
    .sort_values(by="奖励金额", ascending=False)
    .reset_index(drop=True)
)[
    [
        "项目名称",
        "投保公司",
        "25年发卡金额",
        "25年消费金额",
        "转化率25年",
        "24年发卡金额",
        "24年消费金额",
        "转化率24年",
        "转化率提升",
        "奖励比例",
        "消费金额提升",
        "奖励金额",
    ]
]


# 根据转化率映射为奖励比例
def mapped_as_new_reward_ratio(x: Decimal) -> Decimal:

    # noinspection PyUnreachableCode
    match x:
        case x if 30 <= x < 40:
            z = Decimal("0.3")
        case x if 40 <= x < 50:
            z = Decimal("0.4")
        case x if 50 <= x < 60:
            z = Decimal("0.5")
        case x if 60 <= x < 70:
            z = Decimal("0.6")
        case x if 70 <= x < 80:
            z = Decimal("0.7")
        case x if 80 <= x < 90:
            z = Decimal("0.8")
        case x if x >= 90:
            z = Decimal("1.0")
        case _:
            z = Decimal("0")

    return z


# 新增业务消费奖励
new_reward = (
    dataset["保单机构分配"]
    .loc[
        (dataset["保单机构分配"]["自力更生"] == "是")
        & ~dataset["保单机构分配"]["投保公司"].isin(dataset["24年发卡"]["投保公司"])
    ]
    .merge(
        dataset["25年发卡"],
        how="left",
        on="保单编号",
        suffixes=("", "_duplication"),
    )
    .merge(
        dataset["25年消费"], how="left", on="保单编号", suffixes=("", "_duplication")
    )
    .fillna("0")
    .assign(
        发卡金额=lambda dataframe: dataframe["发卡金额"].apply(
            lambda cell: (Decimal(cell) / 10000).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            )
        ),  # 发卡金额单位为万元
        消费金额=lambda dataframe: dataframe["消费金额"].apply(
            lambda cell: (Decimal(cell) / 10000).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            )
        ),  # 消费金额单位为万元
    )
    .assign(
        转化率=lambda dataframe: dataframe.apply(
            lambda row: (
                (row["消费金额"] / row["发卡金额"] * 100).quantize(
                    Decimal("0.00"), rounding=ROUND_HALF_UP
                )
                if row["发卡金额"] != 0
                else Decimal("0.00")
            ),
            axis="columns",
        )
    )
    .assign(
        奖励比例=lambda dataframe: dataframe["转化率"].apply(
            lambda cell: mapped_as_new_reward_ratio(cell)
        )
    )
    .assign(
        奖励金额=lambda dataframe: dataframe.apply(
            lambda row: (row["消费金额"] * row["奖励比例"] / 100 * 10000).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            ),
            axis="columns",
        )
    )  # 先计算奖励金额在根据机构分配比例拆分
    .assign(总部="总部")
    .assign(
        # 整合机构
        机构名称=lambda dataframe: dataframe.apply(
            lambda x: [x["落地机构"], x["出单机构"], x["总部"]], axis="columns"
        ),
        # 整合分配比例
        分配比例=lambda dataframe: dataframe.apply(
            lambda x: [
                x["落地机构分配比例"],
                x["出单机构分配比例"],
                x["总部分配比例"],
            ],
            axis="columns",
        ),
    )
    .explode(["机构名称", "分配比例"])
    .assign(
        分配后奖励金额=lambda dataframe: dataframe.apply(
            lambda row: (row["奖励金额"] * Decimal(row["分配比例"]) / 100).quantize(
                Decimal("0.00"), rounding=ROUND_HALF_UP
            ),
            axis="columns",
        ),
    )
    .assign(
        机构=lambda dataframe: dataframe["机构名称"].apply(
            lambda cell: mapped_as_institution_name(cell)
        )
    )
    .loc[
        lambda dataframe: (dataframe["机构"] != "总部") & (dataframe["分配比例"] != "0")
    ]  # 过滤总部
    .sort_values(by="分配后奖励金额", ascending=False)
    .reset_index(drop=True)
)[
    [
        "保单编号",
        "投保公司",
        "保险总公司",
        "保险分公司",
        "发卡金额",
        "消费金额",
        "转化率",
        "奖励比例",
        "奖励金额",
        "机构",
        "分配比例",
        "分配后奖励金额",
    ]
]

save_as_workbook(
    workbook_name="机构绩效试算.xlsx",
    worksheets=[
        ("大区年终薪酬", regional_year_end_bonus),
        ("机构年终薪酬", institutional_year_end_bonus),
        ("自主经营发卡奖励", card_issuance_reward),
        ("重点存量业务消费提升奖励", increase_reward),
        ("新增业务消费奖励", new_reward),
    ],
)
