<template>
  <div class="number-card-block" :class="{ 'edit-mode': editMode }">
    <div class="number-card" :style="{ cursor: editMode ? 'default' : 'pointer' }" @click="handleClick">
      <div class="number-card-header">
        <div class="card-label">{{ label }}</div>
        <div v-if="!editMode" class="card-actions-menu">
          <n-dropdown trigger="click" :options="cardActions" @select="handleAction">
            <n-button text size="small" @click.stop>
              <Icon icon="tabler:dots" />
            </n-button>
          </n-dropdown>
        </div>
      </div>
      <div class="number-card-content">
        <div v-if="loading" class="loading-state">
          <Icon icon="tabler:loader-2" class="animate-spin" :style="{ fontSize: '24px' }" />
          <span>{{ t('Loading...') }}</span>
        </div>
        <div v-else class="number-display">
          <div class="number-value" :style="{ color: cardColor || undefined }">
            {{ formattedNumber }}
          </div>
          <div v-if="showStats && percentageStat !== null" class="card-stats" :class="statsClass">
            <span class="percentage-stat-area">
              <Icon v-if="percentageStat > 0" icon="tabler:arrow-up-right" class="stat-icon" />
              <Icon v-else-if="percentageStat < 0" icon="tabler:arrow-down-right" class="stat-icon" />
              {{ Math.abs(percentageStat).toFixed(1) }}% {{ statsQualifier }}
            </span>
          </div>
        </div>
      </div>
    </div>
    <div v-if="editMode" class="card-actions">
      <button class="action-btn" @click="$emit('edit')" :title="t('Edit')">
        <Icon icon="tabler:edit" />
      </button>
      <button class="action-btn" @click="$emit('expand')" :title="t('Expand')">
        <Icon icon="tabler:arrows-maximize" />
      </button>
      <button class="action-btn" @click="$emit('shrink')" :title="t('Shrink')">
        <Icon icon="tabler:arrows-minimize" />
      </button>
      <button class="action-btn drag-handle" :title="t('Drag')">
        <Icon icon="tabler:grip-vertical" />
      </button>
      <n-dropdown trigger="click" :options="menuOptions" @select="handleMenuSelect">
        <button class="action-btn" :title="t('More')">
          <Icon icon="tabler:dots" />
        </button>
      </n-dropdown>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, h } from 'vue'
import { Icon } from '@iconify/vue'
import { NButton, NDropdown } from 'naive-ui'
import { t } from '@/shared/i18n'
import { api } from '@/shared/api/common'

const props = defineProps<{
  numberCardName: string
  numberCardData?: any
  editMode: boolean
}>()

const emit = defineEmits<{
  edit: []
  expand: []
  shrink: []
  delete: []
}>()

const menuOptions = computed(() => [
  { label: t('Delete'), key: 'delete', icon: () => h(Icon, { icon: 'tabler:trash', size: 16 }) }
])

function handleMenuSelect(key: string) {
  if (key === 'delete') {
    emit('delete')
  }
}

const loading = ref(false)
const cardDoc = ref<any>(null)
const number = ref<number>(0)
const formattedNumber = ref('0')
const percentageStat = ref<number | null>(null)
const cardColor = ref<string>('')

const label = computed(() => {
  return props.numberCardData?.label || t(props.numberCardName)
})

const showStats = computed(() => {
  return cardDoc.value?.show_percentage_stats && cardDoc.value?.type === 'Document Type'
})

const statsClass = computed(() => {
  if (percentageStat.value === null || percentageStat.value === 0) return 'grey-stat'
  return percentageStat.value > 0 ? 'green-stat' : 'red-stat'
})

const statsQualifier = computed(() => {
  const map: Record<string, string> = {
    'Daily': t('since yesterday'),
    'Weekly': t('since last week'),
    'Monthly': t('since last month'),
    'Yearly': t('since last year')
  }
  return map[cardDoc.value?.stats_time_interval] || ''
})

const cardActions = computed(() => [
  {
    label: t('Refresh'),
    key: 'refresh',
    icon: () => h(Icon, { icon: 'tabler:refresh' })
  },
  {
    label: t('Edit'),
    key: 'edit',
    icon: () => h(Icon, { icon: 'tabler:edit' })
  }
])

onMounted(() => {
  loadCard()
})

async function loadCard() {
  if (loading.value) return
  loading.value = true

  try {
    const result = await api.call('jingrow.desk.form.load.getpage', {
      pagetype: 'Number Card',
      name: props.numberCardName
    })

    if (!result?.pgs?.[0]) {
      loading.value = false
      return
    }

    cardDoc.value = result.pgs[0]
    cardColor.value = cardDoc.value.color || ''

    await fetchData()
  } catch (error: any) {
    console.error('Failed to load number card:', error)
  } finally {
    loading.value = false
  }
}

async function fetchData() {
  if (!cardDoc.value) return

  try {
    const filters = getFilters()

    if (cardDoc.value.type === 'Custom') {
      await fetchCustomCard(filters)
    } else if (cardDoc.value.type === 'Report') {
      await fetchReportCard(filters)
    } else {
      await fetchDocTypeCard(filters)
    }
  } catch (error: any) {
    console.error('Failed to fetch number card data:', error)
    formattedNumber.value = 'N/A'
  }
}

function getFilters() {
  try {
    return JSON.parse(cardDoc.value.filters_json || '[]')
  } catch {
    return []
  }
}

async function fetchCustomCard(filters: any[]) {
  const res = await api.call(cardDoc.value.method, { filters })
  if (typeof res?.message === 'object' && res.message.value !== undefined) {
    number.value = res.message.value
    formattedNumber.value = formatNumber(res.message)
  } else {
    formattedNumber.value = String(res?.message || '0')
  }
}

async function fetchReportCard(filters: any[]) {
  const res = await api.call('jingrow.desk.query_report.run', {
    report_name: cardDoc.value.report_name,
    filters: filters,
    ignore_prepared_report: 1
  })

  const result = res?.message?.result || []
  const field = cardDoc.value.report_field
  const values = result.map((row: any) => row[field]).filter(Boolean)
  number.value = calculateAggregate(values, cardDoc.value.report_function)
  formattedNumber.value = formatNumber({ fieldtype: 'Float' })
}

async function fetchDocTypeCard(filters: any[]) {
  const res = await api.call('jingrow.desk.pagetype.number_card.number_card.get_result', {
    pg: JSON.stringify(cardDoc.value),
    filters: JSON.stringify(filters)
  })

  number.value = res?.message || 0
  formattedNumber.value = formatNumber()

  if (showStats.value) {
    await fetchPercentageStats(filters)
  }
}

function calculateAggregate(values: number[], func: string): number {
  if (!values.length) return 0
  switch (func) {
    case 'Sum': return values.reduce((a, b) => a + b, 0)
    case 'Average': return values.reduce((a, b) => a + b, 0) / values.length
    case 'Minimum': return Math.min(...values)
    case 'Maximum': return Math.max(...values)
    default: return 0
  }
}

function formatNumber(df?: any): string {
  let val = number.value
  const shortened = shortenNumber(val)
  const parts = shortened.split(' ')
  
  if (cardDoc.value?.currency) {
    return `${cardDoc.value.currency} ${parts[0]}`
  }
  
  const symbol = parts[1] || ''
  return `${parts[0]} ${symbol}`.trim()
}

function shortenNumber(num: number): string {
  const absNum = Math.abs(num)
  if (absNum >= 1e9) return `${(num / 1e9).toFixed(1)} B`
  if (absNum >= 1e6) return `${(num / 1e6).toFixed(1)} M`
  if (absNum >= 1e3) return `${(num / 1e3).toFixed(1)} K`
  return num.toFixed(0)
}

async function fetchPercentageStats(filters: any[]) {
  try {
    const res = await api.call('jingrow.desk.pagetype.number_card.number_card.get_percentage_difference', {
      pg: JSON.stringify(cardDoc.value),
      filters: JSON.stringify(filters),
      result: JSON.stringify(number.value)
    })
    percentageStat.value = res?.message ?? null
  } catch (error: any) {
    console.error('Failed to fetch percentage stats:', error)
  }
}

function handleClick() {
  if (props.editMode) return
  
  if (cardDoc.value?.type === 'Custom') {
    return
  }

  const isDocType = cardDoc.value?.type !== 'Report'
  const name = isDocType ? cardDoc.value?.document_type : cardDoc.value?.report_name
  
  if (isDocType) {
    window.location.href = `/app/${name}`
  } else {
    window.location.href = `/app/query-report/${name}`
  }
}

function handleAction(key: string) {
  if (key === 'refresh') {
    loadCard()
  } else if (key === 'edit') {
    window.location.href = `/app/number-card/${props.numberCardName}`
  }
}
</script>

<style scoped>
.number-card-block {
  background: #fff;
  border: 1px solid #eef2f7;
  border-radius: 12px;
  padding: 16px;
  position: relative;
  transition: all 0.2s;
  box-shadow: 0 2px 8px rgba(15,23,42,0.04);
}

.edit-mode .number-card-block {
  border: 2px dashed transparent;
}

.number-card {
  width: 100%;
  padding: 16px;
  min-height: 120px;
  display: flex;
  flex-direction: column;
}

.number-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.card-label {
  font-size: 13px;
  font-weight: 500;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.card-actions-menu {
  opacity: 0;
  transition: opacity 0.2s;
}

.number-card:hover .card-actions-menu {
  opacity: 1;
}

.number-card-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #94a3b8;
  padding: 20px 0;
}

.animate-spin {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.number-display {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.number-value {
  font-size: 32px;
  font-weight: 700;
  color: #0f172a;
  line-height: 1;
}

.card-stats {
  display: flex;
  align-items: center;
  font-size: 12px;
  font-weight: 500;
}

.card-stats.green-stat {
  color: #10b981;
}

.card-stats.red-stat {
  color: #ef4444;
}

.card-stats.grey-stat {
  color: #94a3b8;
}

.percentage-stat-area {
  display: flex;
  align-items: center;
  gap: 4px;
}

.stat-icon {
  font-size: 14px;
}

.card-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  opacity: 0;
  transition: opacity 0.2s;
  position: absolute;
  top: 8px;
  right: 8px;
}

.edit-mode:hover .card-actions {
  opacity: 1;
}

.action-btn {
  background: transparent;
  border: none;
  color: #64748b;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  font-size: 16px;
}

.action-btn:hover {
  background: #f1f5f9;
  color: #0f172a;
}

.drag-handle {
  cursor: grab;
}

.drag-handle:active {
  cursor: grabbing;
}
</style>
