<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
import api from '@/api/client'
import PageHeader from '@/components/PageHeader.vue'
import AppCard from '@/components/AppCard.vue'

const { t } = useI18n()

interface ProxyNode {
  id: number
  name: string
  runtime_name: string
  type: string
  source: string
  enabled: boolean
  country: string
  latency_ms: number
  alive: boolean
}

interface CountryStat {
  code: string
  name: string
  count: number
}

const items = ref<ProxyNode[]>([])
const countries = ref<CountryStat[]>([])
const total = ref(0)
const loading = ref(false)
const activeTab = ref('all')
const countryFilter = ref('')
const page = ref(1)
const pageSize = ref(50)
const testing = ref(false)
const testProgress = ref('')
const testCancel = ref(false)
const dialogVisible = ref(false)
const saving = ref(false)
const form = ref({ name: '', type: 'socks5', server: '', port: 1080, username: '', password: '' })

const importVisible = ref(false)
const importMode = ref<'append' | 'replace'>('append')
const importText = ref('')
const importing = ref(false)
const exportLoading = ref(false)

const testable = computed(() => items.value.filter(i => i.enabled))

function sourceParam() {
  if (activeTab.value === 'manual') return 'manual'
  if (activeTab.value === 'subscription') return 'subscription'
  return ''
}

function onFilterChange() {
  page.value = 1
  load()
}

async function load() {
  loading.value = true
  try {
    const [proxies, countryRes] = await Promise.all([
      api.get('/proxies', {
        params: {
          source: sourceParam() || undefined,
          country: countryFilter.value || undefined,
          limit: pageSize.value,
          offset: (page.value - 1) * pageSize.value,
        },
      }),
      api.get('/countries'),
    ])
    items.value = proxies.data.items || []
    total.value = proxies.data.total || 0
    countries.value = countryRes.data.items || []
  } finally {
    loading.value = false
  }
}

function countryLabel(code: string) {
  if (!code) return t('common.unknown')
  const hit = countries.value.find(c => c.code === code)
  return hit ? hit.name : code
}

function latencyClass(ms: number) {
  if (ms < 0) return 'latency-dead'
  if (ms < 200) return 'latency-good'
  if (ms < 500) return 'latency-warn'
  return 'latency-bad'
}

async function rebuildCountries() {
  const { data } = await api.post('/proxies/rebuild-countries')
  ElMessage.success(t('proxies.countriesRebuilt', { n: data.updated }))
  load()
}

async function testOne(row: ProxyNode) {
  const { data } = await api.post(`/proxies/${row.id}/test`, {}, { timeout: 12000 })
  row.latency_ms = data.latency_ms
  row.alive = data.alive
  if (data.error) {
    throw new Error(data.error)
  }
}

function cancelTest() {
  testCancel.value = true
}

async function testAll() {
  const list = testable.value
  if (!list.length) {
    ElMessage.info(t('proxies.noTestable'))
    return
  }
  testing.value = true
  testCancel.value = false
  let failed = 0
  try {
    for (let i = 0; i < list.length; i++) {
      if (testCancel.value) {
        ElMessage.warning(t('proxies.testCancelled'))
        break
      }
      const row = list[i]
      testProgress.value = `${i + 1}/${list.length}`
      try {
        await testOne(row)
      } catch {
        failed++
      }
    }
    if (!testCancel.value) {
      ElMessage.success(failed ? t('proxies.testDoneFailed', { n: failed }) : t('proxies.testDone'))
    }
  } finally {
    testing.value = false
    testProgress.value = ''
  }
}

function openCreate() {
  form.value = { name: '', type: 'socks5', server: '', port: 1080, username: '', password: '' }
  dialogVisible.value = true
}

async function save() {
  saving.value = true
  try {
    const raw = {
      type: form.value.type,
      server: form.value.server,
      port: form.value.port,
      ...(form.value.username ? { username: form.value.username, password: form.value.password } : {}),
    }
    await api.post('/proxies', {
      name: form.value.name,
      type: form.value.type,
      raw_config: JSON.stringify(raw),
    })
    ElMessage.success(t('proxies.nodeAdded'))
    dialogVisible.value = false
    load()
  } finally {
    saving.value = false
  }
}

function downloadBlob(data: Blob, filename: string) {
  const url = URL.createObjectURL(data)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
  URL.revokeObjectURL(url)
}

async function exportProxies(format: 'json' | 'links') {
  exportLoading.value = true
  try {
    const { data } = await api.get('/proxies/export', {
      params: { format: format === 'links' ? 'links' : 'json' },
      responseType: 'blob',
    })
    downloadBlob(data, `prism-proxies.${format === 'links' ? 'txt' : 'json'}`)
    ElMessage.success(t('proxies.exported'))
  } finally {
    exportLoading.value = false
  }
}

function openImport() {
  importMode.value = 'append'
  importText.value = ''
  importVisible.value = true
}

function onImportFileChange(uploadFile: { raw?: File }) {
  const raw = uploadFile.raw
  if (!raw) return
  const reader = new FileReader()
  reader.onload = () => {
    importText.value = String(reader.result || '')
  }
  reader.readAsText(raw)
}

async function submitImport() {
  const text = importText.value.trim()
  if (!text) {
    ElMessage.warning(t('proxies.pasteRequired'))
    return
  }
  if (importMode.value === 'replace') {
    await ElMessageBox.confirm(t('proxies.importConfirmReplace'), t('proxies.importConfirmTitle'), {
      type: 'warning',
    })
  }
  importing.value = true
  try {
    const { data } = await api.post('/proxies/import', {
      mode: importMode.value,
      text,
    })
    const errs: string[] = data.errors || []
    if (errs.length) {
      ElMessage.warning(t('proxies.importedPartial', { n: data.imported, s: data.skipped }))
    } else {
      ElMessage.success(t('proxies.imported', { n: data.imported }))
    }
    importVisible.value = false
    load()
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string; errors?: string[] } } }
    const detail = err.response?.data?.errors?.join('；') || err.response?.data?.error
    ElMessage.error(detail || t('proxies.importFailed'))
  } finally {
    importing.value = false
  }
}

onMounted(load)
</script>

<template>
  <div class="page">
    <PageHeader :title="t('proxies.title')" :description="t('proxies.desc')">
      <template #actions>
        <el-button @click="rebuildCountries">{{ t('proxies.rebuildCountries') }}</el-button>
        <el-dropdown trigger="click" @command="(cmd: 'json' | 'links') => exportProxies(cmd)">
          <el-button :loading="exportLoading">{{ t('common.export') }}</el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="json">{{ t('proxies.exportJson') }}</el-dropdown-item>
              <el-dropdown-item command="links">{{ t('proxies.exportLinks') }}</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <el-button @click="openImport">{{ t('common.import') }}</el-button>
        <el-button type="primary" @click="openCreate">{{ t('proxies.addNode') }}</el-button>
        <el-button v-if="testing" @click="cancelTest">{{ t('proxies.cancelTest') }}</el-button>
        <el-button :loading="testing" @click="testAll">
          {{ testing && testProgress ? t('proxies.testingProgress', { progress: testProgress }) : t('proxies.testAll') }}
        </el-button>
      </template>
    </PageHeader>

    <AppCard>
      <div class="tabs-bar">
        <el-tabs v-model="activeTab" @tab-change="onFilterChange">
          <el-tab-pane :label="t('proxies.tabAll')" name="all" />
          <el-tab-pane :label="t('common.subscription')" name="subscription" />
          <el-tab-pane :label="t('common.manual')" name="manual" />
        </el-tabs>
      </div>
      <div class="card-toolbar">
        <el-select v-model="countryFilter" clearable :placeholder="t('proxies.filterCountry')" class="toolbar-select--country" @change="onFilterChange">
          <el-option :label="t('proxies.allCountries')" value="" />
          <el-option
            v-for="c in countries"
            :key="c.code"
            :label="`${c.name} (${c.count})`"
            :value="c.code"
          />
        </el-select>
        <span v-if="testing" class="form-hint form-hint--flush">{{ t('proxies.testingHint') }}</span>
      </div>
      <el-table :data="items" v-loading="loading" size="small">
        <el-table-column prop="name" :label="t('common.name')" min-width="140" />
        <el-table-column :label="t('proxies.country')" width="90">
          <template #default="{ row }">
            <el-tag v-if="row.country" size="small" type="info">{{ countryLabel(row.country) }}</el-tag>
            <span v-else class="form-hint">{{ t('common.none') }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="type" :label="t('common.type')" width="90" />
        <el-table-column prop="source" :label="t('common.source')" width="90" />
        <el-table-column :label="t('proxies.latency')" width="100">
          <template #default="{ row }">
            <span :class="latencyClass(row.latency_ms)">
              {{ row.latency_ms >= 0 ? `${row.latency_ms} ms` : t('proxies.notTested') }}
            </span>
          </template>
        </el-table-column>
        <el-table-column :label="t('common.status')" width="80">
          <template #default="{ row }">
            <el-tag :type="row.alive ? 'success' : 'info'" size="small">
              {{ row.alive ? t('proxies.alive') : t('common.unknown') }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column :label="t('common.actions')" width="100" fixed="right">
          <template #default="{ row }">
            <el-button size="small" link :disabled="testing" @click="testOne(row)">{{ t('proxies.testOne') }}</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="card-pager">
        <el-pagination
          v-model:current-page="page"
          v-model:page-size="pageSize"
          :page-sizes="[50, 100, 200, 500]"
          :total="total"
          layout="total, sizes, prev, pager, next"
          @current-change="load"
          @size-change="onFilterChange"
        />
      </div>
    </AppCard>

    <el-dialog v-model="importVisible" :title="t('proxies.importTitle')" width="560px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item :label="t('proxies.importMode')">
          <el-radio-group v-model="importMode">
            <el-radio value="append">{{ t('proxies.append') }}</el-radio>
            <el-radio value="replace">{{ t('proxies.replace') }}</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item :label="t('proxies.importFile')">
          <el-upload
            :auto-upload="false"
            :show-file-list="false"
            accept=".txt,.json"
            :on-change="onImportFileChange"
          >
            <el-button>{{ t('proxies.chooseFile') }}</el-button>
          </el-upload>
          <p class="form-hint">{{ t('proxies.importFileHint') }}</p>
        </el-form-item>
        <el-form-item :label="t('proxies.importContent')">
          <el-input
            v-model="importText"
            type="textarea"
            :rows="10"
            :placeholder="t('proxies.importPlaceholder')"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="importVisible = false">{{ t('common.cancel') }}</el-button>
        <el-button type="primary" :loading="importing" @click="submitImport">{{ t('common.import') }}</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="dialogVisible" :title="t('proxies.addDialogTitle')" width="520px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item :label="t('common.name')"><el-input v-model="form.name" /></el-form-item>
        <el-form-item :label="t('common.type')">
          <el-select v-model="form.type" class="w-full">
            <el-option label="SOCKS5" value="socks5" />
            <el-option label="HTTP" value="http" />
          </el-select>
        </el-form-item>
        <el-form-item :label="t('proxies.server')"><el-input v-model="form.server" /></el-form-item>
        <el-form-item :label="t('proxies.port')"><el-input-number v-model="form.port" :min="1" :max="65535" /></el-form-item>
        <el-form-item :label="t('proxies.username')"><el-input v-model="form.username" /></el-form-item>
        <el-form-item :label="t('proxies.password')"><el-input v-model="form.password" type="password" show-password /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
        <el-button type="primary" :loading="saving" @click="save">{{ t('common.confirm') }}</el-button>
      </template>
    </el-dialog>
  </div>
</template>
