<template>
  <div class="grid-management-container">
    <!-- Page Header -->
    <div class="page-header">
      <h2>网格地图</h2>
      <div class="header-actions">
        <el-button type="primary" @click="refreshData" :loading="loading || isLoadingWorkers" icon="Refresh">
          刷新数据
        </el-button>
      </div>
    </div>

    <!-- Main Content -->
    <div class="main-content-grid">
      <!-- Grid Map Area -->
      <div class="map-area" v-loading="loading">
        <div v-if="error" class="error-message">
          <el-alert title="地图数据加载失败" :description="error" type="error" show-icon :closable="false" />
          <el-button @click="fetchAllGrids" type="primary" class="retry-button">重试</el-button>
        </div>
        <svg v-else-if="displayGrids.length" :width="svgDimensions.width" :height="svgDimensions.height" class="grid-svg">
          <defs>
            <pattern id="grid-pattern" :width="CELL_SIZE" :height="CELL_SIZE" patternUnits="userSpaceOnUse">
              <path :d="`M ${CELL_SIZE} 0 L 0 0 0 ${CELL_SIZE}`" fill="none" stroke="#e9e9e9" stroke-width="0.5" />
            </pattern>
            
            <!-- Softer Gradient for the path -->
            <linearGradient id="soft-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
              <stop offset="0%" style="stop-color:#89f7fe; stop-opacity:1" /> <!-- Light Sky Blue -->
              <stop offset="100%" style="stop-color:#66a6ff; stop-opacity:1" /> <!-- Soft Lavender Blue -->
            </linearGradient>

          </defs>
          <rect :width="svgDimensions.width" :height="svgDimensions.height" fill="url(#grid-pattern)" />

          <g v-for="grid in displayGrids" :key="grid.id">
            <!-- Replace rect with foreignObject to allow for CSS pseudo-elements -->
            <foreignObject
              :x="grid.displayX * CELL_SIZE"
              :y="grid.displayY * CELL_SIZE"
              :width="CELL_SIZE"
              :height="CELL_SIZE"
            >
              <div
                xmlns="http://www.w3.org/1999/xhtml"
                class="grid-cell-wrapper"
                @click="selectGrid(grid)"
              >
                <div
                  :class="{
                    'grid-cell': true,
                    'selected': selectedGrid && selectedGrid.id === grid.id,
                    'is-path': pathInfo.pathSet.has(`${grid.gridX},${grid.gridY}`),
                    'is-start': pathInfo.start === `${grid.gridX},${grid.gridY}`,
                    'is-end': pathInfo.end === `${grid.gridX},${grid.gridY}`
                  }"
                  :style="{
                    'animation-delay': `${(pathInfo.pathMap.get(`${grid.gridX},${grid.gridY}`) || 0) * 50}ms`,
                    'background-color': getGridFillColor(grid)
                  }"
                ></div>
              </div>
            </foreignObject>

            <!-- Path Number Text remains as SVG text -->
            <text
              v-if="pathInfo.pathSet.has(`${grid.gridX},${grid.gridY}`)"
              :x="grid.displayX * CELL_SIZE + CELL_SIZE / 2"
              :y="grid.displayY * CELL_SIZE + CELL_SIZE / 2"
              class="path-text"
              :style="{ 'animation-delay': `${(pathInfo.pathMap.get(`${grid.gridX},${grid.gridY}`) || 0) * 50}ms` }"
            >
              {{ (pathInfo.pathMap.get(`${grid.gridX},${grid.gridY}`) || 0) + 1 }}
            </text>
            <!-- Border Rendering -->
            <line v-if="getBorder(grid, 'top')" :x1="grid.displayX * CELL_SIZE" :y1="grid.displayY * CELL_SIZE" :x2="(grid.displayX + 1) * CELL_SIZE" :y2="grid.displayY * CELL_SIZE" class="border-line" />
            <line v-if="getBorder(grid, 'right')" :x1="(grid.displayX + 1) * CELL_SIZE" :y1="grid.displayY * CELL_SIZE" :x2="(grid.displayX + 1) * CELL_SIZE" :y2="(grid.displayY + 1) * CELL_SIZE" class="border-line" />
            <line v-if="getBorder(grid, 'bottom')" :x1="grid.displayX * CELL_SIZE" :y1="(grid.displayY + 1) * CELL_SIZE" :x2="(grid.displayX + 1) * CELL_SIZE" :y2="(grid.displayY + 1) * CELL_SIZE" class="border-line" />
            <line v-if="getBorder(grid, 'left')" :x1="grid.displayX * CELL_SIZE" :y1="grid.displayY * CELL_SIZE" :x2="grid.displayX * CELL_SIZE" :y2="(grid.displayY + 1) * CELL_SIZE" class="border-line" />
          </g>
        </svg>
        <el-empty v-else description="没有可显示的网格数据" />
      </div>

      <!-- Details Sidebar -->
      <div class="sidebar-area">
        <el-card shadow="never" class="details-card">
          <template #header>
            <div class="card-header">
              <span>网格详情</span>
              <el-button v-if="selectedGrid && !isEditing && canEdit" type="primary" link @click="enterEditMode" icon="Edit">
                编辑
              </el-button>
            </div>
          </template>

          <div v-if="isSaving" v-loading="true" class="details-content-loading"></div>

          <div v-else-if="selectedGrid" class="details-content">
            <!-- Display Mode -->
            <template v-if="!isEditing">
              <p><strong>网格ID:</strong> {{ selectedGrid.id }}</p>
              <p><strong>城市:</strong> <el-tag :color="getCityColor(selectedGrid.cityName)" effect="light">{{ selectedGrid.cityName }}</el-tag></p>
              <p><strong>区县:</strong> {{ selectedGrid.districtName || 'N/A' }}</p>
              <p><strong>原始坐标:</strong> ({{ selectedGrid.gridX }}, {{ selectedGrid.gridY }})</p>
              <p><strong>是否为障碍物:</strong> <el-tag :type="selectedGrid.isObstacle ? 'danger' : 'success'">{{ selectedGrid.isObstacle ? '是' : '否' }}</el-tag></p>
              <p><strong>描述:</strong> {{ selectedGrid.description || '无' }}</p>
              <el-divider />
              <p><strong>负责人:</strong></p>
              <div v-if="selectedGridWorker">
                <el-tag effect="plain" type="info">
                  <el-icon><User /></el-icon>
                  {{ selectedGridWorker.name }} ({{ selectedGridWorker.phone }})
                </el-tag>
              </div>
              <div v-else>
                <el-tag type="warning">未分配</el-tag>
              </div>
            </template>

            <!-- Editing Mode -->
            <template v-else-if="canEdit">
              <el-form label-position="top" label-width="100px">
                <el-form-item label="是否为障碍物">
                  <el-switch v-model="editableIsObstacle" />
                </el-form-item>
                <el-form-item label="描述">
                  <el-input type="textarea" v-model="editableDescription" :rows="3" />
                </el-form-item>
                <el-form-item label="分配网格员">
                  <el-select 
                    v-model="selectedWorkerIdToAssign" 
                    placeholder="请选择网格员" 
                    clearable
                    filterable
                    style="width: 100%;"
                  >
                    <el-option label="-- 未分配 --" value="unassigned"></el-option>
                    <el-option
                      v-for="worker in allWorkers"
                      :key="worker.id"
                      :label="`${worker.name} (${worker.phone})`"
                      :value="worker.id"
                    />
                  </el-select>
                </el-form-item>
              </el-form>
              <div class="edit-actions">
                <el-button @click="cancelEdit">取消</el-button>
                <el-button type="primary" @click="saveChanges" :loading="isSaving">保存</el-button>
              </div>
            </template>
          </div>
          <el-empty v-else description="请在左侧地图上选择一个网格" />
        </el-card>

        <!-- Pathfinding Card -->
        <el-card shadow="never" class="details-card pathfinding-card">
          <template #header>
            <div class="card-header">
              <span>路径规划</span>
            </div>
          </template>
          <div v-if="!authStore.user" class="pathfinding-content">
             <el-empty description="请先登录以使用路径规划功能" />
          </div>
          <div v-else class="pathfinding-content">
            <el-form label-position="top" :model="pathfinding" @submit.prevent="handleFindPath">
              <el-form-item label="起点坐标 (X, Y)">
                <div style="display: flex; gap: 8px; width: 100%;">
                  <el-input-number v-model="pathfinding.startX" :controls="false" placeholder="X" style="width: 100%" />
                  <el-input-number v-model="pathfinding.startY" :controls="false" placeholder="Y" style="width: 100%" />
                </div>
                <small class="form-help-text">默认为您分配的网格，或 (0,0)</small>
              </el-form-item>
              <el-form-item label="终点坐标 (X, Y)">
                 <div style="display: flex; gap: 8px; width: 100%;">
                  <el-input-number v-model="pathfinding.endX" :controls="false" placeholder="X" style="width: 100%" />
                  <el-input-number v-model="pathfinding.endY" :controls="false" placeholder="Y" style="width: 100%" />
                </div>
                 <small class="form-help-text">点击地图上的网格可快速设置终点</small>
              </el-form-item>
            </el-form>
            <div class="pathfinding-actions">
              <el-button @click="clearPath" :disabled="!calculatedPath.length">清除路径</el-button>
              <el-button type="primary" @click="handleFindPath" :loading="isPathfindingLoading">规划路径</el-button>
            </div>
          </div>
        </el-card>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useAuthStore } from '@/stores/auth';
import type { Grid, UserAccount } from '@/api/types';
import { getGrids } from '@/api/dashboard';
import { getAllGridWorkers } from '@/api/personnel';
import { updateGrid, assignWorkerByCoordinates, unassignWorkerByCoordinates } from '@/api/grid';
import { findPath, type Point, type PathfindingRequest } from '@/api/pathfinding';
import { User } from '@element-plus/icons-vue';

const CELL_SIZE = 25;
const PADDING_CELLS = 2;

const authStore = useAuthStore();

// --- State ---
const gridData = ref<Grid[]>([]);
const allWorkers = ref<UserAccount[]>([]);
const loading = ref(false); // For main grid loading
const isLoadingWorkers = ref(false);
const isSaving = ref(false);
const error = ref<string | null>(null);
const selectedGrid = ref<DisplayGrid | null>(null);
const isEditing = ref(false);

// --- Editing State ---
const editableDescription = ref('');
const editableIsObstacle = ref(false);
const selectedWorkerIdToAssign = ref<number | 'unassigned' | null>(null);

// --- Pathfinding State ---
const pathfinding = ref({
  startX: 0,
  startY: 0,
  endX: undefined as number | undefined,
  endY: undefined as number | undefined
});
const calculatedPath = ref<Point[]>([]);
const isPathfindingLoading = ref(false);

// --- Data Fetching & Refresh ---
const fetchAllGrids = async () => {
  loading.value = true;
  error.value = null;
  selectedGrid.value = null; // Reset selection
  try {
    const response = await getGrids();
    gridData.value = Array.isArray(response) ? response : (response as any).content || [];
  } catch (e: any) {
    const errorMessage = e.message || '获取网格数据时发生未知错误';
    error.value = errorMessage;
    ElMessage.error(errorMessage);
  } finally {
    loading.value = false;
  }
};

const fetchAllWorkers = async () => {
  const userRole = authStore.user?.role;
  // 只有管理员和主管需要获取完整的网格员列表用于管理
  if (userRole !== 'ADMIN' && userRole !== 'SUPERVISOR') {
    allWorkers.value = []; // 其他角色无需加载网格员数据
    return;
  }

  isLoadingWorkers.value = true;
  try {
    allWorkers.value = await getAllGridWorkers();
  } catch (e: any) {
    ElMessage.error('获取网格员列表失败: ' + e.message);
  } finally {
    isLoadingWorkers.value = false;
  }
};

const refreshData = async () => {
  await Promise.all([fetchAllGrids(), fetchAllWorkers()]);
  ElMessage.success('数据已刷新');
  // Set default start point for pathfinding if user has one
  const user = authStore.user;
  if (user && typeof user.gridX === 'number' && typeof user.gridY === 'number') {
    pathfinding.value.startX = user.gridX;
    pathfinding.value.startY = user.gridY;
  }
};

onMounted(() => {
  refreshData();
});

// --- Computed Properties ---
const canEdit = computed(() => {
  const role = authStore.user?.role;
  return role === 'ADMIN' || role === 'SUPERVISOR';
});

const workersByCoord = computed<Map<string, UserAccount>>(() => {
  const map = new Map<string, UserAccount>();
  allWorkers.value.forEach(worker => {
    if (worker.gridX !== null && worker.gridY !== null) {
      map.set(`${worker.gridX},${worker.gridY}`, worker);
    }
  });
  return map;
});

const selectedGridWorker = computed<UserAccount | undefined>(() => {
  if (!selectedGrid.value || !allWorkers.value.length) {
    return undefined;
  }
  return allWorkers.value.find(
    worker => worker.gridX === selectedGrid.value?.gridX && worker.gridY === selectedGrid.value?.gridY
  );
});

const pathInfo = computed(() => {
  const pathSet = new Set<string>();
  const pathMap = new Map<string, number>(); // Stores coordinate -> index for animation delay
  let start = '';
  let end = '';

  if (calculatedPath.value.length > 0) {
    calculatedPath.value.forEach((point, index) => {
      const coord = `${point.x},${point.y}`;
      pathSet.add(coord);
      pathMap.set(coord, index);
    });
    const startPoint = calculatedPath.value[0];
    const endPoint = calculatedPath.value[calculatedPath.value.length - 1];
    start = `${startPoint.x},${startPoint.y}`;
    end = `${endPoint.x},${endPoint.y}`;
  }
  
  return { pathSet, pathMap, start, end };
});

// --- City Color Logic ---
const cityColors = ref<Map<string, string>>(new Map());
const getCityColor = (cityName: string): string => {
  if (!cityColors.value.has(cityName)) {
    let hash = 0;
    for (let i = 0; i < cityName.length; i++) {
      hash = cityName.charCodeAt(i) + ((hash << 5) - hash);
    }
    const color = `hsl(${hash % 360}, 80%, 85%)`;
    cityColors.value.set(cityName, color);
  }
  return cityColors.value.get(cityName)!;
};

const getGridFillColor = (grid: Grid): string => {
  const isPath = pathInfo.value.pathSet.has(`${grid.gridX},${grid.gridY}`);
  // If it's part of the path, let the CSS class handle the gradient background
  if (isPath) {
    return 'transparent';
  }
  if (grid.isObstacle) {
    return '#000000'; // Black for obstacles
  }
  if (workersByCoord.value.has(`${grid.gridX},${grid.gridY}`)) {
    return '#FF0000'; // Red for grids with workers
  }
  return getCityColor(grid.cityName);
};

// --- Display Logic ---
interface DisplayGrid extends Grid {
  displayX: number;
  displayY: number;
}

const displayGrids = computed<DisplayGrid[]>(() => {
  if (!gridData.value.length) return [];

  // Determine the top-left corner of the entire map to normalize coordinates
  const minX = Math.min(...gridData.value.map(g => g.gridX));
  const minY = Math.min(...gridData.value.map(g => g.gridY));

  // Render all grids based on their absolute positions, normalized to start at (0,0)
  return gridData.value.map(grid => ({
    ...grid,
    displayX: grid.gridX - minX,
    displayY: grid.gridY - minY,
  }));
});

const gridMap = computed(() => {
  const map = new Map<string, DisplayGrid>();
  displayGrids.value.forEach(grid => {
    map.set(`${grid.displayX},${grid.displayY}`, grid);
  });
  return map;
});

const svgDimensions = computed(() => {
  if (!displayGrids.value.length) return { width: 0, height: 0 };
  const maxX = Math.max(...displayGrids.value.map(g => g.displayX));
  const maxY = Math.max(...displayGrids.value.map(g => g.displayY));
  return {
    width: (maxX + 1) * CELL_SIZE,
    height: (maxY + 1) * CELL_SIZE,
  };
});

const getBorder = (grid: DisplayGrid, side: 'top' | 'right' | 'bottom' | 'left'): boolean => {
  const { displayX, displayY, cityName } = grid;
  let neighbor: DisplayGrid | undefined;
  switch (side) {
    case 'top':
      neighbor = gridMap.value.get(`${displayX},${displayY - 1}`);
      break;
    case 'right':
      neighbor = gridMap.value.get(`${displayX + 1},${displayY}`);
      break;
    case 'bottom':
      neighbor = gridMap.value.get(`${displayX},${displayY + 1}`);
      break;
    case 'left':
      neighbor = gridMap.value.get(`${displayX - 1},${displayY}`);
      break;
  }
  return !neighbor || neighbor.cityName !== cityName;
};

const selectGrid = (grid: DisplayGrid) => {
  selectedGrid.value = grid;

  // Also set pathfinding endpoint for convenience
  pathfinding.value.endX = grid.gridX;
  pathfinding.value.endY = grid.gridY;

  // If in edit mode, populate fields
  if (isEditing.value) {
    // populateEditFields(grid); // This function was removed, keep it commented or remove it if not needed
  }
};

// --- Editing Logic ---
const enterEditMode = () => {
  if (!selectedGrid.value) return;
  isEditing.value = true;
  editableDescription.value = selectedGrid.value.description || '';
  editableIsObstacle.value = selectedGrid.value.isObstacle;
  selectedWorkerIdToAssign.value = selectedGridWorker.value?.id ?? 'unassigned';
};

const cancelEdit = () => {
  isEditing.value = false;
};

const saveChanges = async () => {
  if (!selectedGrid.value) return;
  isSaving.value = true;

  try {
    const { id, gridX, gridY } = selectedGrid.value;
    let needsGridRefresh = false;
    let needsWorkerRefresh = false;
    
    // 1. Update grid details (obstacle, description)
    const originalDescription = selectedGrid.value.description || '';
    if (editableIsObstacle.value !== selectedGrid.value.isObstacle || editableDescription.value !== originalDescription) {
      await updateGrid(id, {
        isObstacle: editableIsObstacle.value,
        description: editableDescription.value,
      });
      needsGridRefresh = true;
    }

    // 2. Update worker assignment
    const originalWorkerId = selectedGridWorker.value?.id;
    const newWorkerId = selectedWorkerIdToAssign.value;
    
    if (newWorkerId !== (originalWorkerId ?? 'unassigned')) {
      if (newWorkerId === 'unassigned') {
        await unassignWorkerByCoordinates(gridX, gridY);
      } else if (newWorkerId) {
        await assignWorkerByCoordinates(gridX, gridY, newWorkerId);
      }
      needsWorkerRefresh = true;
    }

    ElMessage.success('网格信息更新成功！');
    
    // Refresh data
    if (needsGridRefresh) await fetchAllGrids();
    if (needsWorkerRefresh) await fetchAllWorkers();

    isEditing.value = false;
  } catch (e: any) {
    ElMessage.error('保存失败: ' + (e.response?.data?.message || e.message));
  } finally {
    isSaving.value = false;
  }
};

// --- Pathfinding Methods ---
const handleFindPath = async () => {
  if (typeof pathfinding.value.endX !== 'number' || typeof pathfinding.value.endY !== 'number') {
    ElMessage.warning('请输入有效的终点坐标。');
    return;
  }

  isPathfindingLoading.value = true;
  calculatedPath.value = []; // Clear previous path

  const request: PathfindingRequest = {
    startX: pathfinding.value.startX,
    startY: pathfinding.value.startY,
    endX: pathfinding.value.endX,
    endY: pathfinding.value.endY,
  };

  try {
    const path = await findPath(request);
    if (path && path.length > 0) {
      calculatedPath.value = path;
      ElMessage.success(`路径规划成功，共 ${path.length} 步。`);
    } else {
      ElMessage.error('未找到有效路径，请检查起终点或地图障碍物。');
    }
  } catch (e: any) {
    ElMessage.error('路径规划失败: ' + (e.response?.data?.message || e.message));
  } finally {
    isPathfindingLoading.value = false;
  }
};

const clearPath = () => {
    calculatedPath.value = [];
    ElMessage.info('路径已清除。');
};
</script>

<style scoped>
.grid-management-container {
  padding: 20px;
  background-color: #f7f8fa;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  flex-shrink: 0;
}

.page-header h2 {
  margin: 0;
  font-size: 24px;
}

.main-content-grid {
  display: flex;
  gap: 20px;
  flex: 1;
  overflow: hidden;
}

.map-area {
  flex: 3;
  background-color: #fff;
  border-radius: 8px;
  padding: 10px;
  overflow: auto;
  border: 1px solid #e9e9e9;
}

.sidebar-area {
  flex: 1;
  min-width: 300px;
}

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

.grid-svg {
  display: block;
}

.grid-cell-wrapper {
  width: 100%;
  height: 100%;
  cursor: pointer;
}

.grid-cell {
  width: 100%;
  height: 100%;
  background-color: transparent; /* Default state */
  border: 0.5px solid #dcdfe6;
  box-sizing: border-box;
  transition: all 0.2s ease;
  position: relative;
  overflow: hidden; /* Important for pseudo-element animation */
}

.grid-cell:hover {
  filter: brightness(0.9);
}

.grid-cell.selected {
  border: 2px solid #ff4d4f;
}

.grid-cell.is-start {
  background-color: #00e676;
  box-shadow: 0 0 8px #00e676, inset 0 0 5px rgba(255,255,255,0.7);
  border-color: #fff;
}

.grid-cell.is-end {
  background-color: #ff5252;
  box-shadow: 0 0 8px #ff5252, inset 0 0 5px rgba(255,255,255,0.7);
  border-color: #fff;
}

.grid-cell.is-path {
  background-image: linear-gradient(to bottom right, #89f7fe, #66a6ff);
  border-color: #66a6ff;
  opacity: 0;
  animation: draw-path-reveal 0.4s forwards ease-out;
}

.grid-cell.is-path::before {
  content: '';
  position: absolute;
  top: 0;
  left: -150%;
  width: 50%;
  height: 100%;
  background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0) 100%);
  transform: skewX(-25deg);
  animation: light-sweep 1.2s ease-in-out 3 forwards; /* Play 3 times and stop */
  animation-delay: inherit; /* Inherit delay from parent */
}

@keyframes light-sweep {
  100% {
    left: 150%;
  }
}

.path-text {
  font-size: 10px;
  fill: white;
  font-weight: bold;
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
  animation: draw-path-reveal 0.4s forwards ease-out;
}

.border-line {
    stroke: #000;
    stroke-width: 2.5px;
    margin-top: 15px;
    width: 100%; /* Ensure it takes full width */
}

.error-message {
  padding: 20px;
}

.retry-button {
  margin-top: 15px;
}

.details-content p {
  margin: 0 0 12px;
  color: #606266;
  margin-top: 4px;
  line-height: 1.2;
  width: 100%; /* Ensure it takes full width */
}

.details-content p strong {
    color: #303133;
    margin-right: 8px;
}

.details-content-loading {
  height: 200px;
}

.edit-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
}

.pathfinding-card {
  margin-top: 20px;
}

.pathfinding-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.form-help-text {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
  line-height: 1.2;
  width: 100%; /* Ensure it takes full width */
}

@keyframes draw-path-reveal {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes pulse {
  0%, 100% {
    filter: brightness(1);
    transform: scale(1);
  }
  50% {
    filter: brightness(1.7);
    transform: scale(1.05);
  }
}
</style>