# -*- coding: utf-8 -*-
"""
Description:
    
Versions:
    Created by www.rokedata.com<HuChuanwei>
"""
import base64
import io
import json
import time
import datetime
import requests
import logging
from . import generator
from odoo import models, fields, api, _
_logger = logging.getLogger(__name__)


class InheritWorkCenter(models.Model):
    _inherit = "roke.work.center"

    app_name = fields.Char(string="切割软件名称")
    app_ver = fields.Char(string="切割软件版本")
    card_id = fields.Char(string="控制卡ID")
    # 机床加工中的任务
    filename = fields.Char(string="加工文件")
    portionId = fields.Char(string="排版ID")
    startTime = fields.Datetime(string="开始时间")
    # 机床状态
    deviceState = fields.Selection([
        ("OFFLINE", "离线"),
        ("WORKING", "加工中"),
        ("ALARMING", "报警中"),
        ("IDLE", "空闲"),
        ("UNKNOWN", "未知"),
        ("CLOSE", "关闭切割软件"),
        ("PAUSE", "暂停加工"),
        ("STOP", "停止加工")
    ], string="机床状态")
    # 机床切割系统状态
    axisX = fields.Float(string="X轴")
    axisY = fields.Float(string="Y轴")
    axisZ = fields.Integer(string="Z轴")
    workTime = fields.Float(string="加工时长")
    workTimeStr = fields.Char(string="加工时长")
    workSpeed = fields.Integer(string="加工速度")
    cutPercent = fields.Float(string="加工进度(%)")
    laserPower = fields.Integer(string="激光器功率")
    pwmFreq = fields.Integer(string="Pwm频率(Hz)")
    gasType = fields.Char(string="气体类型")
    gasPressure = fields.Integer(string="切割气压")
    pwmRatio = fields.Integer(string="Pwm占空比(%)")
    targetHeight = fields.Integer(string="跟随高度(设定值)")
    diodeCurrent = fields.Integer(string="峰值功率(%)")
    taskName = fields.Char(string="任务名称")

    def _request_work_logs(self, card_id, headers, start_time, end_time, time_interval, page_number=0, page_size=50, total=None):
        """
        请求加工记录接口
        :return:
        """
        if not start_time or not end_time:
            end_datetime = fields.Datetime.now() + datetime.timedelta(hours=8)
            start_datetime = end_datetime - datetime.timedelta(minutes=time_interval)
            start_time = start_datetime.strftime("%Y-%m-%d %H:%M:%S")
            end_time = end_datetime.strftime("%Y-%m-%d %H:%M:%S")
        url = "https://mcs-gateway.fscut.com/api/statistics/work_logs/v2"
        payload = json.dumps({
            "cardId": card_id,
            "startTime": start_time,
            "endTime": end_time,
            "pageNumber": page_number,
            "pageSize": page_size,
            "timeDesc": False
        })
        response = requests.request("POST", url, headers=headers, data=payload)
        response_dict = json.loads(response.text)
        if response_dict.get("status") != 0:
            _logger.error("获取机床加工记录错误：")
            _logger.error(response_dict)
            return []
        response_data = response_dict.get("data")
        result = response_data.get("list")
        if not total:
            total = response_data.get("meta").get("total")
        if (page_number + 1) * page_size < total:
            time.sleep(1)
            result += self._request_work_logs(
                card_id,
                headers,
                start_time,
                end_time,
                time_interval,
                page_number=page_number + 1,
                page_size=page_size,
                total=total
            )
        return result

    def _get_request_headers(self):
        """
        获取请求头
        :return: 
        """
        app_id = self.env["ir.config_parameter"].get_param("fscut.app_id")
        app_secret = self.env["ir.config_parameter"].get_param("fscut.app_secret")
        helper = generator.OpenApiHeaderHelper(app_id, app_secret)
        map_header = helper.gen_map()
        return {
            "Content-Type": "application/json",
            "app-id": map_header.get("app-id"),
            "time-stamp": str(map_header.get("time-stamp")),
            "app-sign": map_header.get("app-sign")
        }

    def _get_work_log_vals(self, work_log, work_center_id, write=False):
        """
        创建加加工记录
        :return:
        """
        vals = work_log.copy()
        vals.pop("parts")
        parts = work_log.get("parts", [])
        part_vals = [] if not write else [(6, 0, [])]
        for part in parts:
            part_vals.append((0, 0, part))
        vals.update({
            "endState": str(work_log.get("endState")),
            "part_ids": part_vals,
            "work_center_id": work_center_id
        })
        return vals

    def get_work_logs(self, start_time=None, end_time=None, time_interval=10):
        """
        获取机床加工记录
        :return:
        """
        if not self:
            records = self.search([("card_id", "!=", False)])
        else:
            records = self.filtered(lambda w: w.cardId)
        WorkLog = self.sudo().env["roke.work.log"]
        headers = self._get_request_headers()
        for record in records:
            work_logs = self._request_work_logs(record.card_id, headers, start_time, end_time, time_interval)
            for work_log in work_logs:
                workUuid = work_log.get("workUuid")
                work_log_rec = WorkLog.search([("workUuid", "=", workUuid), ("work_center_id", "=", record.id)])
                if work_log_rec:
                    work_log_rec.write(self._get_work_log_vals(work_log, record.id, write=True))
                else:
                    WorkLog.create(self._get_work_log_vals(work_log, record.id))
            time.sleep(1)

    def _request_user_devices(self, headers):
        """
        请求车床列表接口
        :return:
        """
        url = "https://mcs-gateway.fscut.com/api/user_devices"
        payload = json.dumps({})
        response = requests.request("POST", url, headers=headers, data=payload)
        response_dict = json.loads(response.text)
        result = response_dict.get("data")
        return result

    def _get_cardIdDevices(self, headers, cardIdDevices):
        """
        单独执行时获取请求头和请求设备
        :return:
        """
        if not cardIdDevices:
            cardIdDevices = {}
            existing_devices = self.search([("card_id", "!=", False)])
            for existing_device in existing_devices:
                cardIdDevices[existing_device.id] = existing_device
        if not headers:
            headers = self._get_request_headers()
        return headers, cardIdDevices

    def get_devices_state(self, headers=None, cardIdDevices=None):
        """
        获取设备状态
        :return:
        """
        headers, cardIdDevices = self._get_cardIdDevices(headers, cardIdDevices)
        card_ids = list(cardIdDevices.keys())
        url = "https://mcs-gateway.fscut.com/api/user_devices/current_state"
        payload = json.dumps({"cardIds": card_ids})
        response = requests.request("POST", url, headers=headers, data=payload)
        response_dict = json.loads(response.text)
        if response_dict.get("status") != 0:
            _logger.error("获取设备状态异常")
            _logger.error(response_dict)
            return
        result = response_dict.get("data")
        for device_state in result:
            cardId = device_state.get("cardId")
            deviceState = device_state.get("deviceState")
            cardIdDevices.get(cardId).write({"deviceState": deviceState})
            time.sleep(1)

    def get_cut_system_state(self, headers=None, cardIdDevices=None):
        """
        获取机床切割系统的实时状态
        :return:
        """
        headers, cardIdDevices = self._get_cardIdDevices(headers, cardIdDevices)
        for cardId, device in cardIdDevices.items():
            url = "https://mcs-gateway.fscut.com/api/user_devices/cut_system_state"
            payload = json.dumps({"cardId": cardId})
            response = requests.request("POST", url, headers=headers, data=payload)
            response_dict = json.loads(response.text)
            if response_dict.get("status") != 0:
                _logger.error("获取机床切割系统的实时状态异常")
                _logger.error(response_dict)
                time.sleep(1)
                continue
            result = response_dict.get("data")
            device.write(result)
            time.sleep(1)

    def get_current_work(self, headers=None, cardIdDevices=None):
        """
        获取机床加工中的任务
        :return:
        """
        headers, cardIdDevices = self._get_cardIdDevices(headers, cardIdDevices)
        for cardId, device in cardIdDevices.items():
            url = "https://mcs-gateway.fscut.com/api/user_devices/current_work"
            payload = json.dumps({"cardId": cardId})
            response = requests.request("POST", url, headers=headers, data=payload)
            response_dict = json.loads(response.text)
            if response_dict.get("status") != 0:
                _logger.error("获取机床加工中的任务异常")
                _logger.error(response_dict)
                time.sleep(1)
                continue
            result = response_dict.get("data")
            if result.get("startTime"):  # 修改开始时间
                result.update({
                    "startTime": datetime.datetime.strptime(result.get("startTime"), "%Y-%m-%d %H:%M:%S") - datetime.timedelta(hours=8)
                })
            device.write(result)
            time.sleep(1)

    def get_user_devices(self):
        """
        获取车床列表
        :return:
        """
        headers = self._get_request_headers()
        user_devices = self._request_user_devices(headers)
        existing_devices = self.search([("card_id", "!=", False)])
        cardIdDevices = {}
        for existing_device in existing_devices:
            cardIdDevices[existing_device.card_id] = existing_device
        for user_device in user_devices:
            cardId = user_device.get("cardId")
            if cardId in cardIdDevices:
                continue
            new_device = self.create({
                "code": cardId,
                "name": user_device.get("nickname"),
                "app_name": user_device.get("appName"),
                "app_ver": user_device.get("appVer"),
                "card_id": cardId
            })
            cardIdDevices[new_device.card_id] = new_device
        self.flush()
        _logger.info("获取机床列表完毕")
        # 获取机床状态
        self.get_devices_state(headers=headers, cardIdDevices=cardIdDevices)
        self.flush()
        _logger.info("获取机床状态完毕")
        # 获取机床切割系统的实时状态
        self.get_cut_system_state(headers=headers, cardIdDevices=cardIdDevices)
        self.flush()
        _logger.info("获取机床切割系统的实时状态完毕")
        # 获取机床加工中的任务
        self.get_current_work(headers=headers, cardIdDevices=cardIdDevices)
        self.flush()
        _logger.info("获取机床加工中的任务完毕")

    def upload_task(self, task, attachment):
        """
        上传任务
        :return:
        """
        headers = self._get_request_headers()
        headers.pop("Content-Type")
        url = "https://mcs-gateway.fscut.com/upload/api/device_tasks/upload/cut"
        payload = {
            "cardId": task.work_center_id.card_id,
            "taskName": task.taskName,
            "taskAmount": 1
        }
        binary_data = base64.b64decode(attachment.datas)
        file_like_object = io.BytesIO(binary_data)
        filename = attachment.name
        files = [('file', (filename, file_like_object, 'application/octet-stream'))]
        try:
            response = requests.request("POST", url, headers=headers, data=payload, files=files)
            response_dict = json.loads(response.text)
            UploadMsg = response_dict.get("msg")
            TaskUUID = response_dict.get("data") or ""
            _logger.info(f"任务上传成功：{task.taskName}")
        except Exception as e:
            UploadMsg = e
            TaskUUID = ""
            _logger.error("上传任务失败")
            _logger.error(e)
        task.write({"UploadMsg": UploadMsg, "TaskUUID": TaskUUID})
