/*
 * 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 { reactive } from 'vue'
import {
  updateTask,
  genTaskCodeList,
  saveSingle,
  queryTaskDefinitionByCode,
  updateWithUpstream
} from '@/service/modules/task-definition'
import { formatParams as formatData } from '../components/node/format-data'
import type { ITaskData, INodeData, ISingleSaveReq, IRecord } from './types'
import { Connect } from '../../workflow/components/dag/types'

export function useTask(projectCode: number) {
  const initalTask = {
    taskType: 'SHELL'
  } as ITaskData
  const task = reactive({
    taskShow: false,
    taskData: { ...initalTask },
    taskSaving: false,
    taskReadonly: false
  } as { taskShow: boolean; taskData: ITaskData; taskSaving: boolean; taskReadonly: boolean })

  const formatParams = (data: INodeData, isCreate: boolean): ISingleSaveReq => {
    const params = formatData(data)
    if (isCreate) {
      return {
        processDefinitionCode: params.processDefinitionCode,
        upstreamCodes: params.upstreamCodes,
        taskDefinitionJsonObj: JSON.stringify(params.taskDefinitionJsonObj)
      }
    }
    return {
      upstreamCodes: params.upstreamCodes,
      taskDefinitionJsonObj: JSON.stringify(params.taskDefinitionJsonObj)
    }
  }

  const getTaskCode = async () => {
    const result = await genTaskCodeList(1, projectCode)
    return result[0]
  }

  const onToggleShow = (show: boolean) => {
    task.taskShow = show
  }
  const onTaskSave = async (data: INodeData) => {
    if (task.taskSaving) return
    task.taskSaving = true
    try {
      if (data.id) {
        data.code &&
          (await updateWithUpstream(
            projectCode,
            data.code,
            formatParams({ ...data, code: data.code }, false)
          ))
      } else {
        const taskCode = await getTaskCode()
        await saveSingle(
          projectCode,
          formatParams({ ...data, code: taskCode }, true)
        )
      }

      task.taskSaving = false
      return true
    } catch (err) {
      task.taskSaving = false
      return false
    }
  }

  const onEditTask = async (row: IRecord, readonly: boolean) => {
    const result = await queryTaskDefinitionByCode(row.taskCode, projectCode)
    task.taskData = {
      ...result,
      processName: row.processDefinitionCode,
      preTasks:
        result?.processTaskRelationList?.map(
          (item: Connect) => item.preTaskCode
        ) || []
    }
    task.taskShow = true
    task.taskReadonly = readonly
  }

  const onInitTask = () => {
    task.taskData = { ...initalTask }
    task.taskReadonly = false
  }

  const onUpdateTask = async (data: INodeData) => {
    if (task.taskSaving || !data.code) return
    task.taskSaving = true

    const params = {
      taskExecuteType: 'STREAM',
      taskDefinitionJsonObj: JSON.stringify(
        formatData(data).taskDefinitionJsonObj
      )
    }

    try {
      await updateTask(projectCode, data.code, params)

      task.taskSaving = false
      return true
    } catch (err) {
      task.taskSaving = false
      return false
    }
  }

  return {
    task,
    onToggleShow,
    onTaskSave,
    onEditTask,
    onInitTask,
    onUpdateTask
  }
}
