package com.qaup.collision.area.service;

import com.qaup.collision.common.model.spatial.AirportArea;
import com.qaup.collision.area.model.AreaInfo;
import com.qaup.collision.area.model.AreaType;
import com.qaup.collision.common.model.repository.AirportAreaRepository;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yaml.snakeyaml.Yaml;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 区域配置导入服务 - 将YAML配置文件中的区域数据导入到PostGIS数据库
 * 
 * 主要功能：
 * 1. 解析YAML格式的区域配置文件
 * 2. 转换JTS几何对象为PostGIS兼容格式
 * 3. 批量导入区域数据到数据库
 * 4. 处理重复数据和增量更新
 * 5. 数据验证和异常处理
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AreaConfigImportService {

    private final AirportAreaRepository airportAreaRepository;
    private final GeometryFactory geometryFactory = new GeometryFactory();

    /**
     * 应用启动后自动导入区域配置
     * 仅在数据库中没有区域数据时执行导入
     */
    @EventListener(ApplicationReadyEvent.class)
    public void autoImportOnStartup() {
        try {
            long existingCount = airportAreaRepository.count();
            if (existingCount == 0) {
                log.info("数据库中未发现区域配置，开始自动导入YAML配置...");
                importFromYaml("config/airport_areas.yaml");
            } else {
                log.info("数据库中已存在 {} 个区域配置，跳过自动导入", existingCount);
            }
        } catch (Exception e) {
            log.warn("自动导入区域配置失败，请手动检查配置文件", e);
        }
    }

    /**
     * 从YAML文件导入区域配置
     * 
     * @param yamlFilePath YAML文件路径（相对于classpath）
     * @return 导入的区域数量
     */
    @Transactional
    public int importFromYaml(String yamlFilePath) {
        try {
            log.info("开始从YAML文件导入区域配置: {}", yamlFilePath);
            
            // 读取YAML文件
            ClassPathResource resource = new ClassPathResource(yamlFilePath);
            if (!resource.exists()) {
                log.warn("YAML配置文件不存在: {}", yamlFilePath);
                return 0;
            }

            List<AreaInfo> areaInfos = parseYamlFile(resource.getInputStream());
            if (areaInfos.isEmpty()) {
                log.warn("YAML文件中未发现有效的区域配置");
                return 0;
            }

            // 转换并保存到数据库
            int importedCount = 0;
            for (AreaInfo areaInfo : areaInfos) {
                try {
                    AirportArea airportArea = convertToAirportArea(areaInfo);
                    
                    // 检查是否已存在
                    if (airportAreaRepository.findByName(airportArea.getName()).isPresent()) {
                        log.debug("区域 {} 已存在，跳过导入", airportArea.getName());
                        continue;
                    }
                    
                    airportAreaRepository.save(airportArea);
                    importedCount++;
                    log.debug("成功导入区域: {}", airportArea.getName());
                    
                } catch (Exception e) {
                    log.error("导入区域配置失败: {}", areaInfo.getId(), e);
                }
            }
            
            log.info("区域配置导入完成，成功导入 {} 个区域", importedCount);
            return importedCount;
            
        } catch (Exception e) {
            log.error("导入YAML区域配置时发生异常", e);
            throw new RuntimeException("区域配置导入失败", e);
        }
    }

    /**
     * 强制重新导入所有区域配置
     * 会清空现有数据并重新导入
     * 
     * @param yamlFilePath YAML文件路径
     * @return 导入的区域数量
     */
    @Transactional
    public int forceReimport(String yamlFilePath) {
        log.info("开始强制重新导入区域配置，将清空现有数据");
        
        // 清空现有数据
        long deletedCount = airportAreaRepository.count();
        airportAreaRepository.deleteAll();
        log.info("已清空 {} 个现有区域配置", deletedCount);
        
        // 重新导入
        return importFromYaml(yamlFilePath);
    }

    /**
     * 增量更新区域配置
     * 只更新变更的区域，不影响现有数据
     * 
     * @param yamlFilePath YAML文件路径
     * @return 更新的区域数量
     */
    @Transactional
    public int incrementalUpdate(String yamlFilePath) {
        try {
            log.info("开始增量更新区域配置");
            
            ClassPathResource resource = new ClassPathResource(yamlFilePath);
            if (!resource.exists()) {
                log.warn("YAML配置文件不存在: {}", yamlFilePath);
                return 0;
            }

            List<AreaInfo> areaInfos = parseYamlFile(resource.getInputStream());
            int updatedCount = 0;

            for (AreaInfo areaInfo : areaInfos) {
                try {
                    AirportArea newArea = convertToAirportArea(areaInfo);
                    
                    // 检查是否已存在
                    Optional<AirportArea> existingOpt = airportAreaRepository.findByName(newArea.getName());
                    if (existingOpt.isPresent()) {
                        // 更新现有区域
                        AirportArea existing = existingOpt.get();
                        updateExistingArea(existing, newArea);
                        airportAreaRepository.save(existing);
                        updatedCount++;
                        log.debug("更新区域: {} - {}", existing.getName(), existing.getName());
                    } else {
                        // 新增区域
                        airportAreaRepository.save(newArea);
                        updatedCount++;
                        log.debug("新增区域: {} - {}", newArea.getName(), newArea.getName());
                    }
                    
                } catch (Exception e) {
                    log.error("更新区域配置失败: {}", areaInfo.getId(), e);
                }
            }
            
            log.info("增量更新完成，处理 {} 个区域", updatedCount);
            return updatedCount;
            
        } catch (Exception e) {
            log.error("增量更新区域配置时发生异常", e);
            throw new RuntimeException("区域配置增量更新失败", e);
        }
    }

    /**
     * 解析YAML文件并转换为AreaInfo列表
     */
    @SuppressWarnings("unchecked")
    private List<AreaInfo> parseYamlFile(InputStream inputStream) throws IOException {
        Yaml yaml = new Yaml();
        Map<String, Object> data = yaml.load(inputStream);
        
        // 这里需要根据实际的YAML结构进行解析
        // 假设YAML结构为: { "areas": [ { area_configs... } ] }
        Object areasObj = data.get("areas");
        if (areasObj instanceof List) {
            List<Map<String, Object>> areasList = (List<Map<String, Object>>) areasObj;
            return areasList.stream()
                    .map(this::parseAreaFromMap)
                    .filter(area -> area != null)
                    .toList();
        }
        
        return List.of();
    }

    /**
     * 从Map解析单个区域配置
     */
    private AreaInfo parseAreaFromMap(Map<String, Object> areaMap) {
        try {
            AreaInfo areaInfo = new AreaInfo();
            
            // 基本信息
            areaInfo.setId((String) areaMap.get("id"));
            areaInfo.setName((String) areaMap.get("name"));
            areaInfo.setDescription((String) areaMap.get("description"));
            
            // 区域类型
            String typeStr = (String) areaMap.get("type");
            if (typeStr != null) {
                try {
                    areaInfo.setType(AreaType.valueOf(typeStr.toUpperCase()));
                } catch (IllegalArgumentException e) {
                    log.warn("未知的区域类型: {}", typeStr);
                }
            }
            
            // 几何边界（假设是坐标点数组）
            Object boundaryObj = areaMap.get("boundary");
            if (boundaryObj instanceof List<?>) {
                List<?> list = (List<?>) boundaryObj;
                if (!list.isEmpty() && list.get(0) instanceof List) {
                    @SuppressWarnings("unchecked")
                    List<List<Double>> coordinates = (List<List<Double>>) boundaryObj;
                    Polygon polygon = createPolygonFromCoordinates(coordinates);
                    areaInfo.setBoundary(polygon);
                }
            }
            
            // 限制信息
            Object speedLimitObj = areaMap.get("speedLimitKph");
            if (speedLimitObj instanceof Number) {
                areaInfo.setSpeedLimitKph(((Number) speedLimitObj).doubleValue());
            }
            
            Object restrictedObj = areaMap.get("restricted");
            if (restrictedObj instanceof Boolean) {
                areaInfo.setRestricted((Boolean) restrictedObj);
            }
            
            return areaInfo;
            
        } catch (Exception e) {
            log.error("解析区域配置失败: {}", areaMap.get("id"), e);
            return null;
        }
    }

    /**
     * 从坐标列表创建多边形
     */
    private Polygon createPolygonFromCoordinates(List<List<Double>> coordinates) {
        if (coordinates == null || coordinates.size() < 3) {
            throw new IllegalArgumentException("多边形至少需要3个坐标点");
        }
        
        // 确保多边形闭合
        if (!coordinates.get(0).equals(coordinates.get(coordinates.size() - 1))) {
            coordinates.add(coordinates.get(0));
        }
        
        Coordinate[] coords = coordinates.stream()
                .map(coord -> new Coordinate(coord.get(0), coord.get(1)))
                .toArray(Coordinate[]::new);
        
        return geometryFactory.createPolygon(coords);
    }

    /**
     * 将AreaInfo转换为AirportArea实体
     */
    private AirportArea convertToAirportArea(AreaInfo areaInfo) {
        AirportArea airportArea = new AirportArea();
        
        // 基本信息
        airportArea.setName(areaInfo.getName());
        airportArea.setDescription(areaInfo.getDescription());
        airportArea.setType(convertAreaType(areaInfo.getType()));
        
        // 几何边界
        airportArea.setBoundary((Polygon) areaInfo.getBoundary());
        
        // 默认值
        airportArea.setEnabled(true);
        airportArea.setPriority(1);
        airportArea.setCreatedAt(LocalDateTime.now());
        airportArea.setUpdatedAt(LocalDateTime.now());
        
        return airportArea;
    }

    /**
     * 转换区域类型枚举
     */
    private String convertAreaType(AreaType oldType) {
        if (oldType == null) {
            return "OTHER";
        }
        
        return oldType.name();
    }

    /**
     * 更新现有区域的属性
     */
    private void updateExistingArea(AirportArea existing, AirportArea newArea) {
        existing.setName(newArea.getName());
        existing.setDescription(newArea.getDescription());
        existing.setType(newArea.getType());
        existing.setBoundary(newArea.getBoundary());
        existing.setUpdatedAt(LocalDateTime.now());
    }

    /**
     * 验证导入结果
     * 
     * @return 验证报告
     */
    public String validateImportedData() {
        StringBuilder report = new StringBuilder();
        
        long totalCount = airportAreaRepository.count();
        report.append("数据库中总计区域数量: ").append(totalCount).append("\n");
        
        // 按类型统计
        for (AreaType type : 
             AreaType.values()) {
            long count = airportAreaRepository.countByType(type.name());
            if (count > 0) {
                report.append("  ").append(type.name()).append(": ").append(count).append("\n");
            }
        }
        
        // 检查启用状态
        long enabledCount = airportAreaRepository.countByEnabled(true);
        long disabledCount = airportAreaRepository.countByEnabled(false);
        report.append("启用状态: 启用=").append(enabledCount).append(", 禁用=").append(disabledCount).append("\n");
        
        return report.toString();
    }
} 