// 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.

<template>
  <div>
    <!-- GPU Device Management Buttons (before tabs, for Host resource type only) -->
    <div
      v-if="resourceType === 'Host'"
      style="margin-bottom: 16px;"
    >
      <a-space wrap>
        <!-- GPU Device Discovery -->
        <a-popconfirm
          :title="$t('message.confirm.discover.gpu.devices')"
          @confirm="discoverGpuDevices"
          okText="Yes"
          cancelText="No"
        >
          <a-button type="default">
            {{ $t('label.discover.gpu.devices') }}
          </a-button>
        </a-popconfirm>

        <!-- Add GPU Device (Admin Only) -->
        <a-button
          v-if="isAdmin"
          type="primary"
          @click="showAddGpuDeviceModal"
        >
          {{ $t('label.gpu.devices.add') }}
        </a-button>
      </a-space>
    </div>

    <!-- For VMs: Show tabs only for admin, summary only for regular users -->
    <div v-if="resourceType === 'VirtualMachine' && !isAdmin">
      <!-- Summary only for non-admin users viewing VMs -->
      <GPUSummaryTab
        ref="summaryTabSimple"
        :resource="resource"
        :resourceType="resourceType"
        :loading="loading"
        @refresh="$emit('refresh')"
      />
    </div>

    <!-- For admins on VMs or all users on other resource types: Show tabs -->
    <a-tabs
      v-else
      defaultActiveKey="summary"
      :tabBarStyle="{ marginBottom: '16px' }"
    >
      <!-- Summary Tab -->
      <a-tab-pane
        key="summary"
        :tab="$t('label.gpu.summary')"
      >
        <GPUSummaryTab
          ref="summaryTab"
          :resource="resource"
          :resourceType="resourceType"
          :loading="loading"
          @refresh="$emit('refresh')"
        />
      </a-tab-pane>

      <!-- Devices Tab -->
      <a-tab-pane
        key="devices"
        :tab="$t('label.gpu.devices')"
      >
        <GPUDevicesTab
          ref="devicesTab"
          :resource="resource"
          :resourceType="resourceType"
          :loading="loading"
          @refresh="refresh(true)"
        />
      </a-tab-pane>
    </a-tabs>

    <!-- Add GPU Device Modal -->
    <a-modal
      :visible="addGpuDeviceModalVisible"
      :title="$t('label.gpu.devices.add')"
      @ok="addGpuDevice"
      @cancel="addGpuDeviceModalVisible = false"
    >
      <a-form layout="vertical">
        <a-form-item
          v-for="field in createFormFields"
          :key="field.key"
          :label="field.label"
          :required="field.required"
        >
          <!-- Input field -->
          <a-input
            v-if="field.type === 'input'"
            v-model:value="gpuDeviceForm[field.key]"
            :placeholder="field.placeholder"
          />

          <!-- Select field -->
          <a-select
            v-else-if="field.type === 'select'"
            v-model:value="gpuDeviceForm[field.key]"
            :placeholder="field.placeholder"
            :loading="field.loading"
            :show-search="field.showSearch"
            :filter-option="filterOption"
            :allow-clear="field.allowClear"
            @change="field.onChange"
          >
            <a-select-option
              v-for="option in field.options"
              :key="option.value"
              :value="option.value"
            >
              {{ option.label }}
            </a-select-option>
          </a-select>
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script>
import { getAPI, postAPI } from '@/api'
import GPUSummaryTab from '@/components/view/GPUSummaryTab'
import GPUDevicesTab from '@/components/view/GPUDevicesTab'

export default {
  name: 'GPUTab',
  components: {
    GPUSummaryTab,
    GPUDevicesTab
  },
  props: {
    resource: {
      type: Object,
      required: true
    },
    loading: {
      type: Boolean,
      required: true
    },
    resourceType: {
      type: String,
      required: true,
      default: 'Host'
    }
  },
  data () {
    return {
      addGpuDeviceModalVisible: false,
      gpuDeviceForm: {},
      gpuCards: [],
      vgpuProfiles: [],
      parentGpuDevices: [],
      loadingGpuCards: false,
      loadingVgpuProfiles: false,
      loadingParentDevices: false,
      createApiParams: {},
      createFormFields: []
    }
  },
  computed: {
    isAdmin () {
      return this.$store.getters.userInfo.roletype === 'Admin'
    }
  },
  created () {
    this.fetchApiParams()
  },
  methods: {
    discoverGpuDevices () {
      if (!this.resource.id) {
        return
      }

      getAPI('discoverGpuDevices', {
        id: this.resource.id
      }).then(() => {
        this.$notification.success({
          message: this.$t('label.success'),
          description: this.$t('message.success.discover.gpu.devices')
        })
        this.refresh()
      }).catch(error => {
        this.$notifyError(error)
      })
    },
    fetchApiParams () {
      this.createApiParams = this.$getApiParams('createGpuDevice') || {}
      this.generateFormFields()
    },
    generateFormFields () {
      const fields = []
      const fieldOrder = ['busaddress', 'gpucardid', 'vgpuprofileid', 'type', 'numanode', 'parentgpudeviceid']

      fieldOrder.forEach(paramName => {
        if (paramName === 'hostid') return // Skip hostid as it's auto-populated

        const param = this.createApiParams[paramName]
        if (!param) return

        const field = {
          key: paramName,
          label: this.$t(`label.${paramName}`),
          required: param.required || ['busaddress', 'gpucardid', 'vgpuprofileid'].includes(paramName),
          placeholder: param.description,
          type: this.getFieldType(paramName, param)
        }

        // Add special configurations for dropdown fields
        if (field.type === 'select') {
          field.options = this.getFieldOptions(paramName)
          field.loading = this.getFieldLoading(paramName)
          field.showSearch = true
          field.allowClear = false

          if (paramName === 'gpucardid') {
            field.onChange = this.onGpuCardChange
          }
        }

        fields.push(field)
      })

      this.createFormFields = fields
    },
    getFieldType (paramName, param) {
      const selectFields = ['gpucardid', 'vgpuprofileid', 'parentgpudeviceid', 'type']
      return selectFields.includes(paramName) ? 'select' : 'input'
    },
    getFieldOptions (paramName) {
      switch (paramName) {
        case 'gpucardid':
          return this.gpuCards.map(card => ({ value: card.id, label: card.name }))
        case 'vgpuprofileid':
          return this.vgpuProfiles.map(profile => ({ value: profile.id, label: profile.name }))
        case 'parentgpudeviceid':
          return this.parentGpuDevices.map(device => ({
            value: device.id,
            label: `${device.gpucardname} - ${device.busaddress}`
          }))
        case 'type':
          return [
            { value: 'PCI', label: 'PCI' },
            { value: 'MDEV', label: 'MDEV' },
            { value: 'VGPUOnly', label: 'VGPUOnly' }
          ]
        default:
          return []
      }
    },
    getFieldLoading (paramName) {
      switch (paramName) {
        case 'gpucardid':
          return this.loadingGpuCards
        case 'vgpuprofileid':
          return this.loadingVgpuProfiles
        case 'parentgpudeviceid':
          return this.loadingParentDevices
        default:
          return false
      }
    },
    onGpuCardChange (gpucardid) {
      // Clear the selected vGPU profile when GPU card changes
      this.gpuDeviceForm.vgpuprofileid = null
      // Fetch vGPU profiles for the selected GPU card
      if (gpucardid) {
        this.fetchVgpuProfiles(gpucardid)
      } else {
        this.vgpuProfiles = []
      }
    },
    fetchGpuCards () {
      this.loadingGpuCards = true
      getAPI('listGpuCards').then(json => {
        this.gpuCards = json?.listgpucardsresponse?.gpucard || []
        this.generateFormFields() // Refresh form fields with new data
      }).catch(error => {
        this.$notifyError(error)
      }).finally(() => {
        this.loadingGpuCards = false
      })
    },
    fetchVgpuProfiles (gpucardid = null) {
      this.loadingVgpuProfiles = true
      const params = {}
      if (gpucardid) {
        params.gpucardid = gpucardid
      }
      getAPI('listVgpuProfiles', params).then(json => {
        this.vgpuProfiles = json?.listvgpuprofilesresponse?.vgpuprofile || []
        this.generateFormFields() // Refresh form fields with new data
      }).catch(error => {
        this.$notifyError(error)
      }).finally(() => {
        this.loadingVgpuProfiles = false
      })
    },
    fetchParentGpuDevices () {
      if (!this.resource.id || this.resourceType !== 'Host') {
        return
      }
      this.loadingParentDevices = true
      getAPI('listGpuDevices', { hostid: this.resource.id }).then(json => {
        const devices = json?.listgpudevicesresponse?.gpudevice || []
        // Only include devices that can be parent devices (not virtual GPU devices)
        this.parentGpuDevices = devices.filter(device => !device.parentgpudeviceid)
        this.generateFormFields() // Refresh form fields with new data
      }).catch(error => {
        this.$notifyError(error)
      }).finally(() => {
        this.loadingParentDevices = false
      })
    },
    filterOption (input, option) {
      return option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },
    showAddGpuDeviceModal () {
      this.gpuDeviceForm = {
        type: 'PCI' // Set default type
      }
      this.vgpuProfiles = [] // Clear profiles initially
      this.fetchGpuCards()
      this.fetchParentGpuDevices()
      this.addGpuDeviceModalVisible = true
    },
    addGpuDevice () {
      // Validate required fields
      if (!this.gpuDeviceForm.busaddress || !this.gpuDeviceForm.gpucardid || !this.gpuDeviceForm.vgpuprofileid) {
        this.$notification.warning({
          message: this.$t('label.warning'),
          description: this.$t('message.please.fill.required.fields')
        })
        return
      }

      const params = {
        hostid: this.resource.id,
        busaddress: this.gpuDeviceForm.busaddress,
        gpucardid: this.gpuDeviceForm.gpucardid,
        vgpuprofileid: this.gpuDeviceForm.vgpuprofileid
      }

      // Add optional parameters only if they have values
      if (this.gpuDeviceForm.type) {
        params.type = this.gpuDeviceForm.type
      }
      if (this.gpuDeviceForm.numanode) {
        params.numanode = this.gpuDeviceForm.numanode
      }
      if (this.gpuDeviceForm.parentgpudeviceid) {
        params.parentgpudeviceid = this.gpuDeviceForm.parentgpudeviceid
      }

      postAPI('createGpuDevice', params).then(() => {
        this.$notification.success({
          message: this.$t('label.success'),
          description: this.$t('message.success.add.gpu.device')
        })
        this.addGpuDeviceModalVisible = false
        this.refresh()
      }).catch(error => {
        this.$notifyError(error)
      })
    },
    refresh (skipDevicesTab = false) {
      // Refresh summary tabs
      const summaryTab = this.$refs.summaryTab || this.$refs.summaryTabSimple
      if (summaryTab?.refresh) {
        summaryTab.refresh()
      }
      // Refresh devices tab only if not skipped
      if (!skipDevicesTab && this.$refs.devicesTab?.refresh) {
        this.$refs.devicesTab.refresh()
      }
      // Emit refresh to parent
      this.$emit('refresh')
    }
  }
}
</script>

<style scoped>
/* Background colors for GPU device types */
:deep(.parent-gpu-row) {
  background-color: #fafafa;
}

:deep(.vgpu-row) {
  background-color: #f0f8ff;
}

:deep(.parent-gpu-row:hover) {
  background-color: #f5f5f5 !important;
}

:deep(.vgpu-row:hover) {
  background-color: #e6f4ff !important;
}

/* Text truncation for long names */
:deep(.ant-table-tbody .ant-table-cell) {
  max-width: 200px;
}

:deep(.ant-table-tbody .ant-table-cell:has([data-column="gpucardname"]),
  .ant-table-tbody .ant-table-cell:has([data-column="vgpuprofilename"]),
  .ant-table-tbody .ant-table-cell:has([data-column="hostname"])) {
  max-width: 150px;
}

.text-ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
  display: inline-block;
}
</style>
