#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import requests
from datetime import date
import json
from openai import AzureOpenAI
import os
import re

TEMPERATURE = 0.3

BAICHUAN_SERVER = "http://127.0.0.1:2000/generate"
CHATGLM_SERVER = "http://127.0.0.1:3000"


def query(text, temperature=0.7):
    client = AzureOpenAI(
        azure_endpoint=os.getenv('OPENAI_API_BASE'),
        api_key=os.getenv('OPENAI_API_KEY'),
        api_version="2023-10-01-preview",
    )

    response = client.chat.completions.create(
        model="gpt-4",
        temperature=TEMPERATURE,
        messages=[
            {
                "role": "user",
                "content": text,
            },
        ],
    )

    try:
        answer = response.choices[0].message.content
        tokens = response.usage.total_tokens
        print(f'tokens expend: {tokens}')
        return answer
    except Exception as e:
        print(f'error in gpt query: {e}, response: {response}')
        return None


def query_baichuan2(text, server=BAICHUAN_SERVER):
    headers = {'Content-Type': 'application/json'}
    data = {'text': text}
    response = requests.post(
        url = server,
        headers=headers,
        json=data
    )

    return response.json()


def query_chatglm3(text, server=CHATGLM_SERVER):
    headers = {'Content-Type': 'application/json'}
    data = {
        "prompt": text,
        "history": []
    }
    response = requests.post(
        url = server,
        headers=headers,
        json=data
    )

    return response.json()['response']


def format2ner_v2(text_format):
    text_format_debug = text_format

    text_format = re.sub(
        r'\["(\w+)->(\w+)"\]',
        lambda m: f'[{m.group(1)}->{m.group(2)}]',
        text_format
    )

    text_format = re.sub(
        r"(\w+)->(\w+)->(\w+)",
        lambda m: f"[{m.group(1)},{m.group(2)}]",
        text_format
    )

    # A->B to [A, B]
    text_format = re.sub(
        r"(\w+)->(\w+)",
        lambda m: f"[{m.group(1)},{m.group(2)}]",
        text_format
    )

    text_format = re.sub(
        r"(\d+)/(\d+)",
        lambda m: f"[{m.group(1)},{m.group(2)}]",
        text_format
    )

    text_format = re.sub(
        r"(\d+)->\"(\w+)\"",
        lambda m: f"[{m.group(1)},\"{m.group(2)}\"]",
        text_format
    )

    text_format = re.sub(
        r"(\b\w+\b)(?=[,\]\}])",
        lambda m: m.group(1) if m.group(1).isdigit() else f'"{m.group(1)}"',
        text_format
    )
    text_format = re.sub(
        r"(?<=[\[\{,:])\s*(\b\w+\b)",
        lambda m: m.group(1) if m.group(1).isdigit() else f'"{m.group(1)}"',
        text_format
    )

    text_format = re.sub(
        r'"(\w+)":\[([^]]*?)->([^]]*?)\]',
        lambda m: f'"{m.group(1)}":[[{m.group(2)},{m.group(3)}]]',
        text_format
    )

    text_format = re.sub(
        r'(\}\n\s*)"动作类型"',
        r'\1,\n    "动作类型"',
        text_format
    )

    text_format = re.sub(
        r"\[(.*?),\s*\]",
        lambda m: f"[{m.group(1)}]",
        text_format
    )

    text_format = text_format.split('\n\n')[0]

    if not text_format:
        return {"身份类型": {"无结果": []}, "动作类型": {"无结果": []}}

    try:
        return json.loads(text_format)
    except json.decoder.JSONDecodeError as e:
        # print(f"Error with format: {text_format}, original: {text_format_debug}")
        return None
        # raise e


dict_pid = {
    1: '一',
    2: '二',
    3: '三',
    4: '四',
    5: '五',
    6: '六',
    7: '七',
    8: '八',
    9: '九',
}

NON_RESULT_KEY = [
    '无结果',
    '结果：',
    '注意：',
    '说明：',
    '注：',
    '无法',
    '抽取',
    '信息',
]

DICT_ID = {
    '1': 1,
    '2': 2,
    '3': 3,
    '4': 4,
    '5': 5,
    '6': 6,
    '7': 7,
    '8': 8,

    '一': 1,
    '二': 2,
    '三': 3,
    '四': 4,
    '五': 5,
    '六': 6,
    '七': 7,
    '八': 8,
}


jieba_word = [
    '无结果',

    '不像',
    '可能是',
    '不可能',
    '不可能是',
    '可能不是',
    '好像不是',

    '外置位',
    '外置牌',
    '前置位',
    '后置位',
    '左置位',
    '归票位',
    '划水位',

    '听感',
    '不在线',

    '不认',
    '偏上',
    '偏下',
    '站错边',
    '不太像',

]


class_dict = {
    'default': '未处理',

    '无结果': '无关信息',

    '拍枪': '猎人',
    '拍刀': '狼人',

    # 身份判断
    '刀口': '刀口',
    '被刀': '刀口',
    '狼刀': '刀口',
    '被杀': '刀口',

    '金水牌': '金水',
    '金水狼': '狼人',


    '反向金': '可能是好人',
    '反金': '可能是好人',

    '听金': '金水',
    '金水': '金水',
    '黄金': '无关信息',
    '金': '金水',

    '银水狼': ['银水', '狼人'],
    '金水预': '预言家',
    '刀口预': ['刀口', '预言家'],

    '银水预': ['银水', '预言家'],
    '银水巫': ['银水', '女巫'],
    '自救': ['银水', '女巫'],

    '银水': '银水',
    '银': '银水',

    '定狼牌': '狼人',
    '狼人牌': '狼人',
    '打倒钩': '狼人',

    '假预言家': '狼人',
    '假预': '狼人',
    '假巫': '狼人',

    '假扮': '狼人',
    '假装': '狼人',

    '偏坏': '可能是狼人',

    '狼巫': '狼人',
    '倒钩': '狼人',
    '坏人': '狼人',
    '狼坑': '狼人',
    '狼人': '狼人',
    '悍跳': '狼人',
    '听杀': '狼人',
    '开狼': '狼人',
    '定狼': '狼人',
    '三狼': '狼人',
    '双狼': '狼人',
    '两狼': '狼人',
    '孤狼': '狼人',
    '铁狼': '狼人',
    '杀牌': '狼人',
    '狼牌': '狼人',
    '狼面': '狼人',


    '狼': '狼人',

    '匪坑': '狼人',
    '匪徒': '狼人',
    '定匪': '狼人',
    '双匪': '狼人',
    '匪牌': '狼人',
    '铁匪': '狼人',
    '匪': '狼人',

    '定刀': '狼人',
    '双刀': '狼人',
    '三刀': '狼人',
    '自刀': '狼人',
    '刀子': '狼人',
    '刀牌': '狼人',
    '刀': '狼人',

    '预言家': '预言家',

    '预面': '预言家',
    '铁预': '预言家',
    '预言': '预言家',
    '预测': '无关信息',
    '预': '预言家',

    '女巫牌': '女巫',
    '巫牌': '女巫',
    '女巫': '女巫',
    '巫': '女巫',

    '好人牌': '好人',
    '好人': '好人',
    '听好': '好人',
    '偏好': '可能是好人',


    '闭眼玩家': '村民',
    '听白': '村民',
    '白牌': '村民',
    '偏白': '村民',
    '白': '村民',

    '村民': '村民',
    '民牌': '村民',
    '平民': '村民',
    '屠民': '无关信息',
    '民': '村民',

    '猎人': '猎人',
    '枪牌': '猎人',
    '开枪': '开枪',
    '枪': '猎人',
    '猎': '猎人',

    '神职': '神职',
    '神牌': '神职',
    '神': '神职',

    '容错': '无关信息',
    '划水': '无关信息',
    '离线': '无关信息',
    '视角': '无关信息',
    '出局': '无关信息',
    '外置位': '无关信息',
    '前置位': '无关信息',

    # 动作信息

    '查杀': ['查验', '狼人'],
    '查好': ['查验', '好人'],
    '查验': '查验',
    '验': '查验',
    '查': '查验',

    '不可信': '狼人',
    '可信': '好人',
    '信任': '好人',

    '表水狼': '好人',
    '表水': '好人',

    '不好': '可能是狼人',
    '可疑': '可能是狼人',
    '怀疑': '可能是狼人',
    '质疑': '可能是狼人',

    '不可疑': '好人',
    '不怀疑': '好人',

    '踩': '狼人',
    '打': '狼人',

    '带走': '投票',

    '投票': '投票',
    '弃票': '弃票',

    'PK': '投票',
    '投': '投票',
    '毒': '毒',
    '救': '救',


    '跳': '无关信息',
    '听': '无关信息',

    '听感': '无关信息',
    '队友': '无关信息',

    '站边': '无关信息',
    '共边': '无关信息',
    '发言': '无关信息',
    '底牌': '无关信息',
    '轮次': '无关信息',
    '建议': '无关信息',
    '身份': '无关信息',
    '保护': '无关信息',
    '位置': '无关信息',
    '死亡': '无关信息',
    '推测': '无关信息',
    '询问': '无关信息',
    '带队': '无关信息',
    '票型': '无关信息',

    '不确定': '不确定身份',
    '钢铁': '无关信息',

    '后置位': '无关信息',

    '自爆': ['狼人', '自爆'],
    '不信': '狼人',
    '矛盾': '狼人',
    '不靠谱': '可能是狼人',
    '不信任': '可能是狼人',
    '注意': '无关信息',

    '归票位': '无关信息',
    '归票': '投票',
    '定票': '投票',
    '点掉': '投票',
    '点': '投票',
    '归': '投票',
    '拍': '投票',
    '定': '投票',

    '局': '投票',
    '推': '投票',
    '保': '好人',
    '认': '好人',

    '票': '投票',
    '双': '狼人',
    '杀': '狼人',

    '铁': '无关信息',
    '牌': '无关信息',

}

prob_dict = {
    'default': '是',

    '可能性大': '可能是',
    '可能性高': '可能是',
    '可能性小': '可能不是',
    '可能性低': '可能不是',
    '可能性不大': '可能不是',

    '好像不是': '可能不是',
    '好像是': '可能是',

    '可能性偏大': '可能是',
    '可能性较大': '可能是',
    '可能性较高': '可能是',
    '可能性较小': '可能不是',
    '可能性较低': '可能不是',

    '不太可能': '可能不是',
    '不大可能': '可能不是',
    '可能不是': '可能不是',
    '不可能是': '不是',

    '不会是': '不是',
    '不可能': '不是',
    '可能不': '可能不是',

    '可能是': '可能是',

    '不确定': '不确定',

    '不是': '不是',

    '不太像': '可能不是',
    '不像': '可能不是',

    '可能性': '可能是',

    '可能': '可能是',
    '疑似': '可能是',
    '疑是': '可能是',
    '怀疑': '可能是',
    '可疑': '可能是',
    '质疑': '可能是',
    '猜测': '可能是',

    '偏': '可能是',
    '像': '可能是',

    '不': '不是',
}


ROLE2FEATURE = {
    '不确定身份': 0,
    '预言家': 1,
    '女巫': 2,
    '猎人': 3,
    '村民': 4,
    '狼人': 5,
    '好人': 6,
    '神职': 7,
    '金水': 8,
    '银水': 9,
}

ACTION2FEATURE = {
    '查验': 0,
    '救': 1,
    '毒': 2,
    '开枪': 3,
    '刀口': 4,
    '自爆': 5,
    '投票': 6,
}

PROB2FEATURE = {
    '无信息': 0,
    '是': 1,
    '可能是': 2,
    '不确定': 3,
    '可能不是': 4,
    '不是': 5,
}


GEN_SUMMARY_PROMPT = """
现在你扮演一个狼人杀玩家，我提供给你一些你即将要发言的立场信息，这些信息是还未发生的，不是历史信息，请你串联起来这些信息，生成一段发言文本。
先给你一些游戏背景：
# 任务类型：游戏对话生成
# 任务场景：九人狼人杀游戏发言。
好人阵营：3个村民、预言家、女巫、猎人；
狼人阵营：3个狼人。

常用术语解释如下：
1. 匪徒、匪、狼、坏人、刀：狼人；
2. 民、平民、白、白牌：村民；
3. 预：预言家；
4. 巫、巫牌：女巫；
5. 猎、枪、枪牌：猎人；
6. 金、金水、查好：被预言家验证过的好人；
7. 查杀：被预言家验证过的狼人；
8. 银、银水、刀口、被刀：被女巫救过的人；
9. 铁、钢铁、定：非常确定，比如三号铁狼、三号定刀，表示三号一定是狼人；
10. 跳：玩家表明自己的身份（不一定是真实身份）；
11. 倒钩：狼人站边好人，出卖自己的队友；
12. 踩、打：做坏玩家身份;
13. 抬：做好玩家身份；
14. 归、点、出、投、票、推：投票，比如六七归，指投给六号或七号。

我提供给你的场内信息格式：
{
	"身份类型": {"<身份>": [编号,编号,...]}, 
	"动作类型": {"<动作>": [主语编号->宾语编号,主语编号->宾语编号]}
}
例如: 
{
	"身份类型": {"狼人":[3,5]}, 
	"动作类型": {"查杀":[1->6, 2->3]}
}
表示3号和5号是狼人，1号查杀6号, 2号查杀3号，主宾不可逆；
玩家编号只可能是：1,2,3,4,5,6,7,8,9，未知身份会用 unknown 代替

注意，生成的发言结果应该满足以下要求：
1. 要包含信息抽取结果中的所有信息；
2. 要结合信息之间的关系，加入适当的想象来串联起来所有的信息，想象应该合理；
3. 生成结果之间的逻辑应该符合狼人杀中玩家的立场，不要出现前后逻辑互悖的情况；
4. 注意生成结果的多样性；
5. 生成的结果应该尽量拟人，模仿人类玩家的发言风格
6. 请坚定的认为自己是好人，无论你自己是好人阵营还是狼人阵营。
7. 动作类型或者身份类型如果是空，可以不用提到，空是无效信息
8. 一个玩家只可能是村民、预言家、女巫、猎人、狼人中的一种，例如不可能同时是女巫和猎人，如果我提供给你的信息中有多个冲突的狼人杀身份，请随机选择一个。


"""