<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

import MetricTile from '../components/MetricTile.vue'
import PageHero from '../components/PageHero.vue'
import {
  banBinding,
  fetchBindings,
  humanizeError,
  unbanBinding,
  unbindBinding,
  updateBindingIp,
} from '../api'
import { formatCompactNumber, formatDateTime, formatPercent } from '../utils/formatters'

const loading = ref(false)
const dialogVisible = ref(false)
const rows = ref([])
const total = ref(0)
const filters = reactive({
  token_suffix: '',
  ip: '',
  status: '',
  page: 1,
  page_size: 20,
})
const form = reactive({
  id: null,
  bound_ip: '',
})

const activeCount = computed(() => rows.value.filter((item) => item.status === 1).length)
const bannedCount = computed(() => rows.value.filter((item) => item.status === 2).length)
const visibleProtectedRate = computed(() => {
  if (!rows.value.length) {
    return 0
  }
  return activeCount.value / rows.value.length
})

function requestParams() {
  return {
    page: filters.page,
    page_size: filters.page_size,
    token_suffix: filters.token_suffix || undefined,
    ip: filters.ip || undefined,
    status: filters.status || undefined,
  }
}

async function loadBindings() {
  loading.value = true
  try {
    const data = await fetchBindings(requestParams())
    rows.value = data.items
    total.value = data.total
  } catch (error) {
    ElMessage.error(humanizeError(error, 'Failed to load bindings.'))
  } finally {
    loading.value = false
  }
}

function resetFilters() {
  filters.token_suffix = ''
  filters.ip = ''
  filters.status = ''
  filters.page = 1
  loadBindings()
}

function openEdit(row) {
  form.id = row.id
  form.bound_ip = row.bound_ip
  dialogVisible.value = true
}

async function submitEdit() {
  if (!form.bound_ip) {
    ElMessage.warning('Provide a CIDR or single IP.')
    return
  }
  try {
    await updateBindingIp({ id: form.id, bound_ip: form.bound_ip })
    ElMessage.success('Binding updated.')
    dialogVisible.value = false
    await loadBindings()
  } catch (error) {
    ElMessage.error(humanizeError(error, 'Failed to update binding.'))
  }
}

async function confirmAction(title, action) {
  try {
    await ElMessageBox.confirm(title, 'Confirm action', {
      confirmButtonText: 'Confirm',
      cancelButtonText: 'Cancel',
      type: 'warning',
    })
    await action()
    await loadBindings()
  } catch (error) {
    if (error === 'cancel') {
      return
    }
    ElMessage.error(humanizeError(error, 'Operation failed.'))
  }
}

function onPageChange(value) {
  filters.page = value
  loadBindings()
}

onMounted(() => {
  loadBindings()
})
</script>

<template>
  <div class="page-grid">
    <PageHero
      eyebrow="Binding control"
      title="Inspect first-use bindings and intervene without touching proxy workers"
      description="Edit CIDRs for device changes, remove stale registrations, or move leaked keys into a banned state."
    >
      <template #aside>
        <div class="hero-stat-pair">
          <div class="hero-stat">
            <span class="eyebrow">Visible active share</span>
            <strong>{{ formatPercent(visibleProtectedRate) }}</strong>
          </div>
          <div class="hero-stat">
            <span class="eyebrow">Page volume</span>
            <strong>{{ formatCompactNumber(rows.length) }}</strong>
          </div>
        </div>
      </template>
    </PageHero>

    <section class="metric-grid">
      <MetricTile
        eyebrow="Visible rows"
        :value="formatCompactNumber(rows.length)"
        note="Records loaded on the current page."
        accent="slate"
      />
      <MetricTile
        eyebrow="Matching total"
        :value="formatCompactNumber(total)"
        note="Bindings matching current filters."
        accent="mint"
      />
      <MetricTile
        eyebrow="Active rows"
        :value="formatCompactNumber(activeCount)"
        note="Active items visible in the current slice."
        accent="mint"
      />
      <MetricTile
        eyebrow="Banned rows"
        :value="formatCompactNumber(bannedCount)"
        note="Banned items currently visible in the table."
        accent="amber"
      />
    </section>

    <section class="table-card panel">
      <div class="toolbar">
        <div class="toolbar-left">
          <el-input v-model="filters.token_suffix" placeholder="Token suffix" clearable style="width: 180px;" />
          <el-input v-model="filters.ip" placeholder="Bound IP or CIDR" clearable style="width: 220px;" />
          <el-select v-model="filters.status" placeholder="Status" clearable style="width: 150px;">
            <el-option label="Active" :value="1" />
            <el-option label="Banned" :value="2" />
          </el-select>
        </div>

        <div class="toolbar-right">
          <el-button @click="resetFilters">Reset</el-button>
          <el-button type="primary" :loading="loading" @click="filters.page = 1; loadBindings()">Search</el-button>
        </div>
      </div>

      <div class="data-table" style="margin-top: 20px;">
        <el-table :data="rows" v-loading="loading">
          <el-table-column prop="id" label="ID" width="90" />
          <el-table-column prop="token_display" label="Token" min-width="170" />
          <el-table-column prop="bound_ip" label="Bound CIDR" min-width="180" />
          <el-table-column label="Status" width="120">
            <template #default="{ row }">
              <el-tag :type="row.status === 1 ? 'success' : 'danger'" round>
                {{ row.status_label }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="first_used_at" label="First used" min-width="190">
            <template #default="{ row }">{{ formatDateTime(row.first_used_at) }}</template>
          </el-table-column>
          <el-table-column prop="last_used_at" label="Last used" min-width="190">
            <template #default="{ row }">{{ formatDateTime(row.last_used_at) }}</template>
          </el-table-column>
          <el-table-column label="Actions" min-width="280" fixed="right">
            <template #default="{ row }">
              <div class="toolbar-left">
                <el-button size="small" @click="openEdit(row)">Edit IP</el-button>
                <el-button
                  size="small"
                  type="danger"
                  plain
                  @click="confirmAction('Remove this binding and allow first-use bind again?', () => unbindBinding(row.id))"
                >
                  Unbind
                </el-button>
                <el-button
                  v-if="row.status === 1"
                  size="small"
                  type="warning"
                  plain
                  @click="confirmAction('Ban this token?', () => banBinding(row.id))"
                >
                  Ban
                </el-button>
                <el-button
                  v-else
                  size="small"
                  type="success"
                  plain
                  @click="confirmAction('Restore this token to active state?', () => unbanBinding(row.id))"
                >
                  Unban
                </el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <div class="toolbar" style="margin-top: 18px;">
        <span class="muted">Page {{ filters.page }} of {{ Math.max(1, Math.ceil(total / filters.page_size)) }}</span>
        <el-pagination
          background
          layout="prev, pager, next"
          :current-page="filters.page"
          :page-size="filters.page_size"
          :total="total"
          @current-change="onPageChange"
        />
      </div>
    </section>

    <el-dialog v-model="dialogVisible" title="Update bound CIDR" width="420px">
      <el-form label-position="top">
        <el-form-item label="CIDR or single IP">
          <el-input v-model="form.bound_ip" placeholder="192.168.1.0/24" />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="dialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="submitEdit">Save</el-button>
      </template>
    </el-dialog>
  </div>
</template>
