<template>
  <div class="taskList">
    <a-spin :spinning="state.onlineDockListLoading" v-if="state.collapsed">
      <div class="taskList-left">
        <div class="taskList-left-title">
          <div>
            当前机场
          </div>
          <a-checkbox v-model:checked="checkState.checkAll" :indeterminate="checkState.indeterminate"
            @change="onCheckAllChange">
            全选
          </a-checkbox>
        </div>
        <div v-if="state.onlineDockList.length">
          <div v-for="(dock) in state.onlineDockList" :key="dock.sn">
            <div :class="[
              'taskList-left-item',
              checkState.checkSnList.includes(dock.gateway.sn) ? 'taskList-left-item-selected' : ''
            ]" @click="onClickCheckItem(dock.gateway.sn)">
              <Airport :dock="dock" :look-info="false" />
            </div>
          </div>
        </div>
        <a-empty style="margin-top: 20%;" :image="noDataSrc" :image-style="{ height: '60px' }" v-else />
        <div class="taskList-left-fill"></div>
      </div>
    </a-spin>
    <div :style="{ width: state.collapsed ? 'calc(100% - 250px)' : '100%' }">
      <Search :onClickCollapsed="() => { state.collapsed = !state.collapsed }" :onClickCreateTask="onClickCreateTask"
        :onClickSearch="onClickSearch" :onClickReset="onClickReset" />
      <a-table :scroll="{ x: '100%', y: 500 }" rowKey="job_id" :loading="state.listLoading" :columns="columns"
        :dataSource="state.list" @change="refreshData" :rowClassName="rowClassName" :pagination="paginationConfig">
        <!-- 计划｜实际时间 -->
        <template #duration="{ record }">
          <div class="flex-row" style="white-space: pre-wrap">
            <div>
              <div>
                {{ record.begin_time }}
              </div>
              <div>
                {{ record.end_time }}
              </div>
            </div>
            <div class="ml10">
              <div>
                {{ record.execute_time }}
              </div>
              <div>
                {{ record.completed_time }}
              </div>
            </div>
          </div>
        </template>
        <!-- 执行状态 -->
        <template #status="{ record }">
          <div style="color: #2B85E4;" v-if="record.status === 1">
            待执行
          </div>
          <div style="color: #2B85E4;" v-else-if="record.status === 2">
            执行中
          </div>
          <div style="color: #19BE6B;" v-else-if="record.status === 3">
            完成
          </div>
          <div style="color: #E02020;" v-else-if="record.status === 4">
            取消
          </div>
          <div style="color: #E02020;" v-else-if="record.status === 5">
            <span>
              失败
            </span>
            <a-tooltip :title="record.error_text">
              <ExclamationCircleOutlined />
            </a-tooltip>
          </div>
          <div style="color: #2B85E4;" v-else-if="record.status === 6">
            暂停
          </div>
        </template>
        <!-- 媒体上传 -->
        <template #media_upload="{ record }">
          <div style="display: flex;align-items: center;">
            <div style="display: flex;align-items: center;">
              <span class="circle-icon" :style="{ backgroundColor: formatMediaTaskStatus(record).color }"></span>
              {{ formatMediaTaskStatus(record).text }}
            </div>
            <div class="pl15">
              {{ formatMediaTaskStatus(record).number }}
            </div>
          </div>
        </template>
        <!-- 操作 -->
        <template #action="{ record }">
          <div class="flex-align-center flex-row" style="color: #2d8cf0">
            <a-tooltip title="查看详情">
              <EyeOutlined style="margin-right: 10px;" @click="onClickLookDetail(record.job_id)" />
            </a-tooltip>
            <a-tooltip title="复制任务" v-if="[0, 1].includes(record.task_type)">
              <CopyOutlined style=" margin-right: 10px;" @click="onClickCopy(record.job_id)" />
            </a-tooltip>
            <a-tooltip title="断点续飞" v-if="record.breakpoint_continuation && record.wayline_mission_state === 7">
              <ApiOutlined style="margin-right: 10px;" @click="onClickContinueFlight(record.job_id)" />
            </a-tooltip>
            <a-tooltip title="删除" v-if="record.status !== 4">
              <DeleteOutlined @click="onClickDelete(record.job_id, record.job_name)" />
            </a-tooltip>
          </div>
        </template>
      </a-table>
    </div>
    <TaskModal :jobId="state.currentJobId" :type="state.currentType" :visible="state.visible"
      :onClickConfirm="taskModalOnClickConfirm" :onClickCancel="taskModalOnClickCancel" v-if="state.visible" />
  </div>
</template>

<script lang="ts" setup>
import { reactive, onMounted, watch } from 'vue';
import { Modal, message } from 'ant-design-vue';
import { ExclamationCircleOutlined, ApiOutlined, CopyOutlined, EyeOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import Search from './components/Search.vue';
import Airport from '/@/components/airport/index.vue';
import TaskModal from './components/TaskModal.vue';
import noDataSrc from '/@/assets/icons/no-data.png';
import { useFormatTask } from '/@/components/task/use-format-task';
import { apis } from '/@/api/custom';
import { getDeviceTopo } from '/@/api/manage';
import { createPlan } from '/@/api/wayline';
import { getWorkspaceId } from '/@/utils';
import { OnlineDevice, EModeCode } from '/@/types/device';
import { EDeviceTypeName } from '/@/types';

interface State {
  currentJobId: string,
  currentType: 'COPY' | 'DETAIL' | 'CREATE',
  visible: boolean,
  collapsed: boolean,
  onlineDockListLoading: boolean,
  onlineDockList: OnlineDevice[],
  query: any,
  listLoading: boolean,
  list: any[],
};

const state: State = reactive({
  currentJobId: '',
  currentType: 'CREATE',
  visible: false,
  collapsed: true,
  onlineDockListLoading: false,
  onlineDockList: [],
  query: undefined,
  listLoading: false,
  list: [],
});

const checkState = reactive({
  checkAll: false as boolean,
  indeterminate: false as boolean,
  checkSnList: [] as string[],
});

watch(() => checkState.checkSnList, val => {
  checkState.indeterminate = !!val.length && val.length < state.onlineDockList.length;
  checkState.checkAll = val.length === state.onlineDockList.length;
}, { deep: true });

const { formatMediaTaskStatus } = useFormatTask();

const fetchOnlineDock = async () => {
  state.onlineDockListLoading = true;
  try {
    const res = await getDeviceTopo(getWorkspaceId());
    if (res.code !== 0) {
      return;
    }
    const list: OnlineDevice[] = [];
    res.data.forEach((gateway: any) => {
      const child = gateway.children
      const device: OnlineDevice = {
        model: child?.device_name,
        callsign: child?.nickname,
        sn: child?.device_sn,
        mode: EModeCode.Disconnected,
        gateway: {
          model: gateway?.device_name,
          callsign: gateway?.nickname,
          sn: gateway?.device_sn,
          domain: gateway?.domain
        },
        payload: []
      }
      child?.payloads_list.forEach((payload: any) => {
        device.payload.push({
          index: payload.index,
          model: payload.model,
          payload_name: payload.payload_name,
          payload_sn: payload.payload_sn,
          control_source: payload.control_source,
          payload_index: payload.payload_index
        })
      })
      if (EDeviceTypeName.Dock === gateway.domain) {
        list.push(device)
      }
    })
    state.onlineDockList = list;
    checkState.checkAll = true;
    checkState.checkSnList = list.map(item => item.gateway.sn);
  } catch (error) {
    console.error(error);
  } finally {
    state.onlineDockListLoading = false;
  }
}

const fetchList = async () => {
  state.listLoading = true;
  try {
    const res = await apis.fetchJobList({
      ...state.query,
      snList: checkState.checkSnList.join(','),
      page: paginationConfig.current,
      page_size: paginationConfig.pageSize
    });
    if (res.code === 0) {
      state.list = res.data.list;
      paginationConfig.total = res.data.pagination.total
      paginationConfig.current = res.data.pagination.page
      paginationConfig.pageSize = res.data.pagination.page_size
    }
  } catch (e) {
    console.error(e);
  } finally {
    state.listLoading = false;
  }
}

onMounted(async () => {
  await fetchOnlineDock();
  await fetchList();
});

// 全选
const onCheckAllChange = async (e: any) => {
  Object.assign(checkState, {
    checkSnList: e.target.checked ? state.onlineDockList.map(item => item.gateway.sn) : [],
    indeterminate: false,
  });
  await fetchList();
}

// 点击勾选条
const onClickCheckItem = async (sn: string) => {
  const list = checkState.checkSnList;
  if (list.includes(sn)) {
    checkState.checkSnList = list.filter(item => item !== sn);
  } else {
    list.push(sn);
    checkState.checkSnList = list;
  }
  await fetchList();
}

// 机场任务弹出层-点击确定
const taskModalOnClickConfirm = async (data: any) => {
  try {
    const res = await createPlan(getWorkspaceId(), data);
    if (res.code === 0) {
      state.visible = false;
      await fetchList();
      message.success('新建成功');
    }
  } catch (error) {
    console.error(error);
  }
}

// 机场任务弹出层-点击取消
const taskModalOnClickCancel = () => {
  state.visible = false;
}

const paginationConfig = reactive({
  pageSizeOptions: ['20', '50', '100'],
  showQuickJumper: true,
  showSizeChanger: true,
  pageSize: 20,
  current: 1,
  total: 0
});

const columns = [
  {
    title: '计划｜实际时间',
    dataIndex: 'duration',
    width: 350,
    slots: { customRender: 'duration' },
  },
  {
    title: '执行状态',
    dataIndex: 'status',
    width: 100,
    slots: { customRender: 'status' },
  },
  {
    title: '任务名称',
    dataIndex: 'job_name',
    width: 150,
    ellipsis: true,
  },
  {
    title: '任务策略',
    dataIndex: 'task_type',
    width: 120,
    customRender: ({ text }: any) => {
      let content = '';
      switch (text) {
        case 0:
          content = '立即';
          break;
        case 1:
          content = '定时';
          break;
        case 2:
          content = '循环';
          break;
        default:
          break;
      }
      return content;
    }
  },
  {
    title: '航线名称',
    dataIndex: 'file_name',
    width: 150,
    ellipsis: true,
  },
  {
    title: '设备名称',
    dataIndex: 'dock_name',
    width: 200,
    ellipsis: true,
  },
  {
    title: '创建人',
    dataIndex: 'username',
    width: 150,
  },
  {
    title: '媒体上传',
    dataIndex: 'media_upload',
    width: 200,
    slots: { customRender: 'media_upload' },
  },
  {
    title: '操作',
    dataIndex: 'actions',
    fixed: 'right',
    width: 120,
    slots: { customRender: 'action' },
  },
];

const rowClassName = (record: any, index: number) => {
  const className = []
  if ((index & 1) === 0) {
    className.push('table-striped')
  }
  return className.toString().replaceAll(',', ' ')
}

const refreshData = async (page: any) => {
  paginationConfig.current = page?.current!
  paginationConfig.pageSize = page?.pageSize!
  await fetchList();
}

// 点击创建任务
const onClickCreateTask = () => {
  state.currentJobId = '';
  state.currentType = 'CREATE';
  state.visible = true
}

// 点击搜索
const onClickSearch = async (query: any) => {
  state.query = query;
  await fetchList();
}

// 点击重置
const onClickReset = async (query: any) => {
  state.query = query;
  await fetchList();
}

// 点击查看详情
const onClickLookDetail = (id: string) => {
  state.currentJobId = id;
  state.currentType = 'DETAIL';
  state.visible = true;
}

// 点击复制
const onClickCopy = (id: string) => {
  state.currentJobId = id;
  state.currentType = 'COPY';
  state.visible = true;
}

// 点击断点续飞
const onClickContinueFlight = async (id: string) => {
  try {
    const res = await apis.renewalJob(id);
    if (res.code === 0) {
      await fetchList();
      message.success('操作成功');
    }
  } catch (error) {
    console.error(error);
  }
}

// 点击删除
const onClickDelete = (id: string, name: string) => {
  Modal.confirm({
    title: '删除任务',
    content: `确定删除${name}吗？`,
    okType: 'danger',
    onOk: async () => {
      try {
        const res = await apis.deleteJob({ job_id: id });
        if (res.code === 0) {
          await fetchList();
          message.success('删除成功');
        }
      } catch (error) {
        message.error('删除失败: ' + error);
      }
    },
  })
}
</script>

<style lang="scss">
.taskList {
  padding: 20px;
  display: flex;

  &-left {
    width: 230px;
    height: calc(100vh - 146px);
    padding: 10px 8px 0;
    background-color: #232323;
    color: #FFFFFF;
    overflow-y: auto;
    margin-right: 20px;

    &-title {
      display: flex;
      justify-content: space-between;
      align-items: center;

      .ant-checkbox-wrapper {
        color: #FFFFFF !important;
      }
    }

    &-item {
      border-radius: 4px;
      border: 2px solid transparent;
      overflow: hidden;
      margin-top: 10px;

      &-selected {
        border-color: #1fa3f6;
      }
    }

    &-fill {
      width: 100%;
      height: 20px;
    }
  }
}

.ant-table {
  border-top: 1px solid rgb(0, 0, 0, 0.06);
  border-bottom: 1px solid rgb(0, 0, 0, 0.06);
}

.ant-table-tbody tr td {
  border: 0;
}

.table-striped {
  background-color: #f7f9fa;
}
</style>