import os
import json
import pymongo
import logging
from datetime import datetime
from .parameter import Parameter
from .tools import handle_date

logging.basicConfig(
    level=logging.WARNING,
    format='[%(asctime)s] [%(levelname)s] %(message)s'
)


class DBConnect():
    def __init__(self, db: str, collection: str, home_kye='MONGODB_HOST', port_kye='MONGODB_PORT'):
        self.mongo_home = os.environ.get(home_kye, None)
        self.mongo_port = os.environ.get(port_kye, 27017)

        if not self.mongo_home or not self.mongo_port:
            logging.error('MongoDB(组件)的组件连接信息是不完整的')

        self.mongo_client = pymongo.MongoClient(
            host=self.mongo_home,
            port=int(self.mongo_port)
        )
        self.mongo_db = self.mongo_client[db]
        self.mongo_collection = self.mongo_db[collection]

    def write_one_docu(self, docu: dict) -> bool:
        try:
            if not docu.__contains__('creation_time'):
                docu['creation_time'] = datetime.today()
            new_data = self.mongo_collection.insert_one(docu)
            return new_data.inserted_id
        except Exception as err:
            logging.warning('MongoDB(组件)出现写入错误: {0}'.format(err))
            return False

    def does_it_exist(self, docu: dict) -> bool:
        count = self.mongo_collection.count_documents(docu)
        if count != 0:
            return True
        else:
            return False

    def update_docu(self, find_docu: dict, modify_docu: dict, many=False) -> bool:
        try:
            if many:
                self.mongo_collection.update_many(find_docu, modify_docu)
            else:
                self.mongo_collection.update_one(find_docu, modify_docu)
            return True
        except Exception as err:
            logging.warning('MongoDB(组件)出现更新错误: {0}'.format(err))
            return False

    def find_paging(self, parameter: Parameter) -> tuple:
        if parameter.verification(checking=parameter.param_url, verify={
                'page_size': str,  'current': str,  'columns': str,  'sort_order': str,
                'filtered_value': str, 'start_date': str, 'end_date': str,
        }):
            param = parameter.param_url
            try:
                page_size = int(param['page_size'])  # 每页条数
                current = int(param['current'])  # 当前页数
                if current < 1 or page_size < 1:
                    raise Exception('当前页数和每页条数都从 1 开始计算')
                else:
                    current -= 1
                columns = json.loads(param['columns'])  # 受控列
                # 排序顺序（对应受控列），asc=升序，desc=降序
                sort_order = json.loads(param['sort_order'])
                # 筛选值（对应受控列）
                filtered_value = json.loads(param['filtered_value'])
                start_date = handle_date(date=param['start_date'])  # 可选——开始日期
                # 可选——结束日期，与开始日期组成日期区间
                end_date = handle_date(date=param['end_date'], date_type='end')
                if len(columns) != len(sort_order) or len(columns) != len(filtered_value):
                    raise Exception('三个控制列表的长度不一致')
            except Exception as err:
                logging.warning('计算组件分页参数异常: {0}'.format(err))
                return '请求参数异常', 400, []
            # 查找字典和排序列表
            find_dict = {}
            sort_list = []
            if len(columns):
                for i in range(len(columns)):
                    # 整理请求参数中的筛选项字典
                    if filtered_value[i].strip() != '':
                        find_dict[columns[i]] = {'$regex': filtered_value[i]}
                    # 整理请求参数中的筛排序列表
                    sort_value = sort_order[i].strip()
                    if sort_value == 'asc':
                        sort_list.append((columns[i], pymongo.ASCENDING))
                    elif sort_value == 'desc':
                        sort_list.append((columns[i], pymongo.DESCENDING))
            # 仅存在日期查询区间参数时，进行额外的创建时间区间查询
            if start_date and end_date:
                find_dict['creation_time'] = {
                    '$gte': start_date, '$lte': end_date}
            find_data = self.mongo_collection.find(find_dict)
            records_filtered = find_data.count()
            if not records_filtered:
                return '请求数据不存在', 204, []
            if sort_list:
                find_data.sort(sort_list).limit(
                    page_size).skip(page_size*current)
            else:
                find_data.limit(page_size).skip(page_size*current)
            # 处理返回数据
            query_result = []
            for data in find_data:
                data['_id'] = str(data['_id'])
                query_result.append(data)
            return {
                'records_total': self.mongo_collection.estimated_document_count(),
                'records_filtered': records_filtered,
                'query_result': query_result,
            }, 200, []
        else:
            return '请求参数错误', 400, []
