# -*- coding:utf-8 -*-
import json
import requests
import logging
from base_framework.public_tools.utils import Tools
obj_tool = Tools()


class FeiShuMultidimensionalTableOperations:
    def __init__(self, app_token, table_id, view_id):
        """
        初始化飞书多维表格操作类
        Args:
            app_token: 多维表格token，登录飞书多维表格，按F12，右侧接口列表中找带token的接口，复制token
            table_id: 多维表格id，登录飞书多维表格，在浏览器地址栏中找到table=后面的值
            view_id: 多维表格视图id，登录飞书多维表格，在浏览器地址栏中找到view=后面的值
        Note：
            如果返回显示禁止访问的话，说明你的飞书表格没有给应用开通权限，需要在更多-添加应用中添加此应用，并开通权限
            这里我们使用的应用名是：QualityAssurance-Customer-CD-QA
            如果你搜多不到这个应用，说明你没有此应用的使用权限，找陈江或刚哥开通权限
        """
        self.app_token = app_token  # 表格token
        self.table_id = table_id  # 表格id
        self.view_id = view_id  # 表格视图id
        self.app_id = 'cli_a53b456397bdd00c'  # 飞书应用的app_id,使用前，多维表格需要在更多-添加应用中添加此应用，并开通权限
        self.app_secret = 's3U4tXp9lTz7imMDQsHDNcoO4AgzXWk7'  # 飞书应用的app_secret
        self.fs_login_url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
        self.http_session = requests.session()
        self.tenant_access_token = (  # 以应用身份请求api的鉴权凭证，每次获取后有效期为2小时
            self.__get_tenant_access_token_by_feishu().get("tenant_access_token"))
        self.http_session.headers.update({"Content-Type": "application/json; charset=utf-8",
                                          "Authorization": f"Bearer {self.tenant_access_token}",
                                          "User-Agent": "lark-api-explorer/v1"})

    def __get_tenant_access_token_by_feishu(self):
        """功能：获取飞书应用的tenant_access_token：以应用身份请求api的鉴权凭证，每次获取后有效期为2小时"""
        headers = {'Content-Type': 'application/json; charset=utf-8'}
        data = {'app_id': self.app_id, 'app_secret': self.app_secret}
        r = requests.post(self.fs_login_url, data=json.dumps(data), headers=headers, verify=False)
        r_json = r.json()
        if r_json.get('code') == 0:
            return {"expire": r_json.get('expire'), "tenant_access_token": r_json.get('tenant_access_token')}
        else:
            raise Exception(f"获取原始tenant_access_token失败{r_json}")

    def fsmt_search_from_m_table(self, filter_dict=None, sort=None, automatic_fields=False, field_names=None):
        """
        功能：从多维表格中查询数据，详细说明见：https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/bitable-v1/app-table-record/search
        Args:
            filter_dict: 过滤条件，类型：list，格式：[{"conjunction": "string", "conditions": "list"]
                conjunction: 过滤条件之间的关系，取值范围：and、or，当仅有一个条件时，也需要填写此字段
                conditions: 过滤条件，格式：[{"field_name": "string", "operator": "string", "value": "list"}]
                    field_name: 筛选条件的左值，值为字段的名称，类型：string
                    operator: 筛选条件的运算符，
                        取值范围：is：等于
                                isNot：不等于
                                contains：包含
                                doesNotContain：不包含
                                isEmpty：为空
                                isNotEmpty：不为空
                                isGreater：大于
                                isGreaterEqual：大于等于
                                isLess：小于
                                isLessEqual：小于等于
                                like：LIKE 运算符。暂未支持
                                in：IN 运算符。暂未支持
                    value: 筛选条件的右值，值为字段的值，类型：list
                        若查询条件是时间格式，且为具体时间或日期时，格式为：["ExactDate", "13位的时间戳"]
                        同时也支持时间段查询，格式为：["具体的时间段描述字符"]，如：
                            ["Today"]：今天
                            ["Tomorrow"]: 明天
                            ["Yesterday"]：昨天
                            ["CurrentWeek"]：本周
                            ["LastWeek"]：上周
                            ["CurrentMonth"]：本月
                            ["LastMonth"]：上月
                            ["TheLastWeek"]：过去七天内
                            ["TheNextWeek"]：未来七天内
                            ["TheLastMonth"]：过去三十天内
                            ["TheNextMonth"]：未来三十天内
            sort: 排序条件，类型：list，格式：[{"field_name": "string", "desc": "bool"}]
                field_name: 排序字段的名称，类型：string
                desc: 是否倒序排序，类型：bool, 默认值：False
            automatic_fields: 控制是否返回自动计算的字段, true 表示返回
            field_names: 指定本次查询返回记录中包含哪些字段
        Returns: {"code": 0, "msg": "",
                  "data": {"items": "入参中自定义的返回字段"，
                           "has_more": "bool,是否还有更多项",
                           "page_token": "boolean, 分页标记，当 has_more 为 true 时，会同时返回新的 page_token，否则不返回 page_token",
                           "total": "int, 总数"}}
        """
        url = ("https://open.feishu.cn/open-apis/bitable/v1/apps/{}/tables/{}/records/search"
               .format(self.app_token, self.table_id))
        request_data = {"view_id": self.view_id,
                        "filter": filter_dict,
                        "automatic_fields": automatic_fields,
                        "sort": sort,
                        "field_names": field_names}
        try:
            rs = self.http_session.post(url, data=json.dumps(request_data), verify=False)
        except Exception as e:
            raise Exception(f"调用飞书接口{url}失败:{e}")
        rj_json = rs.json()
        if rj_json.get('code') == 0:
            return rj_json
        else:
            raise Exception(f"调用飞书接口{url}失败:\n{rs.status_code}, {rs.text}")

    def fsmt_insert_data_to_m_table(self, m_table_column_dict):
        """
        https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/batch_create
        api文档地址：https://open.feishu.cn/document/server-docs/docs/bitable-v1/app-table-record/batch_create
        """
        url = ("https://open.feishu.cn/open-apis/bitable/v1/apps/{}/tables/{}/records/batch_create"
               .format(self.app_token, self.table_id))
        request_data = {"records": []}
        for column_dict in m_table_column_dict:
            request_data["records"].append({"fields": column_dict})
        try:
            rs = self.http_session.post(url, data=json.dumps(request_data), verify=False)
        except Exception as e:
            raise Exception(f"调用飞书接口{url}失败:{e}")
        rj_json = rs.json()
        if rj_json.get('code') == 0:
            return rj_json
        else:
            raise Exception(f"调用飞书接口{url}失败:\n{rs.status_code}, {rs.text}")

    def fsmt_update_one_data_to_m_table(self, record_id, m_table_column_dict):
        """
        https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/:record_id/update
        api文档：https://open.feishu.cn/document/server-docs/docs/bitable-v1/app-table-record/update
        """
        url = f"""https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{self.table_id}/records/{record_id}"""
        data = {"fields": m_table_column_dict}
        logging.info(f"更新数据请求参数为：{data}")
        rs = self.http_session.put(url, data=json.dumps(data), verify=False)
        rj_json = rs.json()
        if rj_json.get('code') == 0:
            return rj_json
        else:
            logging.info(f"更新异常，异常返回结果为：{rs}")


    def batch_update_data(self, table_id, update_records_data_list):
        """
        https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/batch_update
        api文档：https://open.feishu.cn/document/server-docs/docs/bitable-v1/app-table-record/batch_update
        """
        url = f"""https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/batch_update"""
        data = {"records": update_records_data_list}
        logging.info(f"批量更新数据请求参数为：{data}")
        rs = self.http_session.post(url, data=json.dumps(data), verify=False)
        rj_json = rs.json()
        if rj_json.get('code') == 0:
            return rj_json
        else:
            logging.info(f"批量更新异常，异常返回结果为：{rs}")
            raise Exception(f"调用飞书接口{url}失败:{rs}")

    def delete_data(self):
        pass


if __name__ == '__main__':

    fs = FeiShuMultidimensionalTableOperations(app_token="HssibyRf4anbpxsA3G2c1IPwnic",
                                               table_id="tblVbNoZE1RI3Hdo",
                                               view_id="vewx9lK9hI")
    filter_dict = {"conjunction": "and",
                   "conditions": [{"field_name": "时间", "operator": "is", "value": ["Today"]}]}
    sort = [{"field_name": "时间", "desc": True}]
    field_names = ["时间", "入班", "换班", "补课", "月份"]

    rsp = fs.fsmt_search_from_m_table(filter_dict=filter_dict, sort=sort, field_names=field_names)

    if rsp.get("code") == 0:
        if int(rsp.get("data").get("total")) == 0:
            ci_data = [['2024-07-24', 7022, 2040, 105]]
            request_data = []
            for item in ci_data:
                ci_date = obj_tool.get_format_date(r_time="{} 00:00:00".format(item[0]), r_type=13)
                request_data.append({"时间": ci_date, "入班": item[1], "换班": item[2], "补课": item[3],
                                     "月份": "{}月".format(int(item[0].split("-")[1]))})
            for item in request_data:
                print(item)
            # request_data = [{"时间": 1721664000000, "入班": 123, "换班": 124, "补课": 125, "月份": "7月"},
            #                 {"时间": 1721750400000, "入班": 223, "换班": 224, "补课": 225, "月份": "7月"}]
            rsp = fs.fsmt_insert_data_to_m_table(m_table_column_dict=request_data)
            print(rsp)
        else:
            print("数据已存在,本次不写入...")
    else:
        print("查询失败:{}".format(rsp))
