<template>
  <div class="error-history">
    <div class="layout-container">
      <!-- 좌측 트리 영역 -->
      <div class="tree-panel">
        <div class="tree-header">
          <h4>파일 탐색</h4>
          <Button size="sm" variant="secondary" @click="loadTree" :loading="treeLoading">
            새로고침
          </Button>
        </div>
        
        <!-- 서버 선택 -->
        <div class="server-select">
          <select v-model="selectedServerId" @change="onServerChange">
            <option :value="null">전체 서버</option>
            <option v-for="server in treeData" :key="server.serverId" :value="server.serverId">
              {{ server.serverName }} ({{ server.totalErrorCount }}건)
            </option>
          </select>
        </div>

        <div class="tree-content">
          <div v-if="treeLoading" class="tree-loading">로딩중...</div>
          <div v-else-if="filteredTreeData.length === 0" class="tree-empty">
            분석된 파일이 없습니다.
          </div>
          <div v-else class="tree-list">
            <!-- 전체 선택 -->
            <div 
              class="tree-item tree-all" 
              :class="{ active: !selectedFile }"
              @click="selectAll"
            >
              <span class="tree-icon">📊</span>
              <span class="tree-label">전체</span>
              <span class="tree-count">{{ filteredErrorCount }}건</span>
            </div>
            
            <!-- 경로 노드 (서버 선택 시) -->
            <div v-for="server in filteredTreeData" :key="server.serverId">
              <div v-for="path in server.paths" :key="path.path" class="tree-path">
                <div 
                  class="tree-item tree-path-item"
                  @click="togglePath(server.serverId + ':' + path.path)"
                >
                  <span class="tree-toggle">{{ expandedPaths.includes(server.serverId + ':' + path.path) ? '▼' : '▶' }}</span>
                  <span class="tree-icon">📁</span>
                  <span class="tree-label" :title="path.path">{{ shortenPath(path.path) }}</span>
                  <span class="tree-count">{{ path.totalErrorCount }}건</span>
                </div>
                
                <!-- 파일 노드 -->
                <div v-if="expandedPaths.includes(server.serverId + ':' + path.path)" class="tree-files">
                  <div 
                    v-for="file in path.files" 
                    :key="file.filePath"
                    class="tree-item tree-file-item"
                    :class="{ active: selectedFile && selectedFile.filePath === file.filePath && selectedFile.serverId === server.serverId }"
                    @click="selectFile(server.serverId, file)"
                    :title="file.fileName"
                  >
                    <span class="tree-icon">📄</span>
                    <span class="tree-label">{{ file.fileName }}</span>
                    <span class="tree-count-detail">
                      <span v-if="file.criticalCount" class="critical">{{ file.criticalCount }}</span>
                      <span v-if="file.errorLevelCount" class="error">{{ file.errorLevelCount }}</span>
                      <span v-if="file.warnCount" class="warn">{{ file.warnCount }}</span>
                    </span>
                    <button class="tree-delete" @click.stop="confirmDeleteFile(server.serverId, file)" title="삭제">
                      🗑️
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 우측 에러 목록 영역 -->
      <div class="list-panel">
        <Card>
          <template #header>
            <div class="card-header-content">
              <h3>
                <span v-if="selectedFile">{{ selectedFile.fileName }}</span>
                <span v-else>전체 에러 이력</span>
              </h3>
              <div class="header-actions">
                <Button size="sm" variant="secondary" @click="exportHtml">HTML</Button>
                <Button size="sm" variant="secondary" @click="exportTxt">TXT</Button>
              </div>
            </div>
          </template>

          <!-- 필터 -->
          <div class="filters">
            <div class="filter-row">
              <FormInput
                v-model="filters.patternId"
                label="패턴"
                type="select"
                :options="patternOptions"
                placeholder="전체"
              />
              <FormInput
                v-model="filters.severity"
                label="심각도"
                type="select"
                :options="severityOptions"
                placeholder="전체"
              />
              <FormInput
                v-model="filters.keyword"
                label="키워드"
                placeholder="검색어 입력..."
              />
              <div class="filter-actions">
                <Button @click="search">검색</Button>
                <Button variant="secondary" @click="resetFilters">초기화</Button>
              </div>
            </div>
          </div>

          <!-- 결과 테이블 -->
          <div class="results-section">
            <div class="results-header">
              <span v-if="totalElements > 0">총 {{ totalElements }}건</span>
            </div>

            <div class="table-wrapper">
              <table class="error-table" v-if="errors.length > 0">
                <thead>
                  <tr>
                    <th class="col-time sortable" @click="toggleSort('occurredAt')">
                      발생시간 <span class="sort-icon">{{ getSortIcon('occurredAt') }}</span>
                    </th>
                    <th class="col-severity sortable" @click="toggleSort('severity')">
                      심각도 <span class="sort-icon">{{ getSortIcon('severity') }}</span>
                    </th>
                    <th class="col-pattern sortable" @click="toggleSort('patternName')">
                      패턴 <span class="sort-icon">{{ getSortIcon('patternName') }}</span>
                    </th>
                    <th class="col-summary sortable" @click="toggleSort('summary')">
                      요약 <span class="sort-icon">{{ getSortIcon('summary') }}</span>
                    </th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="error in errors" :key="error.id">
                    <td class="col-time">{{ formatDate(error.occurredAt) }}</td>
                    <td class="col-severity">
                      <Badge :variant="getSeverityVariant(error.severity)">{{ error.severity }}</Badge>
                    </td>
                    <td class="col-pattern">{{ error.patternName }}</td>
                    <td class="col-summary">
                      <a href="#" class="summary-link" @click.prevent="showDetail(error)">
                        {{ truncate(error.summary, 100) }}
                      </a>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>

            <div v-if="errors.length === 0 && !loading" class="empty-result">
              <p>검색 결과가 없습니다.</p>
            </div>

            <div v-if="loading" class="loading-result">
              <p>로딩중...</p>
            </div>

            <!-- 페이지네이션 -->
            <div v-if="totalPages > 1" class="pagination">
              <Button 
                size="sm" 
                variant="secondary" 
                :disabled="currentPage === 0"
                @click="goToPage(currentPage - 1)"
              >
                이전
              </Button>
              <span class="page-info">{{ currentPage + 1 }} / {{ totalPages }}</span>
              <Button 
                size="sm" 
                variant="secondary" 
                :disabled="currentPage >= totalPages - 1"
                @click="goToPage(currentPage + 1)"
              >
                다음
              </Button>
            </div>
          </div>
        </Card>
      </div>
    </div>

    <!-- 상세 모달 -->
    <Modal v-model="showDetailModal" title="에러 상세" width="900px">
      <div v-if="selectedError" class="error-detail">
        <div class="detail-grid">
          <div class="detail-item">
            <label>서버</label>
            <span>{{ selectedError.serverName }}</span>
          </div>
          <div class="detail-item">
            <label>심각도</label>
            <Badge :variant="getSeverityVariant(selectedError.severity)">{{ selectedError.severity }}</Badge>
          </div>
          <div class="detail-item">
            <label>패턴</label>
            <span>{{ selectedError.patternName }}</span>
          </div>
          <div class="detail-item">
            <label>파일</label>
            <span class="file-path">{{ selectedError.filePath }}</span>
          </div>
          <div class="detail-item">
            <label>라인</label>
            <span>{{ selectedError.lineNumber }}</span>
          </div>
          <div class="detail-item">
            <label>발생시간</label>
            <span>{{ formatDate(selectedError.occurredAt) }}</span>
          </div>
        </div>

        <div class="detail-section">
          <label>요약</label>
          <div class="summary-box">{{ selectedError.summary }}</div>
        </div>

        <div class="detail-section">
          <label>컨텍스트</label>
          <pre class="context-box">{{ selectedError.context }}</pre>
        </div>
      </div>
      <template #footer>
        <Button variant="secondary" @click="showDetailModal = false">닫기</Button>
      </template>
    </Modal>

    <!-- 삭제 확인 모달 -->
    <Modal v-model="showDeleteModal" title="파일 삭제" width="400px">
      <p>{{ deleteFileName }} 파일의 분석 결과를 삭제하시겠습니까?</p>
      <p class="warning-text">에러 로그와 스캔 기록이 삭제되어 재분석이 가능해집니다.</p>
      <template #footer>
        <Button variant="secondary" @click="showDeleteModal = false">취소</Button>
        <Button ref="deleteBtn" variant="danger" @click="executeDelete" :loading="deleting">삭제</Button>
      </template>
    </Modal>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { Card, Button, Badge, Modal, FormInput } from '@/components'
import { patternApi, errorLogApi } from '@/api'

// Tree State
const treeData = ref([])
const treeLoading = ref(false)
const selectedServerId = ref(null)
const expandedPaths = ref([])
const selectedFile = ref(null)

// List State
const loading = ref(false)
const errors = ref([])
const totalElements = ref(0)
const totalPages = ref(0)
const currentPage = ref(0)
const pageSize = 100

// Sort State
const sortField = ref('occurredAt')
const sortDirection = ref('desc')

// Filters
const filters = reactive({
  patternId: '',
  severity: '',
  keyword: ''
})

// Options
const patternOptions = ref([])
const severityOptions = [
  { value: '', label: '전체' },
  { value: 'CRITICAL', label: 'CRITICAL' },
  { value: 'ERROR', label: 'ERROR' },
  { value: 'WARN', label: 'WARN' }
]

// Detail Modal
const showDetailModal = ref(false)
const selectedError = ref(null)

// Delete Modal
const showDeleteModal = ref(false)
const deleteServerId = ref(null)
const deleteFilePath = ref(null)
const deleteFileName = ref('')
const deleting = ref(false)
const deleteBtn = ref(null)

// Computed
const filteredTreeData = computed(() => {
  if (!selectedServerId.value) return treeData.value
  return treeData.value.filter(s => s.serverId === selectedServerId.value)
})

const filteredErrorCount = computed(() => {
  return filteredTreeData.value.reduce((sum, server) => sum + server.totalErrorCount, 0)
})

// Load tree data
const loadTree = async () => {
  treeLoading.value = true
  try {
    treeData.value = await errorLogApi.getTree()
    // 첫 번째 경로 자동 확장
    if (treeData.value.length > 0 && treeData.value[0].paths.length > 0) {
      expandedPaths.value = [treeData.value[0].serverId + ':' + treeData.value[0].paths[0].path]
    }
  } catch (e) {
    console.error('Failed to load tree:', e)
  } finally {
    treeLoading.value = false
  }
}

// Load options
const loadOptions = async () => {
  try {
    const patterns = await patternApi.getAll()
    patternOptions.value = [
      { value: '', label: '전체' },
      ...patterns.map(p => ({ value: p.id, label: p.name }))
    ]
  } catch (e) {
    console.error('Failed to load options:', e)
  }
}

// Server change
const onServerChange = () => {
  selectedFile.value = null
  expandedPaths.value = []
  // 선택된 서버의 첫 번째 경로 확장
  const serverData = filteredTreeData.value[0]
  if (serverData && serverData.paths.length > 0) {
    expandedPaths.value = [serverData.serverId + ':' + serverData.paths[0].path]
  }
  currentPage.value = 0
  search()
}

// Tree actions
const togglePath = (pathKey) => {
  const idx = expandedPaths.value.indexOf(pathKey)
  if (idx >= 0) {
    expandedPaths.value.splice(idx, 1)
  } else {
    expandedPaths.value.push(pathKey)
  }
}

const selectAll = () => {
  selectedFile.value = null
  currentPage.value = 0
  search()
}

const selectFile = (serverId, file) => {
  selectedFile.value = { serverId, ...file }
  currentPage.value = 0
  search()
}

const shortenPath = (path) => {
  if (path.length > 30) {
    return '...' + path.slice(-27)
  }
  return path
}

// Sort
const toggleSort = (field) => {
  if (sortField.value === field) {
    sortDirection.value = sortDirection.value === 'asc' ? 'desc' : 'asc'
  } else {
    sortField.value = field
    sortDirection.value = 'desc'
  }
  currentPage.value = 0
  search()
}

const getSortIcon = (field) => {
  if (sortField.value !== field) return '↕'
  return sortDirection.value === 'asc' ? '↑' : '↓'
}

// Search
const search = async () => {
  loading.value = true
  try {
    const params = {
      page: currentPage.value,
      size: pageSize,
      sort: `${sortField.value},${sortDirection.value}`
    }

    // 서버 필터 (드롭다운 선택 또는 파일 선택)
    if (selectedFile.value) {
      params.serverId = selectedFile.value.serverId
      params.filePath = selectedFile.value.filePath
    } else if (selectedServerId.value) {
      params.serverId = selectedServerId.value
    }
    
    if (filters.patternId) params.patternId = filters.patternId
    if (filters.severity) params.severity = filters.severity
    if (filters.keyword) params.keyword = filters.keyword

    const result = await errorLogApi.search(params)
    errors.value = result.content || []
    totalElements.value = result.totalElements || 0
    totalPages.value = result.totalPages || 0
  } catch (e) {
    console.error('Failed to search errors:', e)
    errors.value = []
  } finally {
    loading.value = false
  }
}

const resetFilters = () => {
  filters.patternId = ''
  filters.severity = ''
  filters.keyword = ''
  sortField.value = 'occurredAt'
  sortDirection.value = 'desc'
  currentPage.value = 0
  search()
}

const goToPage = (page) => {
  currentPage.value = page
  search()
}

// Delete
const confirmDeleteFile = (serverId, file) => {
  deleteServerId.value = serverId
  deleteFilePath.value = file.filePath
  deleteFileName.value = file.fileName
  showDeleteModal.value = true
  nextTick(() => {
    deleteBtn.value?.focus()
  })
}

const executeDelete = async () => {
  deleting.value = true
  try {
    await errorLogApi.deleteByFile(deleteServerId.value, deleteFilePath.value)
    showDeleteModal.value = false
    if (selectedFile.value && selectedFile.value.filePath === deleteFilePath.value) {
      selectedFile.value = null
    }
    await loadTree()
    search()
  } catch (e) {
    console.error('Failed to delete:', e)
    alert('삭제 실패')
  } finally {
    deleting.value = false
  }
}

// Detail
const showDetail = async (error) => {
  try {
    selectedError.value = await errorLogApi.getById(error.id)
    showDetailModal.value = true
  } catch (e) {
    selectedError.value = error
    showDetailModal.value = true
  }
}

// Export
const buildExportParams = () => {
  const params = new URLSearchParams()
  if (selectedFile.value) {
    params.append('serverId', selectedFile.value.serverId)
    params.append('filePath', selectedFile.value.filePath)
  } else if (selectedServerId.value) {
    params.append('serverId', selectedServerId.value)
  }
  if (filters.patternId) params.append('patternId', filters.patternId)
  if (filters.severity) params.append('severity', filters.severity)
  if (filters.keyword) params.append('keyword', filters.keyword)
  return params.toString()
}

const exportHtml = () => {
  const params = buildExportParams()
  window.open(`/api/export/html?${params}`, '_blank')
}

const exportTxt = () => {
  const params = buildExportParams()
  window.open(`/api/export/txt?${params}`, '_blank')
}

// Utils
const formatDate = (dateStr) => {
  if (!dateStr) return '-'
  return new Date(dateStr).toLocaleString('ko-KR', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
  })
}

const truncate = (str, len) => {
  if (!str) return ''
  return str.length > len ? str.substring(0, len) + '...' : str
}

const getSeverityVariant = (severity) => {
  const map = { 'CRITICAL': 'critical', 'ERROR': 'error', 'WARN': 'warn' }
  return map[severity] || 'default'
}

onMounted(() => {
  loadTree()
  loadOptions()
  search()
})
</script>

<style scoped>
.layout-container {
  display: flex;
  gap: 20px;
  height: calc(100vh - 120px);
}

/* 트리 패널 */
.tree-panel {
  width: 360px;
  min-width: 360px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
  display: flex;
  flex-direction: column;
}

.tree-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.tree-header h4 {
  margin: 0;
  font-size: 15px;
}

.server-select {
  padding: 12px 16px;
  border-bottom: 1px solid #eee;
}

.server-select select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 14px;
  background: white;
  cursor: pointer;
}

.server-select select:focus {
  outline: none;
  border-color: #3498db;
}

.tree-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}

.tree-loading,
.tree-empty {
  padding: 20px;
  text-align: center;
  color: #666;
  font-size: 13px;
}

.tree-item {
  display: flex;
  align-items: center;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  transition: background 0.15s;
}

.tree-item:hover {
  background: #f5f5f5;
}

.tree-item.active {
  background: #e3f2fd;
  font-weight: 500;
}

.tree-toggle {
  width: 16px;
  font-size: 10px;
  color: #999;
  margin-right: 4px;
}

.tree-icon {
  margin-right: 8px;
  font-size: 14px;
}

.tree-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tree-count {
  font-size: 12px;
  color: #666;
  background: #f0f0f0;
  padding: 2px 8px;
  border-radius: 10px;
  margin-left: 8px;
}

.tree-count-detail {
  display: flex;
  gap: 4px;
  margin-left: 8px;
}

.tree-count-detail span {
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 8px;
  font-weight: 500;
}

.tree-count-detail .critical {
  background: #f3e5f5;
  color: #9b59b6;
}

.tree-count-detail .error {
  background: #ffebee;
  color: #e74c3c;
}

.tree-count-detail .warn {
  background: #fff8e1;
  color: #f39c12;
}

.tree-delete {
  opacity: 0;
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  font-size: 12px;
  transition: opacity 0.15s;
}

.tree-item:hover .tree-delete {
  opacity: 1;
}

.tree-delete:hover {
  transform: scale(1.1);
}

.tree-all {
  margin-bottom: 8px;
  border-bottom: 1px solid #eee;
  padding-bottom: 12px;
}

.tree-path {
  margin-bottom: 4px;
}

.tree-files {
  margin-left: 20px;
}

.tree-file-item {
  padding-left: 26px;
}

/* 목록 패널 */
.list-panel {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.list-panel :deep(.card) {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.list-panel :deep(.card-body) {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.card-header-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header-content h3 {
  margin: 0;
  font-size: 16px;
}

.header-actions {
  display: flex;
  gap: 8px;
}

.filters {
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
  margin-bottom: 16px;
  flex-shrink: 0;
}

.filter-row {
  display: grid;
  grid-template-columns: 1fr 1fr 2fr auto;
  gap: 16px;
  align-items: end;
}

.filter-actions {
  display: flex;
  gap: 8px;
  padding-bottom: 4px;
}

.results-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.results-header {
  margin-bottom: 12px;
  color: #666;
  font-size: 14px;
  flex-shrink: 0;
}

.table-wrapper {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

.error-table {
  width: 100%;
  border-collapse: collapse;
}

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

.error-table th {
  background: #f8f9fa;
  font-weight: 600;
  font-size: 13px;
  position: sticky;
  top: 0;
  z-index: 1;
}

.error-table th.sortable {
  cursor: pointer;
  user-select: none;
}

.error-table th.sortable:hover {
  background: #e9ecef;
}

.sort-icon {
  margin-left: 4px;
  color: #999;
  font-size: 12px;
}

.error-table tbody tr:hover {
  background: #fafafa;
}

.col-time { width: 160px; white-space: nowrap; }
.col-severity { width: 90px; }
.col-pattern { width: 100px; }
.col-summary { }

.summary-link {
  color: #333;
  text-decoration: none;
  cursor: pointer;
}

.summary-link:hover {
  color: #3498db;
  text-decoration: underline;
}

.empty-result,
.loading-result {
  padding: 40px;
  text-align: center;
  color: #666;
}

.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  padding: 16px 0;
  border-top: 1px solid #eee;
  flex-shrink: 0;
}

.page-info {
  font-size: 14px;
  color: #666;
}

/* 모달 */
.warning-text {
  color: #e74c3c;
  font-size: 13px;
  margin-top: 8px;
}

.error-detail {
  max-height: 60vh;
  overflow-y: auto;
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

.detail-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.detail-item label {
  font-size: 12px;
  color: #666;
}

.file-path {
  word-break: break-all;
  font-family: monospace;
  font-size: 12px;
}

.detail-section {
  margin-bottom: 16px;
}

.detail-section label {
  display: block;
  font-size: 12px;
  color: #666;
  margin-bottom: 8px;
}

.summary-box {
  padding: 12px;
  background: #f8f9fa;
  border-radius: 4px;
  font-size: 14px;
}

.context-box {
  padding: 12px;
  background: #1e1e1e;
  color: #d4d4d4;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.6;
  overflow-x: auto;
  white-space: pre;
  margin: 0;
  max-height: 250px;
}
</style>
