<template>
  <div class="dev-page">
    <div class="page-toolbar">
      <div class="toolbar-left">
        <a-select v-model:value="selectedAppId" placeholder="全部应用" allow-clear style="width: 180px" @change="loadList">
          <a-select-option v-for="app in appOptions" :key="app.productId" :value="app.productId">{{ app.productName }}</a-select-option>
        </a-select>
        <PermissionGuard :app-id="selectedAppId" permission="canEditResource" :show-tip="true">
          <a-button type="primary" @click="showAdd = true">
            <template #icon><PlusOutlined /></template>
            添加存储桶
          </a-button>
        </PermissionGuard>
      </div>
      <div class="toolbar-right">
        <a-input-search
          v-model:value="searchText"
          placeholder="搜索存储桶名称"
          style="width: 240px"
          @search="loadList"
        />
      </div>
    </div>

    <div class="notice-bar">
      <InfoCircleOutlined class="notice-icon" />
      <span>在此管理云对象存储（OSS/COS）存储桶，将文件存储资源关联到对应应用。</span>
    </div>

    <a-table
      :columns="columns"
      :data-source="list"
      :loading="loading"
      :pagination="pagination"
      row-key="resourceId"
      @change="handleTableChange"
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="getStatusColor(record.status)">
            {{ getStatusText(record.status) }}
          </a-tag>
          <div v-if="record.status === 'failed' && record.remark" style="font-size: 12px; color: #ff4d4f;">
            {{ record.remark }}
          </div>
        </template>
        <template v-if="column.key === 'acl'">
          <a-tag :color="record.acl === 'public-read' ? 'green' : 'default'">
            {{ record.acl === 'public-read' ? '公开读' : '私有' }}
          </a-tag>
        </template>
        <template v-if="column.key === 'usedBytes'">
          {{ formatSize(record.usedBytes) }}
        </template>
        <template v-if="column.key === 'action'">
          <a-space>
            <a-button type="link" size="small" @click="handleRefresh(record)">
              <template #icon><ReloadOutlined /></template>
              刷新
            </a-button>
            <a-button v-if="record.isOwner || getAppPermission(record.appId)?.canEditResource" type="link" size="small" @click="handleEdit(record)">编辑</a-button>
            <a-divider v-if="record.isOwner || getAppPermission(record.appId)?.canEditResource" type="vertical" />
            <a-popconfirm v-if="record.isOwner || getAppPermission(record.appId)?.canEditResource" title="确定要移除此存储桶？" @confirm="handleDelete(record.resourceId)">
              <a-button type="link" size="small" danger>移除</a-button>
            </a-popconfirm>
            <span v-if="!record.isOwner && !getAppPermission(record.appId)?.canEditResource" style="font-size: 12px; color: #faad14;">
              <LockOutlined /> 只读
            </span>
          </a-space>
        </template>
      </template>
    </a-table>

    <a-modal
      v-model:open="showAdd"
      :title="editRecord ? '编辑存储桶' : '添加存储桶'"
      ok-text="保存"
      cancel-text="取消"
      :confirm-loading="saveLoading"
      @ok="handleSave"
      @cancel="resetForm"
    >
      <a-form ref="formRef" :model="form" :rules="rules" layout="vertical" style="margin-top: 8px">
        <a-form-item label="存储桶名称" name="name">
          <a-input v-model:value="form.name" placeholder="如：assets-bucket" :disabled="!!editRecord" />
        </a-form-item>
        <a-form-item label="服务商" name="provider">
          <a-select v-model:value="form.provider" placeholder="请选择" :disabled="!!editRecord" @change="handleProviderChange">
            <a-select-option v-for="opt in providerOptions" :key="opt.value" :value="opt.value">
              {{ opt.label }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="云账号凭证" name="credentialId">
          <a-select v-model:value="form.credentialId" placeholder="请先选择服务商" :disabled="!!editRecord" allow-clear>
            <a-select-option v-for="cred in credentialOptions" :key="cred.id" :value="cred.id">
              {{ cred.name }} ({{ cred.accessKeyId?.slice(0, 8) }}***)
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="所在地区" name="region">
          <a-select
            v-model:value="form.region"
            placeholder="请选择地区"
            show-search
            :filter-option="(input, option) => option.label.toLowerCase().includes(input.toLowerCase())"
            allow-clear
            :disabled="!!editRecord"
          >
            <a-select-option v-for="opt in getRegionOptions(form.provider)" :key="opt.value" :value="opt.value">
              {{ opt.label }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="访问权限" name="acl">
          <a-radio-group v-model:value="form.acl">
            <a-radio value="public-read">公开读</a-radio>
            <a-radio value="private">私有</a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item label="关联应用" name="appId">
          <a-select v-model:value="form.appId" placeholder="可选，关联到应用" allow-clear>
            <a-select-option v-for="app in appOptions" :key="app.productId" :value="app.productId">
              {{ app.productName }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="备注" name="remark">
          <a-textarea v-model:value="form.remark" :rows="2" placeholder="可选备注" />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- 删除确认弹窗 -->
    <a-modal
      v-model:open="showVerifyDelete"
      title="确认删除"
      ok-text="确认删除"
      cancel-text="取消"
      :confirm-loading="deleteLoading"
      @ok="confirmDelete"
    >
      <div style="text-align: center; padding: 16px 0;">
        <p style="margin-bottom: 16px; color: #ff4d4f; font-size: 14px;">
          <ExclamationCircleOutlined /> 此操作不可恢复，请谨慎操作！
        </p>
        <p style="margin-bottom: 8px;">请输入手机验证码确认删除</p>
        <p style="margin-bottom: 16px; font-size: 12px; color: #666;">
          验证码将发送至测试手机号：13737128880
        </p>
        <div style="display: flex; gap: 8px; justify-content: center;">
          <a-input
            v-model:value="verifyCode"
            placeholder="请输入验证码"
            style="width: 120px;"
            @pressEnter="confirmDelete"
          />
          <a-button @click="sendVerifyCode" :disabled="verifyCountdown > 0">
            {{ verifyCountdown > 0 ? `${verifyCountdown}s` : '发送验证码' }}
          </a-button>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, InfoCircleOutlined, LockOutlined, ReloadOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { pageAppResource, addAppResource, updateAppResource, removeAppResource, refreshStorage } from '@/api/app/appResource'
import { getMyAccessibleApps, getAppProduct } from '@/api/app/appProduct'
import { sendSmsCaptcha } from '@/api/passport/login'
import { useAppPermission } from '@/composables/useAppPermission'
import PermissionGuard from '@/components/developer/PermissionGuard.vue'
import { pageCloudCredential } from '@/api/app/cloudCredential'
import type { AppResource } from '@/api/app/appResource/model'
import type { AppCloudCredential } from '@/api/app/cloudCredential/model'
import { enrichResourcesWithPermission } from '@/composables/useResourceAccess'

definePageMeta({ layout: 'developer' })
useHead({ title: '云存储管理 - 开发者中心' })

const loading = ref(false)
const saveLoading = ref(false)
const showAdd = ref(false)
const searchText = ref('')
const editRecord = ref<any>(null)
const formRef = ref()
const selectedAppId = ref<number | undefined>(undefined)
const { getAppPermission } = useAppPermission()

const form = reactive({
  name: '',
  provider: undefined as string | undefined,
  credentialId: undefined as number | undefined,
  region: '',
  acl: 'private',
  appId: undefined as number | undefined,
  remark: '',
})

const rules = {
  name: [{ required: true, message: '请输入存储桶名称' }],
  provider: [{ required: true, message: '请选择服务商' }],
  credentialId: [{ required: true, message: '请选择云账号凭证' }],
  region: [{ required: true, message: '请输入所在地区' }],
}

const columns = [
  { title: '存储桶名称', dataIndex: 'name', key: 'name', width: 150 },
  { title: '服务商', dataIndex: 'provider', key: 'provider', width: 100, customRender: ({ record }) => getProviderLabel(record.provider) },
  { title: '地区', dataIndex: 'region', key: 'region', width: 140, customRender: ({ record }) => getRegionLabel(record.provider, record.region) },
  { title: '状态', dataIndex: 'status', key: 'status', width: 90 },
  { title: '访问权限', dataIndex: 'acl', key: 'acl', width: 80 },
  { title: '已用空间', dataIndex: 'usedBytes', key: 'usedBytes', width: 90 },
  { title: '对象数', dataIndex: 'usedCount', key: 'objectCount', width: 70 },
  // { title: '关联应用', dataIndex: 'appName', key: 'appName', width: 120 },
  { title: '操作', key: 'action', width: 100 },
]

// 获取服务商显示标签
function getProviderLabel(provider: string): string {
  const map: Record<string, string> = {
    aliyun: '阿里云',
    tencent: '腾讯云',
    huawei: '华为云',
    qiniu: '七牛云',
  }
  return map[provider] || provider
}

// 获取地区显示标签
function getRegionLabel(provider: string, region: string): string {
  if (!region) return '-'
  const opts = getRegionOptions(provider)
  const found = opts.find(o => o.value === region)
  return found?.label || region
}

const pagination = reactive({ current: 1, pageSize: 10, total: 0 })
const list = ref<AppResource[]>([])
const appOptions = ref<any[]>([])
const credentialOptions = ref<AppCloudCredential[]>([])

// 服务商选项
const providerOptions = [
  { label: '☁️ 阿里云 OSS', value: 'aliyun' },
  { label: '🔵 腾讯云 COS', value: 'tencent' },
  { label: '🟠 华为云 OBS', value: 'huawei' },
  { label: '🟡 七牛云 Kodo', value: 'qiniu' },
]

// 阿里云 OSS 地区选项
const aliyunRegions = [
  { label: '华东 1（杭州）', value: 'oss-cn-hangzhou' },
  { label: '华东 2（上海）', value: 'oss-cn-shanghai' },
  { label: '华南 1（深圳）', value: 'oss-cn-shenzhen' },
  { label: '华南 2（广州）', value: 'oss-cn-guangzhou' },
  { label: '华北 2（北京）', value: 'oss-cn-beijing' },
  { label: '华北 3（张家口）', value: 'oss-cn-zhangjiakou' },
  { label: '华北 5（呼和浩特）', value: 'oss-cn-huhehaote' },
  { label: '西南 1（成都）', value: 'oss-cn-chengdu' },
  { label: '香港', value: 'oss-cn-hongkong' },
  { label: '新加坡', value: 'oss-ap-southeast-1' },
  { label: '日本（东京）', value: 'oss-ap-northeast-1' },
  { label: '韩国（首尔）', value: 'oss-ap-northeast-2' },
  { label: '美国（弗吉尼亚）', value: 'oss-us-east-1' },
  { label: '美国（硅谷）', value: 'oss-us-west-1' },
  { label: '德国（法兰克福）', value: 'oss-eu-central-1' },
  { label: '英国（伦敦）', value: 'oss-eu-west-1' },
]

// 腾讯云 COS 地区选项
const tencentRegions = [
  { label: '华北地区（北京）', value: 'ap-beijing' },
  { label: '华南地区（广州）', value: 'ap-guangzhou' },
  { label: '华南地区（深圳）', value: 'ap-shenzhen' },
  { label: '华东地区（上海）', value: 'ap-shanghai' },
  { label: '西南地区（成都）', value: 'ap-chengdu' },
  { label: '西南地区（重庆）', value: 'ap-chongqing' },
  { label: '港澳台地区（香港）', value: 'ap-hongkong' },
  { label: '亚太东南（新加坡）', value: 'ap-singapore' },
  { label: '亚太东南（曼谷）', value: 'ap-bangkok' },
  { label: '亚太南部（孟买）', value: 'ap-mumbai' },
  { label: '亚太东北（东京）', value: 'ap-tokyo' },
  { label: '美国东部（弗吉尼亚）', value: 'na-ashburn' },
  { label: '美国西部（硅谷）', value: 'na-siliconvalley' },
  { label: '欧洲地区（法兰克福）', value: 'eu-frankfurt' },
  { label: '欧洲地区（伦敦）', value: 'eu-london' },
]

// 华为云 OBS 地区选项
const huaweiRegions = [
  { label: '华北-北京一', value: 'cn-north-1' },
  { label: '华北-北京四', value: 'cn-north-4' },
  { label: '华东-上海一', value: 'cn-east-2' },
  { label: '华南-广州', value: 'cn-south-1' },
  { label: '西南-贵阳一', value: 'cn-southwest-2' },
  { label: '香港', value: 'cn-hongkong' },
  { label: '亚太-新加坡', value: 'ap-southeast-1' },
  { label: '亚太-曼谷', value: 'ap-southeast-2' },
  { label: '非洲-约翰内斯堡', value: 'af-south-1' },
  { label: '欧洲-巴黎', value: 'eu-west-1' },
  { label: '欧洲-法兰克福', value: 'eu-central-1' },
  { label: '拉美-圣保罗', value: 'sa-brazil-1' },
]

// 根据服务商获取地区选项
function getRegionOptions(provider: string) {
  if (provider === 'aliyun') return aliyunRegions
  if (provider === 'tencent') return tencentRegions
  if (provider === 'huawei') return huaweiRegions
  return []
}

// 加载云账号凭证列表
async function loadCredentials(provider?: string) {
  try {
    const result = await pageCloudCredential({ provider, page: 1, limit: 100 })
    credentialOptions.value = result.list || []
  } catch {
    credentialOptions.value = []
  }
}

function formatSize(bytes: number): string {
  if (!bytes) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`
}

function getStatusColor(status: string): string {
  if (status === 'running') return 'success'
  if (status === 'pending') return 'processing'
  if (status === 'failed') return 'error'
  return 'default'
}

function getStatusText(status: string): string {
  if (status === 'running') return '运行中'
  if (status === 'pending') return '创建中'
  if (status === 'failed') return '创建失败'
  return status || '未知'
}

// 选择服务商后加载对应凭证
function handleProviderChange(provider: string) {
  form.credentialId = undefined
  if (provider) {
    loadCredentials(provider)
  } else {
    credentialOptions.value = []
  }
}

// 加载应用下拉列表（仅当前用户可访问的应用）
async function loadAppOptions() {
  try {
    appOptions.value = await getMyAccessibleApps()
  }
  catch {
    appOptions.value = []
  }
}

async function loadList() {
  loading.value = true
  try {
    const result = await pageAppResource({
      resourceType: 'storage',
      keywords: searchText.value || undefined,
      appId: selectedAppId.value,
      page: pagination.current,
      limit: pagination.pageSize,
    })
    list.value = enrichResourcesWithPermission(result?.list ?? [])
    pagination.total = result?.count ?? 0
  }
  catch (e: any) {
    message.error(e.message || '加载失败')
  }
  finally {
    loading.value = false
  }
}

function handleTableChange(pag: any) {
  pagination.current = pag.current
  loadList()
}

function handleEdit(record: AppResource) {
  if (!record.isOwner) {
    message.warning('只有资源创建者才能编辑')
    return
  }
  editRecord.value = record
  // 先加载对应服务商的凭证
  if (record.provider) {
    loadCredentials(record.provider)
  }
  Object.assign(form, {
    name: record.name,
    provider: record.provider,
    credentialId: record.credentialId ? Number(record.credentialId) : undefined,
    region: record.region,
    acl: record.acl || 'private',
    appId: record.appId ? Number(record.appId) : undefined,
    remark: record.remark,
    resourceId: record.resourceId,
  })
  showAdd.value = true
}

// 删除存储桶（需要验证码）
const showVerifyDelete = ref(false)
const verifyResourceId = ref<number>(0)
const verifyCode = ref('')
const verifyTargetPhone = ref('')
const verifyTargetUser = ref('')

async function handleDelete(resourceId: number) {
  const item = list.value.find(r => r.resourceId === resourceId)
  if (item && !item.isOwner) {
    message.warning('只有资源创建者才能删除')
    return
  }
  // 确认删除操作
  showVerifyDelete.value = true
  verifyResourceId.value = resourceId
  verifyCode.value = ''
  verifyTargetPhone.value = ''
  verifyTargetUser.value = ''

  // 获取应用创建者信息
  if (item?.appId) {
    try {
      const app = await getAppProduct(item.appId)
      if (app?.developerPhone) {
        verifyTargetPhone.value = app.developerPhone
        verifyTargetUser.value = app.developer || '应用创建者'
      }
    }
    catch {
      // 静默失败，后续会检查手机号
    }
  }
}

const deleteLoading = ref(false)
const verifyCountdown = ref(0)

async function sendVerifyCode() {
  if (verifyCountdown.value > 0) return
  try {
    // 测试阶段：验证码发送给固定手机号
    const phone = '13737128880'
    await sendSmsCaptcha({ phone })
    message.success('验证码已发送（测试手机号：13737128880）')
    verifyCountdown.value = 60
    const timer = setInterval(() => {
      verifyCountdown.value--
      if (verifyCountdown.value <= 0) clearInterval(timer)
    }, 1000)
  }
  catch (e: any) {
    message.error(e.message || '发送失败')
  }
}

async function confirmDelete() {
  if (!verifyCode.value) {
    message.warning('请输入短信验证码')
    return
  }
  deleteLoading.value = true
  try {
    await removeAppResource(verifyResourceId.value, verifyCode.value)
    message.success('已移除')
    showVerifyDelete.value = false
    loadList()
  }
  catch (e: any) {
    message.error(e.message || '删除失败')
  }
  finally {
    deleteLoading.value = false
  }
}

async function handleRefresh(record: AppResource) {
  try {
    const result = await refreshStorage(record.resourceId!)
    // 更新本地数据
    const index = list.value.findIndex(r => r.resourceId === record.resourceId)
    if (index !== -1) {
      list.value[index].usedBytes = result.usedBytes
      list.value[index].usedCount = result.objectCount
    }
    message.success('刷新成功')
  }
  catch (e: any) {
    message.error(e.message || '刷新失败')
  }
}

async function handleSave() {
  await formRef.value?.validate()
  saveLoading.value = true
  try {
    const payload: AppResource = {
      resourceType: 'storage',
      name: form.name,
      provider: form.provider,
      credentialId: form.credentialId ? Number(form.credentialId) : undefined,
      region: form.region,
      acl: form.acl,
      appId: form.appId ? Number(form.appId) : undefined,
      remark: form.remark,
    }
    if (editRecord.value) {
      payload.resourceId = editRecord.value.resourceId
      await updateAppResource(payload)
      message.success('保存成功')
    }
    else {
      await addAppResource(payload)
      message.success('添加成功，存储桶正在创建中...')
    }
    showAdd.value = false
    resetForm()
    loadList()
  }
  catch (e: any) {
    message.error(e.message || '操作失败')
  }
  finally {
    saveLoading.value = false
  }
}

function resetForm() {
  editRecord.value = null
  formRef.value?.resetFields()
  Object.assign(form, { name: '', provider: undefined, credentialId: undefined, region: '', acl: 'private', appId: undefined, remark: '' })
}

onMounted(() => {
  loadAppOptions()
  loadList()
})
</script>

<style scoped>
.dev-page { padding: 24px; max-width: 1100px; }
.page-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.toolbar-left { display: flex; align-items: center; gap: 12px; }
.toolbar-right { display: flex; gap: 8px; }
.notice-bar {
  display: flex; align-items: center; gap: 8px;
  background: #e6f4ff; border: 1px solid #91caff;
  border-radius: 6px; padding: 8px 14px; margin-bottom: 16px;
  font-size: 13px; color: #1677ff;
}
.notice-icon { font-size: 15px; }
</style>
