/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { RespFields } from "./data";
import { EntityType, ExpressionResultType } from "@/views/dashboard/data";
import { ElMessage } from "element-plus";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useSelectorStore } from "@/store/modules/selectors";
import { useAppStoreWithOut } from "@/store/modules/app";
import type { MetricConfigOpt } from "@/types/dashboard";
import type { Instance, Endpoint, Service } from "@/types/selector";
import type { Node, Call } from "@/types/topology";

export async function useExpressionsQueryProcessor(config: Indexable) {
  function expressionsGraphqlPods() {
    if (!(config.metrics && config.metrics[0])) {
      return;
    }
    const appStore = useAppStoreWithOut();
    const dashboardStore = useDashboardStore();
    const selectorStore = useSelectorStore();

    if (!selectorStore.currentService && dashboardStore.entity !== "All") {
      return;
    }
    const conditions: Recordable = {
      duration: appStore.durationTime,
    };
    const variables: string[] = [`$duration: Duration!`];
    const isRelation = ["ServiceRelation", "ServiceInstanceRelation", "EndpointRelation", "ProcessRelation"].includes(
      dashboardStore.entity,
    );
    if (isRelation && !selectorStore.currentDestService) {
      return;
    }
    const fragment = config.metrics.map((name: string, index: number) => {
      variables.push(`$expression${index}: String!`, `$entity${index}: Entity!`);
      conditions[`expression${index}`] = name;
      const entity = {
        serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
        normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
        serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation", "Process"].includes(
          dashboardStore.entity,
        )
          ? selectorStore.currentPod && selectorStore.currentPod.value
          : undefined,
        endpointName: dashboardStore.entity.includes("Endpoint")
          ? selectorStore.currentPod && selectorStore.currentPod.value
          : undefined,
        processName: dashboardStore.entity.includes("Process")
          ? selectorStore.currentProcess && selectorStore.currentProcess.value
          : undefined,
        destNormal: isRelation ? selectorStore.currentDestService.normal : undefined,
        destServiceName: isRelation ? selectorStore.currentDestService.value : undefined,
        destServiceInstanceName: ["ServiceInstanceRelation", "ProcessRelation"].includes(dashboardStore.entity)
          ? selectorStore.currentDestPod && selectorStore.currentDestPod.value
          : undefined,
        destEndpointName:
          dashboardStore.entity === "EndpointRelation"
            ? selectorStore.currentDestPod && selectorStore.currentDestPod.value
            : undefined,
        destProcessName: dashboardStore.entity.includes("ProcessRelation")
          ? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value
          : undefined,
      };
      conditions[`entity${index}`] = entity;

      return `expression${index}: execExpression(expression: $expression${index}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
    });
    const queryStr = `query queryData(${variables}) {${fragment}}`;

    return {
      queryStr,
      conditions,
    };
  }

  function expressionsSource(resp: { errors: string; data: Indexable }) {
    if (resp.errors) {
      ElMessage.error(resp.errors);
      return { source: {}, tips: [], typesOfMQE: [] };
    }
    if (!resp.data) {
      ElMessage.error("The query is wrong");
      return { source: {}, tips: [], typesOfMQE: [] };
    }
    const tips: string[] = [];
    const source: { [key: string]: unknown } = {};
    const keys = Object.keys(resp.data);
    const typesOfMQE: string[] = [];

    for (let i = 0; i < config.metrics.length; i++) {
      const c: MetricConfigOpt = (config.metricConfig && config.metricConfig[i]) || {};
      const obj = resp.data[keys[i]] || {};
      const results = obj.results || [];
      const name = config.metrics[i];
      const type = obj.type;

      tips.push(obj.error);
      typesOfMQE.push(type);
      if (!obj.error) {
        if (type === ExpressionResultType.TIME_SERIES_VALUES) {
          if (results.length === 1) {
            const label = results[0].metric && results[0].metric.labels[0] && results[0].metric.labels[0].value;
            source[c.label || label || name] = results[0].values.map((d: { value: unknown }) => d.value) || [];
          } else {
            for (const item of results) {
              const values = item.values.map((d: { value: unknown }) => d.value) || [];
              const label = item.metric.labels
                .map((d: { key: string; value: string }) => `${d.key}=${d.value}`)
                .join(",");

              source[label] = values;
            }
          }
        }
        if (type === ExpressionResultType.SINGLE_VALUE) {
          for (const item of results) {
            const label = item.metric.labels
              .map((d: { key: string; value: string }) => `${d.key}=${d.value}`)
              .join(",");
            const values = item.values.map((d: { value: unknown }) => d.value) || [];
            if (results.length === 1) {
              source[label || c.label || name] = values;
            } else {
              source[label] = values;
            }
          }
        }
        if (([ExpressionResultType.RECORD_LIST, ExpressionResultType.SORTED_LIST] as string[]).includes(type)) {
          source[name] = results[0].values;
        }
      }
    }

    return { source, tips, typesOfMQE };
  }

  const params = await expressionsGraphqlPods();
  if (!params) {
    return { source: {}, tips: [], typesOfMQE: [] };
  }

  const dashboardStore = useDashboardStore();
  const json = await dashboardStore.fetchMetricValue(params);
  if (json.errors) {
    ElMessage.error(json.errors);
    return { source: {}, tips: [], typesOfMQE: [] };
  }
  try {
    const data = expressionsSource(json);

    return data;
  } catch (error) {
    console.error(error);
    return { source: {}, tips: [], typesOfMQE: [] };
  }
}

export async function useExpressionsQueryPodsMetrics(
  pods: Array<(Instance | Endpoint | Service) & Indexable>,
  config: {
    expressions: string[];
    subExpressions: string[];
    metricConfig: MetricConfigOpt[];
  },
  scope: string,
) {
  function expressionsGraphqlPods() {
    const metrics: string[] = [];
    const subMetrics: string[] = [];
    config.expressions = config.expressions || [];
    config.subExpressions = config.subExpressions || [];

    for (let i = 0; i < config.expressions.length; i++) {
      if (config.expressions[i]) {
        metrics.push(config.expressions[i]);
        subMetrics.push(config.subExpressions[i]);
      }
    }
    if (!metrics.length) {
      return;
    }
    const appStore = useAppStoreWithOut();
    const selectorStore = useSelectorStore();
    const conditions: { [key: string]: unknown } = {
      duration: appStore.durationTime,
    };
    const variables: string[] = [`$duration: Duration!`];
    const currentService = selectorStore.currentService || {};
    const fragmentList = pods.map((d: (Instance | Endpoint | Service) & Indexable, index: number) => {
      const entity = {
        serviceName: scope === "Service" ? d.label : currentService.label,
        serviceInstanceName: scope === "ServiceInstance" ? d.label : undefined,
        endpointName: scope === "Endpoint" ? d.label : undefined,
        normal: scope === "Service" ? d.normal : currentService.normal,
      };
      variables.push(`$entity${index}: Entity!`);
      conditions[`entity${index}`] = entity;
      const f = metrics.map((name: string, idx: number) => {
        variables.push(`$expression${index}${idx}: String!`);
        conditions[`expression${index}${idx}`] = name;
        let str = "";
        if (config.subExpressions[idx]) {
          variables.push(`$subExpression${index}${idx}: String!`);
          conditions[`subExpression${index}${idx}`] = config.subExpressions[idx];
          str = `subexpression${index}${idx}: execExpression(expression: $subExpression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
        }

        return (
          str +
          `expression${index}${idx}: execExpression(expression: $expression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`
        );
      });
      return f;
    });
    const fragment = fragmentList.flat(1).join(" ");
    const queryStr = `query queryData(${variables}) {${fragment}}`;

    return { queryStr, conditions };
  }

  function expressionsPodsSource(resp: { errors: string; data: Indexable }): Indexable {
    if (resp.errors) {
      ElMessage.error(resp.errors);
      return {};
    }
    const names: string[] = [];
    const subNames: string[] = [];
    const metricConfigArr: MetricConfigOpt[] = [];
    const metricTypesArr: string[] = [];
    const expressionsTips: string[] = [];
    const subExpressionsTips: string[] = [];
    const data = pods.map((d: any, idx: number) => {
      for (let index = 0; index < config.expressions.length; index++) {
        const c: MetricConfigOpt = (config.metricConfig && config.metricConfig[index]) || {};
        const k = "expression" + idx + index;
        const sub = "subexpression" + idx + index;
        const obj = resp.data[k] || {};
        const results = obj.results || [];
        const typesOfMQE = obj.type || "";
        const subObj = resp.data[sub] || {};
        const subResults = subObj.results || [];

        expressionsTips.push(obj.error);
        subExpressionsTips.push(subObj.error);
        if (results.length > 1) {
          const labels = (c.label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
          const labelsIdx = (c.labelsIndex || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
          for (let i = 0; i < results.length; i++) {
            let name = results[i].metric.labels[0].value || "";
            const subValues = subResults[i] && subResults[i].values.map((d: { value: unknown }) => d.value);
            const num = labelsIdx.findIndex((d: string) => d === results[i].metric.labels[0].value);

            if (labels[num]) {
              name = labels[num];
            }
            if (!d[name]) {
              d[name] = {};
            }
            if (subValues) {
              d[name]["values"] = subValues;
            }
            d[name]["avg"] = (results[i].values[0] || {}).value;

            const j = names.find((d: string) => d === name);

            if (!j) {
              names.push(name);
              metricConfigArr.push({ ...c, index: i });
              metricTypesArr.push(typesOfMQE);
            }
          }
        } else {
          if (!results[0]) {
            return d;
          }
          const name = config.expressions[index] || "";
          const subName = config.subExpressions[index] || "";
          if (!d[name]) {
            d[name] = {};
          }
          d[name]["avg"] = [(results[0].values[0] || {}).value];
          if (subResults[0]) {
            if (!d[subName]) {
              d[subName] = {};
            }
            d[subName]["values"] = subResults[0].values.map((d: { value: number }) => d.value);
          }
          const j = names.find((d: string) => d === name);
          if (!j) {
            names.push(name);
            subNames.push(subName);
            metricConfigArr.push(c);
            metricTypesArr.push(typesOfMQE);
          }
        }
      }
      return d;
    });

    return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips };
  }

  const dashboardStore = useDashboardStore();
  const params = await expressionsGraphqlPods();
  const json = await dashboardStore.fetchMetricValue(params);

  if (json.errors) {
    ElMessage.error(json.errors);
    return {};
  }
  const expressionParams = expressionsPodsSource(json);

  return expressionParams;
}

export function useQueryTopologyExpressionsProcessor(metrics: string[], instances: (Call | Node)[]) {
  const appStore = useAppStoreWithOut();
  const dashboardStore = useDashboardStore();

  function getExpressionQuery() {
    const conditions: { [key: string]: unknown } = {
      duration: appStore.durationTime,
    };
    const variables: string[] = [`$duration: Duration!`];
    const fragmentList = instances.map((d: any, index: number) => {
      let serviceName;
      let destServiceName;
      let endpointName;
      let serviceInstanceName;
      let destServiceInstanceName;
      let destEndpointName;
      let normal = false;
      let destNormal;
      if (d.sourceObj && d.targetObj) {
        // instances = Calls
        serviceName = d.sourceObj.serviceName || d.sourceObj.name;
        destServiceName = d.targetObj.serviceName || d.targetObj.name;
        normal = d.sourceObj.normal || d.sourceObj.isReal || false;
        destNormal = d.targetObj.normal || d.targetObj.isReal || false;
        if (EntityType[4].value === dashboardStore.entity) {
          serviceInstanceName = d.sourceObj.name;
          destServiceInstanceName = d.targetObj.name;
        }
        if (EntityType[2].value === dashboardStore.entity) {
          endpointName = d.sourceObj.name;
          destEndpointName = d.targetObj.name;
        }
      } else {
        // instances = Nodes
        serviceName = d.serviceName || d.name;
        normal = d.normal || d.isReal || false;
        if (EntityType[3].value === dashboardStore.entity) {
          serviceInstanceName = d.name;
        }
        if (EntityType[4].value === dashboardStore.entity) {
          serviceInstanceName = d.name;
        }
        if (EntityType[2].value === dashboardStore.entity) {
          endpointName = d.name;
        }
      }
      const entity = {
        serviceName,
        normal,
        serviceInstanceName,
        endpointName,
        destServiceName,
        destNormal: destServiceName ? destNormal : undefined,
        destServiceInstanceName,
        destEndpointName,
      };
      variables.push(`$entity${index}: Entity!`);
      conditions[`entity${index}`] = entity;
      const f = metrics.map((name: string, idx: number) => {
        if (index === 0) {
          variables.push(`$expression${idx}: String!`);
          conditions[`expression${idx}`] = name;
        }
        return `expression${index}${idx}: execExpression(expression: $expression${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
      });
      return f;
    });
    const fragment = fragmentList.flat(1).join(" ");
    const queryStr = `query queryData(${variables}) {${fragment}}`;

    return { queryStr, conditions };
  }
  function handleExpressionValues(resp: { [key: string]: any }) {
    const obj: any = {};
    for (let idx = 0; idx < instances.length; idx++) {
      for (let index = 0; index < metrics.length; index++) {
        const k = "expression" + idx + index;
        if (metrics[index]) {
          if (!obj[metrics[index]]) {
            obj[metrics[index]] = {
              values: [],
            };
          }
          obj[metrics[index]].values.push({
            value: resp[k].results[0] && resp[k].results[0].values[0].value,
            id: instances[idx].id,
          });
        }
      }
    }
    return obj;
  }

  return { getExpressionQuery, handleExpressionValues };
}
