import os

import pandas as pd
import plotly.graph_objects as go
from algorithmContract.confBusiness import *
from algorithmContract.contract import Contract
from behavior.analystWithGoodBadPoint import AnalystWithGoodBadPoint
from plotly.subplots import make_subplots


class RatedPowerWindSpeedAnalyst(AnalystWithGoodBadPoint):
    """
    风电机组额定功率风速分析。
    秒级scada数据运算太慢，建议使用分钟级scada数据
    """

    def typeAnalyst(self):
        return "rated_power_windspeed"

    def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
        dictionary=self.processTurbineData(turbineCodes,conf,[Field_DeviceCode,Field_Time,Field_EnvTemp,Field_WindSpeed,Field_ActiverPower])
        dataFrameMerge=self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
        turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
        return self.draw(dataFrameMerge, outputAnalysisDir, conf,turbineInfos)

    def draw(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract,turbineModelInfo: pd.Series):
        """
        绘制并保存额定满发风速功率分布图，根据环境温度是否大于等于25℃。

        参数:
        dataFrameMerge (pd.DataFrame): 包含数据的DataFrame，需要包含设备名、风速和功率列。
        outputAnalysisDir (str): 分析输出目录。
        confData (ConfBusiness): 配置
        """
        # 检查所需列是否存在
        required_columns = {Field_EnvTemp,
                            Field_WindSpeed, Field_ActiverPower}
        if not required_columns.issubset(dataFrameMerge.columns):
            raise ValueError(f"DataFrame缺少必要的列。需要的列有: {required_columns}")

        y_name = '功率'
        upLimitOfPower = self.turbineInfo[Field_RatedPower].max() * 1.2
        lowLimitOfPower = self.turbineInfo[Field_RatedPower].max()*0.9
        field_RatedWindSpeed = self.turbineModelInfo[Field_RatedWindSpeed].max()

        # 根据环境温度筛选数据
        over_temp = dataFrameMerge[(dataFrameMerge[Field_EnvTemp] >= 25) & (
            dataFrameMerge[Field_WindSpeed] >= field_RatedWindSpeed) & (dataFrameMerge[Field_ActiverPower] >= lowLimitOfPower)].sort_values(by=Field_NameOfTurbine)
        below_temp = dataFrameMerge[(dataFrameMerge[Field_EnvTemp] < 25) & (
            dataFrameMerge[Field_WindSpeed] >= field_RatedWindSpeed) & (dataFrameMerge[Field_ActiverPower] >= lowLimitOfPower)].sort_values(by=Field_NameOfTurbine)

        # 绘制环境温度大于等于25℃的功率分布图
        fig = make_subplots(rows=1, cols=1)
        fig.add_trace(go.Box(y=over_temp[Field_ActiverPower], x=over_temp[Field_NameOfTurbine],
                             # name='Ambient Temp >= 25°C',
                             boxpoints='outliers',
                             # box line color
                             line=dict(color='black', width=1),
                             # quartilemethod='exclusive',
                             fillcolor='dodgerblue',
                             showlegend=False,
                             marker=dict(color='rgba(0, 0, 0, 0)', size=0.1)),
                      row=1, col=1)

        # Calculate medians and plot them as a line for visibility
        medians = over_temp.groupby(Field_NameOfTurbine)[
            Field_ActiverPower].median()
        median_line = go.Scatter(
            x=medians.index,
            y=medians.values,
            mode='markers',
            marker=dict(symbol='line-ew-open', color='red', size=12),
            showlegend=False
        )
        fig.add_trace(median_line)

        # 更新布局
        fig.update_yaxes(title_text=y_name, row=1, col=1, range=[
                         lowLimitOfPower, upLimitOfPower], tickfont=dict(size=10))
        fig.update_xaxes(title_text='机组', type='category',
                         tickangle=-45, tickfont=dict(size=10))
        fig.update_layout(title={
                          'text': f'额定功率分布(环境温度>=25摄氏度)', 'x': 0.5}, boxmode='group')
        # 确保从 Series 中提取的是具体的值
        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
        if isinstance(engineTypeCode, pd.Series):
            engineTypeCode = engineTypeCode.iloc[0]
        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
        if isinstance(engineTypeName, pd.Series):
            engineTypeName = engineTypeName.iloc[0]
        # 构建最终的JSON对象
        json_output = {
            "analysisTypeCode": "额定功率和风速分析",
            "engineCode":  engineTypeCode,
            "engineTypeName": engineTypeName,
            "xaixs": "机组",
            "yaixs": "功率(kW)",
            "data": [{
                    "title":f'额定功率分布（环境温度>=25摄氏度）',
                    "xData": over_temp[Field_NameOfTurbine].tolist(),
                    "yData": over_temp[Field_ActiverPower].tolist(),
                    "linecolor":'black',
                    "linewidth":1,
                    "fillcolor":'dodgerblue'
                    }]
        }
        result_rows = []
        # 保存图像
        # pngFileName = "额定满发风速功率分布(10min)(环境温度大于25度).png"
        # pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
        # fig.write_image(pngFilePath, scale=3)

        # # 保存HTML
        # htmlFileName = "额定满发风速功率分布(10min)(环境温度大于25度).html"
        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
        # fig.write_html(htmlFilePath)
        # 保存Json
        # 将JSON对象保存到文件
        output_json_path = os.path.join(outputAnalysisDir, "total_more_25.json")
        with open(output_json_path, 'w', encoding='utf-8') as f:
            import json
            json.dump(json_output, f, ensure_ascii=False, indent=4)
        # 如果需要返回DataFrame，可以包含文件路径
        result_rows.append({
            Field_Return_TypeAnalyst: self.typeAnalyst(),
            Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
            Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
            Field_CodeOfTurbine: 'total',
            Field_MillTypeCode: 'total_more_25',
            Field_Return_FilePath: output_json_path,
            Field_Return_IsSaveDatabase: True
        })
        # result_rows.append({
        #     Field_Return_TypeAnalyst: self.typeAnalyst(),
        #     Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
        #     Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
        #     Field_CodeOfTurbine: 'total',
        #     Field_Return_FilePath: pngFilePath,
        #     Field_Return_IsSaveDatabase: False
        # })

        # result_rows.append({
        #     Field_Return_TypeAnalyst: self.typeAnalyst(),
        #     Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
        #     Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
        #     Field_CodeOfTurbine: 'total',
        #     Field_Return_FilePath: htmlFilePath,
        #     Field_Return_IsSaveDatabase: True
        # })

        # 绘制环境温度小于25℃的功率分布图
        fig = make_subplots(rows=1, cols=1)
        fig.add_trace(go.Box(y=below_temp[Field_ActiverPower], x=below_temp[Field_NameOfTurbine],
                             # name='Ambient Temp < 25°C',
                             boxpoints='outliers',
                             # box line color
                             line=dict(color='black', width=1),
                             # quartilemethod='exclusive',
                             fillcolor='dodgerblue',
                             showlegend=False,
                             marker=dict(color='rgba(0, 0, 0, 0)', size=0.1)),
                      row=1, col=1)

        # Calculate medians and plot them as a line for visibility
        medians = below_temp.groupby(Field_NameOfTurbine)[
            Field_ActiverPower].median()
        median_line = go.Scatter(
            x=medians.index,
            y=medians.values,
            mode='markers',
            marker=dict(symbol='line-ew-open', color='red', size=10),
            showlegend=False
        )
        fig.add_trace(median_line)

        # 更新布局
        fig.update_yaxes(title_text=y_name, row=1, col=1, range=[
                         lowLimitOfPower, upLimitOfPower], tickfont=dict(size=10))
        fig.update_xaxes(title_text='机组', type='category',
                         tickangle=-45, tickfont=dict(size=10))
        fig.update_layout(title={
                          'text': f'额定功率分布(环境温度<25摄氏度)', 'x': 0.5}, boxmode='group')
        # 构建最终的JSON对象2
        json_output2 = {
            "analysisTypeCode": "额定功率和风速分析",
            "engineCode":  engineTypeCode,
            "engineTypeName": engineTypeName,
            "xaixs": "机组",
            "yaixs": "功率(kw)",
            "data": [{
                    "title":f'额定功率分布(环境温度<25摄氏度)',
                    "xData": below_temp[Field_NameOfTurbine].tolist(),
                    "yData": below_temp[Field_ActiverPower].tolist(),
                    "linecolor":'black',
                    "linewidth":1,
                    "fillcolor":'dodgerblue'
                    }]
        }
        # 保存图像
        # pngFileName = "额定满发风速功率分布(10min)(环境温度小于25度).png"
        # pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
        # fig.write_image(pngFilePath, scale=3)

        # # 保存HTML
        # htmlFileName = "额定满发风速功率分布(10min)(环境温度小于25度).html"
        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
        # fig.write_html(htmlFilePath)
                # 保存Json
        # 将JSON对象保存到文件
        output_json_path2 = os.path.join(outputAnalysisDir, "total_less_25.json")
        with open(output_json_path2, 'w', encoding='utf-8') as f:
            import json
            json.dump(json_output2, f, ensure_ascii=False, indent=4)
        # 如果需要返回DataFrame，可以包含文件路径
        result_rows.append({
            Field_Return_TypeAnalyst: self.typeAnalyst(),
            Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
            Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
            Field_CodeOfTurbine: 'total',
            Field_MillTypeCode: 'total_less_25',
            Field_Return_FilePath: output_json_path2,
            Field_Return_IsSaveDatabase: True
        })
        # result_rows.append({
        #     Field_Return_TypeAnalyst: self.typeAnalyst(),
        #     Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
        #     Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
        #     Field_CodeOfTurbine: 'total',
        #     Field_Return_FilePath: pngFilePath,
        #     Field_Return_IsSaveDatabase: False
        # })

        # result_rows.append({
        #     Field_Return_TypeAnalyst: self.typeAnalyst(),
        #     Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
        #     Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
        #     Field_CodeOfTurbine: 'total',
        #     Field_Return_FilePath: htmlFilePath,
        #     Field_Return_IsSaveDatabase: True
        # })

        result_df = pd.DataFrame(result_rows)

        return result_df

        """
        # 绘制环境温度大于等于25℃的功率分布图
        fig, ax = plt.subplots()
        sns.boxplot(y=confData.field_power, x=Field_NameOfTurbine, data=over_temp, fliersize=0, ax=ax,
                    medianprops={'linestyle': '-', 'color': 'red'},
                    boxprops={'color': 'dodgerblue', 'facecolor': 'dodgerblue'})
        ax.yaxis.set_major_locator(ticker.MultipleLocator(100))
        ax.set_ylim(lowLimitOfPower, upLimitOfPower)
        ax.set_ylabel(y_name)
        ax.set_title(
            'rated wind speed and power distribute(10min)(ambient temperature>=25℃)')
        ax.grid(True)
        plt.xticks(rotation=45)  # 旋转45度
        plt.savefig(os.path.join(outputAnalysisDir,
                    "额定满发风速功率分布(10min)(环境温度大于25度).png"), bbox_inches='tight', dpi=120)
        plt.close()

        # 绘制环境温度小于25℃的功率分布图
        fig, ax = plt.subplots()
        sns.boxplot(y=confData.field_power, x=Field_NameOfTurbine, data=below_temp, fliersize=0, ax=ax,
                    medianprops={'linestyle': '-', 'color': 'red'},
                    boxprops={'color': 'dodgerblue', 'facecolor': 'dodgerblue'})
        ax.yaxis.set_major_locator(ticker.MultipleLocator(100))
        ax.set_ylim(lowLimitOfPower, upLimitOfPower)
        ax.set_ylabel(y_name)
        ax.set_title(
            'rated wind speed and power distribute(10min)(ambient temperature<25℃)')
        ax.grid(True)
        plt.xticks(rotation=45)  # 旋转45度
        plt.savefig(os.path.join(outputAnalysisDir,
                    "额定满发风速功率分布(10min)(环境温度小于25度).png"), bbox_inches='tight', dpi=120)
        plt.close()
        """
