<script setup lang="ts">
import { computed, ref, onMounted, watch } from 'vue'
import { NButton, NModal, NInput, NSelect, NDatePicker, NSpin, useMessage } from 'naive-ui'
import { api } from '@/shared/api/common'

const props = defineProps<{ df: any; record: Record<string, any>; canEdit: boolean; ctx: any }>()

const message = useMessage()

// Label layout
const labelLayout = computed(() => props.df.label_layout || 'vertical')

// Determine which field this is
const isFiltersJson = computed(() => props.df.fieldname === 'filters_json')
const isDynamicFiltersJson = computed(() => props.df.fieldname === 'dynamic_filters_json')
const isCustomOptions = computed(() => props.df.fieldname === 'custom_options')

// Chart type from record
const chartType = computed(() => props.record?.chart_type || '')
const reportName = computed(() => props.record?.report_name || '')
const sourceName = computed(() => props.record?.source || '')
const documentType = computed(() => props.record?.document_type || '')

// Filter configuration
const chartFilters = ref<any[]>([])
const loading = ref(false)

// For custom_options: expanded state
const expanded = ref(false)

// Local edit value for custom_options
const localValue = ref('')

// Parse current filters
const currentFilters = computed(() => {
  const value = props.record?.[props.df.fieldname]
  if (!value) return isFiltersJson.value ? [] : null
  
  try {
    return JSON.parse(value)
  } catch {
    return isFiltersJson.value ? [] : null
  }
})

// Check if is document type chart (not Report or Custom)
const isDocumentType = computed(() => {
  return chartType.value !== 'Report' && chartType.value !== 'Custom'
})

// Load filters for chart type
async function loadFiltersForChartType() {
  if (!isFiltersJson.value && !isDynamicFiltersJson.value) return
  
  loading.value = true
  try {
    if (chartType.value === 'Custom' && sourceName.value) {
      // Get filters from dashboard chart source
      const res = await api.call('jingrow.desk.pagetype.dashboard_chart_source.dashboard_chart_source.get_config', {
        name: sourceName.value
      })
      // The config is JS code, extract filters from jingrow.dashboards.chart_sources
      chartFilters.value = []
    } else if (chartType.value === 'Report' && reportName.value) {
      // Get filters from report via get_script API
      const res = await api.call('jingrow.desk.query_report.get_script', {
        report_name: reportName.value
      })
      chartFilters.value = res?.filters || []
    }
  } catch (e) {
    console.error('Failed to load filters:', e)
    chartFilters.value = []
  } finally {
    loading.value = false
  }
}

// Initialize local value for custom_options
function initLocalValue() {
  if (isCustomOptions.value) {
    const val = props.record?.[props.df.fieldname]
    if (val) {
      try {
        localValue.value = JSON.stringify(JSON.parse(val), null, 2)
      } catch {
        localValue.value = val
      }
    } else {
      localValue.value = ''
    }
  }
}

// Update record from local value
function updateRecordFromLocal() {
  if (!props.record) return
  props.record[props.df.fieldname] = localValue.value
}

// Format JSON
function formatJson() {
  try {
    const parsed = JSON.parse(localValue.value)
    localValue.value = JSON.stringify(parsed, null, 2)
    message.success(props.ctx.t('Formatted successfully'))
  } catch {
    message.error(props.ctx.t('Invalid JSON format'))
  }
}

// Copy to clipboard
function copyToClipboard() {
  const text = localValue.value || props.record?.[props.df.fieldname] || '{}'
  if (!text) return
  
  // Try modern clipboard API first
  if (navigator.clipboard && navigator.clipboard.writeText) {
    navigator.clipboard.writeText(text).then(() => {
      message.success(props.ctx.t('Copied to clipboard.'))
    }).catch(() => {
      fallbackCopy(text)
    })
  } else {
    fallbackCopy(text)
  }
}

// Fallback copy for non-HTTPS environments
function fallbackCopy(text: string) {
  const textarea = document.createElement('textarea')
  textarea.value = text
  textarea.style.position = 'fixed'
  textarea.style.left = '-9999px'
  document.body.appendChild(textarea)
  textarea.select()
  try {
    document.execCommand('copy')
    message.success(props.ctx.t('Copied to clipboard.'))
  } catch {
    message.error(props.ctx.t('Failed to copy to clipboard'))
  } finally {
    document.body.removeChild(textarea)
  }
}

// Table rows for display
const tableRows = computed(() => {
  const filters = currentFilters.value
  
  if (isFiltersJson.value) {
    if (isDocumentType.value) {
      // Document type filters: [[pagetype, fieldname, condition, value], ...]
      if (Array.isArray(filters) && filters.length > 0) {
        return filters.map((f: any) => ({
          filter: f[1] || '',
          condition: f[2] || '=',
          value: f[3] || ''
        }))
      }
    } else {
      // Report filters: { fieldname: value, ... }
      if (filters && typeof filters === 'object' && !Array.isArray(filters)) {
        return Object.entries(filters).map(([key, value]) => {
          const filterDef = chartFilters.value.find((f: any) => f.fieldname === key)
          return {
            filter: filterDef?.label || key,
            condition: '=',
            value: String(value)
          }
        })
      }
    }
  }
  
  if (isDynamicFiltersJson.value) {
    if (Array.isArray(filters) && filters.length > 0) {
      return filters.map((f: any) => ({
        filter: f[1] || '',
        condition: f[2] || '=',
        value: f[3] || ''
      }))
    } else if (filters && typeof filters === 'object') {
      return Object.entries(filters).map(([key, value]) => ({
        filter: key,
        condition: '=',
        value: String(value)
      }))
    }
  }
  
  return []
})

// Dialog state
const showDialog = ref(false)
const dialogFilters = ref<Record<string, any>>({})
const jsonEditorValue = ref('')

// Open dialog to edit filters
function openDialog() {
  if (!props.canEdit) return
  
  // Initialize dialog filters from current values
  dialogFilters.value = {}
  
  const filters = currentFilters.value
  if (filters) {
    if (isDocumentType.value && Array.isArray(filters)) {
      // Document type filters
      filters.forEach((f: any) => {
        if (f[1] && f[3] !== undefined) {
          dialogFilters.value[f[1]] = f[3]
        }
      })
    } else if (typeof filters === 'object' && !Array.isArray(filters)) {
      // Report filters
      Object.assign(dialogFilters.value, filters)
    }
  }
  
  // Initialize JSON editor value
  jsonEditorValue.value = JSON.stringify(filters || (isDocumentType.value ? [] : {}), null, 2)
  
  showDialog.value = true
}

// Update JSON editor
function updateJsonEditor(value: string) {
  jsonEditorValue.value = value
}

// Save filters from dialog
function saveFilters() {
  let newFilters: any
  
  if (!isDocumentType.value && chartFilters.value.length > 0) {
    // Report type with filters defined
    newFilters = { ...dialogFilters.value }
  } else {
    // Document type or no filters: use JSON editor
    try {
      newFilters = JSON.parse(jsonEditorValue.value)
    } catch (e) {
      message.error(props.ctx.t('Invalid JSON format'))
      return
    }
  }
  
  props.record[props.df.fieldname] = JSON.stringify(newFilters)
  showDialog.value = false
  message.success(props.ctx.t('Saved successfully'))
}

// Get filter field type for dialog
function getFilterFieldType(filter: any): string {
  return filter.fieldtype || 'Data'
}

// Watch for chart type changes
watch([chartType, reportName, sourceName], () => {
  loadFiltersForChartType()
}, { immediate: true })

// Watch for record changes to initialize local value
watch(() => props.record?.[props.df.fieldname], () => {
  initLocalValue()
}, { immediate: true })

onMounted(() => {
  initLocalValue()
  if (!isCustomOptions.value) {
    loadFiltersForChartType()
  }
})
</script>

<template>
  <!-- Custom Options: JSON Editor -->
  <div v-if="isCustomOptions" :class="['field-wrapper', `layout-${labelLayout}`]">
    <label class="field-label">
      {{ ctx.t(df.label || df.fieldname) }}
      <span v-if="df.reqd" class="required">*</span>
    </label>
    <div class="code-editor">
      <div class="code-editor__wrap" :class="{ expanded: expanded }">
        <n-input
          v-model:value="localValue"
          @update:value="updateRecordFromLocal"
          type="textarea"
          :rows="expanded ? 12 : 4"
          placeholder=""
          :disabled="!canEdit"
          class="json-textarea"
        />
        <button class="code-editor__copy-btn" type="button" @click="copyToClipboard">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
            <path d="M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1ZM19 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H19C20.1 23 21 22.1 21 21V7C21 5.9 20.1 5 19 5ZM19 21H8V7H19V21Z" fill="currentColor"/>
          </svg>
        </button>
      </div>
      <div class="code-editor__footer">
        <n-button v-if="canEdit" size="tiny" quaternary @click="formatJson">{{ ctx.t('Format') }}</n-button>
        <n-button v-if="canEdit" size="tiny" quaternary @click="expanded = !expanded">
          {{ expanded ? ctx.t('Collapse') : ctx.t('Expand') }}
        </n-button>
      </div>
    </div>
  </div>
  
  <!-- Filters JSON: Interactive Table -->
  <div v-else :class="['field-wrapper', `layout-${labelLayout}`]">
    <label class="field-label">
      {{ ctx.t(df.label || df.fieldname) }}
      <span v-if="df.reqd" class="required">*</span>
    </label>
    
    <div class="filter-table-container">
      <n-spin :show="loading">
        <!-- Filter table -->
        <table class="filter-table" @click="openDialog">
          <thead>
            <tr>
              <th style="width: 30%">{{ ctx.t('Filter') }}</th>
              <th style="width: 20%">{{ ctx.t('Condition') }}</th>
              <th style="width: 50%">{{ ctx.t('Value') }}</th>
            </tr>
          </thead>
          <tbody>
            <tr v-if="tableRows.length === 0">
              <td colspan="3" class="empty-hint">
                {{ ctx.t('Click to Set Filters') }}
              </td>
            </tr>
            <tr v-else v-for="(row, idx) in tableRows" :key="idx">
              <td>{{ row.filter }}</td>
              <td>{{ row.condition }}</td>
              <td>{{ row.value }}</td>
            </tr>
          </tbody>
        </table>
      </n-spin>
      
      <p class="table-hint">{{ ctx.t('Click table to edit') }}</p>
    </div>
    
    <!-- Filter Dialog -->
    <n-modal
      v-model:show="showDialog"
      preset="card"
      :title="ctx.t('Set Filters')"
      :style="{ width: '600px' }"
    >
      <div class="filter-dialog-content">
        <!-- Report type filters -->
        <template v-if="!isDocumentType && chartFilters.length > 0">
          <div v-for="filter in chartFilters" :key="filter.fieldname" class="filter-row">
            <label class="filter-label">{{ ctx.t(filter.label) }}</label>
            
            <!-- Select type -->
            <n-select
              v-if="filter.fieldtype === 'Select'"
              v-model:value="dialogFilters[filter.fieldname]"
              :options="filter.options?.split('\n').map((o: string) => ({ label: ctx.t(o), value: o })) || []"
              clearable
            />
            
            <!-- Date type -->
            <n-date-picker
              v-else-if="filter.fieldtype === 'Date'"
              v-model:value="dialogFilters[filter.fieldname]"
              type="date"
              clearable
            />
            
            <!-- Default text input -->
            <n-input
              v-else
              v-model:value="dialogFilters[filter.fieldname]"
              :placeholder="ctx.t('Enter value')"
              clearable
            />
          </div>
        </template>
        
        <!-- Document type or no filters: show JSON editor -->
        <template v-else>
          <div class="filter-row">
            <label class="filter-label">{{ ctx.t('JSON Editor') }}</label>
            <n-input
              :value="jsonEditorValue"
              @update:value="updateJsonEditor"
              type="textarea"
              :rows="8"
              placeholder=""
            />
          </div>
        </template>
      </div>
      
      <template #footer>
        <div class="dialog-footer">
          <n-button @click="showDialog = false">{{ ctx.t('Cancel') }}</n-button>
          <n-button type="primary" @click="saveFilters">{{ ctx.t('Set') }}</n-button>
        </div>
      </template>
    </n-modal>
  </div>
</template>

<style scoped>
.field-wrapper {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.field-wrapper.layout-horizontal {
  flex-direction: row;
  align-items: flex-start;
}

.field-label {
  font-weight: 500;
  font-size: 14px;
  color: #374151;
}

.field-label .required {
  color: #ef4444;
  margin-left: 4px;
}

.filter-table-container {
  flex: 1;
}

.filter-table {
  width: 100%;
  border-collapse: collapse;
  cursor: pointer;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  overflow: hidden;
}

.filter-table th,
.filter-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid #e5e7eb;
}

.filter-table th {
  background: #f9fafb;
  font-weight: 600;
  color: #374151;
  font-size: 13px;
}

.filter-table td {
  font-size: 13px;
  color: #1f2937;
}

.filter-table tbody tr:hover {
  background: #f3f4f6;
}

.filter-table tbody tr:last-child td {
  border-bottom: none;
}

.empty-hint {
  text-align: center;
  color: #9ca3af;
  font-style: italic;
}

.table-hint {
  margin-top: 8px;
  font-size: 12px;
  color: #6b7280;
}

.filter-dialog-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.filter-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.filter-label {
  font-weight: 500;
  font-size: 13px;
  color: #374151;
}

.no-filters {
  text-align: center;
  color: #9ca3af;
  padding: 20px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* Code editor styles for custom_options */
.code-editor {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.code-editor__wrap {
  position: relative;
  width: 100%;
}

.code-editor__wrap.expanded {
}

.json-textarea {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 13px;
}

.code-editor__copy-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.9);
  color: #64748b;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  transition: all 0.15s ease;
  opacity: 0.7;
  z-index: 10;
}

.code-editor__copy-btn:hover {
  opacity: 1;
}

.code-editor__footer {
  display: flex;
  justify-content: flex-start;
  gap: 8px;
}
</style>
