<template>
  <div class="app-center">
    <div class="app-center-title">应用中心</div>
    <div class="app-center-operation">
      <tiny-button class="add-app" @click="creatApp()"> <svg-icon name="add"></svg-icon>创建应用 </tiny-button>
      <div class="app-center-filter">
        <tiny-select v-model="state.appFilter" :options="appFilterOptions" @change="getApplicationList"></tiny-select>
        <tiny-select v-model="state.orderBy" :options="appOrderByOptions" @change="getApplicationList"></tiny-select>
        <tiny-search
          class="app-center-search"
          v-model="state.appSearchKey"
          clearable
          placeholder="输入关键字搜索、过滤"
          @search="getApplicationList"
          is-enter-search
        >
          <template #prefix> <tiny-icon-search /> </template>
        </tiny-search>
        <div class="type-toolbar">
          <span
            v-for="item in arrangeOptions"
            :key="item.id"
            :class="['icon-wrap', { active: state.type === item.id }]"
            @click="typeClick(item.id)"
          >
            <svg-icon :name="item.assetsUrl"></svg-icon>
          </span>
        </div>
      </div>
    </div>
    <div class="app-center-list">
      <div class="list-wrap">
        <div class="list" v-if="state.type === 'default'">
          <template v-for="item in appList" :key="item.id">
            <div class="item">
              <div class="app-name">
                <svg-icon :name="item.assetsUrl || 'template-cover-1'" class="app-img"></svg-icon>
                <div class="app-name-content">
                  <div class="app-name-text">{{ item.name }}</div>
                  <div class="app-desc">{{ item.description }}</div>
                </div>
              </div>
              <div class="app-operation">
                <div class="option" @click="openApplication(item)">
                  <svg-icon name="cloud-shell"></svg-icon>
                  <span class="option-text">开发应用</span>
                </div>
                <tiny-divider direction="vertical"></tiny-divider>
                <div class="option" @click="handleDelete(item)">
                  <svg-icon name="delete"></svg-icon>
                  <span class="option-text">删除应用</span>
                </div>
              </div>
            </div>
          </template>
        </div>
        <tiny-grid ref="gridRef" class="table" v-if="state.type === 'table' && appList.length" :data="appList">
          <tiny-grid-column field="name" title="应用名称" show-overflow>
            <template #default="data">
              <div class="app-name">
                <svg-icon :name="data.row.assetsUrl || 'template-cover-1'" class="app-img"></svg-icon>
                <span>{{ data.row.name }}</span>
              </div>
            </template>
          </tiny-grid-column>
          <tiny-grid-column field="created_at" title="创建时间" show-overflow></tiny-grid-column>
          <tiny-grid-column field="createdBy" title="创建人" show-overflow></tiny-grid-column>
          <tiny-grid-column field="description" title="应用描述" show-overflow></tiny-grid-column>
          <tiny-grid-column width="180" field="operation" title="操作">
            <template #default="data">
              <tiny-button type="text" @click="openApplication(data.row)"> 开发应用 </tiny-button>
              <tiny-button type="text" @click="handleDelete(data.row)"> 删除应用 </tiny-button>
            </template>
          </tiny-grid-column>
        </tiny-grid>
        <search-empty :isShow="!appList.length" />
      </div>
      <tiny-pager
        v-if="state.total > state.pageSize"
        mode="number"
        :current-page="state.currentPage"
        :page-size="state.pageSize"
        :page-sizes="state.pageSizes"
        :total="state.total"
        @size-change="pageSizeChange"
        @current-change="currentChange"
      ></tiny-pager>
    </div>
    <app-dialog v-model:visible="state.appVisible" @confirm="confirmApp"></app-dialog>
  </div>
</template>

<script>
import { reactive, ref, onMounted } from 'vue'
import { Button, Select, Pager, Grid, GridColumn, Divider, Search, Modal, Notify } from '@opentiny/vue'
import { iconSearch } from '@opentiny/vue-icon'
import { SearchEmpty } from '@opentiny/tiny-engine-common'
import { getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register'
import AppDialog from './AppDialog.vue'
import { fetchApplicationList, createApplication, updateApplication, deleteApplication } from './js/http'

export default {
  components: {
    TinyButton: Button,
    TinySelect: Select,
    TinyPager: Pager,
    TinyGrid: Grid,
    TinyGridColumn: GridColumn,
    TinyDivider: Divider,
    TinySearch: Search,
    SearchEmpty,
    TinyIconSearch: iconSearch(),
    AppDialog
  },

  setup() {
    const { getUserInfo } = getMetaApi(META_SERVICE.GlobalService)
    const appList = ref([])

    const appFilterOptions = [
      {
        label: '全部应用',
        value: 'all'
      },
      {
        label: '我的应用',
        value: 'my'
      }
    ]

    const appOrderByOptions = [
      {
        label: '按创建时间排序',
        value: 'created_time'
      },
      {
        label: '按最近更新时间排序',
        value: 'last_updated_time'
      }
    ]

    const arrangeOptions = [
      {
        id: 'default',
        name: '栅格',
        assetsUrl: 'workspace-icon-application-center'
      },
      {
        id: 'table',
        name: '列表',
        assetsUrl: 'small-list'
      }
    ]

    const queryParams = new URLSearchParams(location.search)

    const state = reactive({
      appFilter: 'all',
      orderBy: 'created_time',
      appSearchKey: '',
      type: 'default',
      total: 0,
      pageSize: 10,
      currentPage: 1,
      pageSizes: [10, 20, 30, 40],
      appVisible: false
    })

    const getApplicationList = () => {
      const info = getUserInfo()
      const params = {
        currentPage: state.currentPage,
        pageSize: state.pageSize,
        name: state.appSearchKey,
        createdBy: state.appFilter === 'all' ? '' : info.id
      }
      if (state.orderBy === 'last_updated_time') {
        params.orderBy = state.orderBy
      }
      fetchApplicationList(Object.fromEntries(Object.entries(params).filter(([, value]) => !!value))).then((res) => {
        appList.value = res.apps || []
        state.total = res.total
      })
    }

    const creatApp = () => {
      state.appVisible = true
    }

    const handleDelete = (template) => {
      Modal.confirm({
        message: '即将删除应用,删除后不可恢复,请谨慎操作。',
        title: '删除应用'
      }).then((res) => {
        if (res === 'confirm') {
          deleteApplication(template.id)
            .then(() => {
              getApplicationList()
            })
            .catch((error) => {
              Notify({
                type: 'error',
                message: error,
                position: 'top-right',
                duration: 5000
              })
            })
        }
      })
    }

    const openApplication = (template) => {
      const href = window.location.href.split('?')[0] || './'
      const newUrl = `${href}?type=app&id=${template.id}&tenant=${template.tenantId || queryParams.get('tenant')}`
      if (window.self !== window.top) {
        window.parent.postMessage(
          {
            type: 'openNewTab',
            url: newUrl
          },
          '*'
        )
      } else {
        window.open(newUrl)
      }
    }

    const typeClick = (type) => {
      state.type = type
    }

    const pageSizeChange = (val) => {
      state.pageSize = val
      state.currentPage = 1
      getApplicationList()
    }

    const currentChange = (val) => {
      state.currentPage = val
      getApplicationList()
    }

    const confirmApp = (formData) => {
      if (formData?.id) {
        const updateId = formData.id
        delete formData.id
        updateApplication(updateId, formData)
          .then(() => {
            Notify({
              type: 'success',
              message: '应用更新成功',
              position: 'top-right',
              duration: 5000
            })
            getApplicationList()
          })
          .catch((error) => {
            Notify({
              type: 'error',
              message: error,
              position: 'top-right',
              duration: 5000
            })
          })
      } else {
        createApplication(formData)
          .then(() => {
            Notify({
              type: 'success',
              message: '应用创建成功',
              position: 'top-right',
              duration: 5000
            })
            getApplicationList()
          })
          .catch((error) => {
            Notify({
              type: 'error',
              message: error,
              position: 'top-right',
              duration: 5000
            })
          })
      }
    }

    onMounted(() => {
      getApplicationList()
    })

    return {
      state,
      appList,
      appFilterOptions,
      appOrderByOptions,
      arrangeOptions,
      creatApp,
      getApplicationList,
      typeClick,
      handleDelete,
      openApplication,
      confirmApp,
      pageSizeChange,
      currentChange
    }
  }
}
</script>

<style lang="less" scoped>
.app-center {
  padding: 24px;
  background: var(--te-template-common-bg-color);
  height: -webkit-fill-available;
  .app-center-title {
    font-size: 20px;
    font-weight: 600;
  }
  .app-center-operation {
    margin: 24px 0 20px;
    display: flex;
    justify-content: space-between;
  }
  .app-center-filter {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .app-center-search {
    min-width: 300px;
  }
  .type-toolbar {
    display: flex;
    border-radius: 4px;
    background-color: var(--te-template-app-center-btn-bg-color);
    .icon-wrap {
      width: 24px;
      height: 24px;
      color: var(--te-template-app-center-btn-icon-color);
      font-size: 16px;
      cursor: pointer;
      display: inline-flex;
      justify-content: center;
      align-items: center;
      transition: 0.3s;
      &.active {
        border: 1px solid var(--te-template-app-center-btn-border-color-active);
        color: var(--te-template-app-center-btn-color-active);
        border-radius: 4px;
        background-color: var(--te-template-app-center-btn-bg-color-active);
      }
    }
  }
  .app-center-list {
    height: calc(100vh - 200px);
  }
}
.list {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  .item {
    width: 252px;
    padding: 24px 24px 12px;
    border-radius: 8px;
    border: 1px solid var(--te-template-app-center-item-border-color);
    position: relative;
    &:hover {
      border-color: var(--te-template-app-center-item-border-color-hover);
    }
    .app-name {
      display: flex;
      gap: 16px;
      .app-img {
        width: 48px;
        height: 48px;
      }
      .app-name-content {
        width: calc(100% - 64px);
        .app-name-text {
          font-size: 18px;
          font-weight: 600;
          line-height: 28px;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
        .app-desc {
          margin-top: 4px;
          font-size: 12px;
          line-height: 18px;
          color: var(--te-template-center-common-item-desc-text-color);
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
      }
    }
    .app-operation {
      display: flex;
      align-items: center;
      gap: 16px;
      padding-top: 12px;
      margin-top: 16px;
      border-top: 1px dashed var(--te-template-app-center-item-border-color);
      .option {
        display: flex;
        align-items: center;
        gap: 6px;
        cursor: pointer;
        &:hover {
          .option-text {
            text-decoration: underline;
          }
        }
      }
    }
  }
}
.table {
  .app-name {
    display: flex;
    gap: 8px;
    align-items: center;
    .app-img {
      width: 24px;
      height: 24px;
    }
  }

  .tiny-button.tiny-button--text {
    padding-left: 0;
  }
}

.list-wrap {
  margin-bottom: 12px;
  max-height: calc(100% - 80px);
  overflow: auto;
  .empty-wrap {
    width: 100%;
  }
}
.options {
  .option {
    padding: 4px 16px;
    cursor: pointer;
    &:hover {
      background: var(--te-template-common-bg-color-hover);
    }
  }
}
</style>