package com.qaup.collision.datacollector.dao;


import com.qaup.collision.common.model.Aircraft;
import com.qaup.collision.common.model.AirportVehicle;
import com.qaup.collision.common.model.UnmannedVehicle;
import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.common.model.dto.Response;
import com.qaup.collision.datacollector.service.AuthService;
import com.qaup.collision.datacollector.dto.AircraftRouteDTO;
import com.qaup.collision.datacollector.dto.AircraftStatusDTO;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.PrecisionModel;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@Component
public class DataCollectorDao {

    // 无人车厂商数据源相关配置
    @Value("${data.collector.vehicle-api.base-url}")
    private String vehicleBaseUrl;

    @Value("${data.collector.vehicle-api.endpoints.vehicle-location}")
    private String vehicleLocationEndpoint;


    private final RestTemplate restTemplate;
    private final AuthService authService;
    private final GeometryFactory geometryFactory;

    @Autowired
    public DataCollectorDao(RestTemplate restTemplate, AuthService authService) {
        this.restTemplate = restTemplate;
        this.authService = authService;
        this.geometryFactory = new GeometryFactory(new PrecisionModel(), 4326); // SRID 4326 for WGS84
    }


    public List<Aircraft> collectAircraftData(String endpoint, String baseUrl) {
        try {
            String url = UriComponentsBuilder
                    .fromUriString(baseUrl)
                    .path(endpoint)
                    .toUriString();

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", authService.getToken());
            HttpEntity<Void> requestEntity = new HttpEntity<>(headers);

            ResponseEntity<Response<List<ExternalAircraftData>>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    requestEntity,
                    new ParameterizedTypeReference<Response<List<ExternalAircraftData>>>() {}
            );

            if (response.getStatusCode().is2xxSuccessful()) {
                Response<List<ExternalAircraftData>> responseBody = response.getBody();
                if (responseBody != null && responseBody.getData() != null) {
                    List<Aircraft> processedAircrafts = responseBody.getData().stream().map(rawData -> {
                        if (rawData.getFlightNo() == null || rawData.getLongitude() == null || rawData.getLatitude() == null) {
                            log.warn("原始航空器数据缺失必要字段 (flightNo, longitude, latitude)，跳过处理: {}", rawData);
                            return null;
                        }
                        Aircraft aircraft = new Aircraft();
                        aircraft.setObjectId(rawData.getFlightNo());
                        aircraft.setObjectName(rawData.getFlightNo()); // 使用 flightNo 作为 objectName
                        aircraft.setCurrentPosition(geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(rawData.getLongitude(), rawData.getLatitude())));
                        // 外部API中没有直接的速度和方向，如果需要，可以在DataCollectorService中计算或使用默认值
                        // 暂时设置为0.0，DataCollectorService会处理
                        aircraft.setCurrentSpeed(0.0); 
                        aircraft.setCurrentHeading(0.0);
                        aircraft.setAltitude(0.0); // 假设默认高度为0，如果API有提供可以设置
                        return aircraft;
                    }).filter(java.util.Objects::nonNull).collect(Collectors.toList());

                    log.info("成功获取航空器数据，数量: {}", processedAircrafts.size());
                    return processedAircrafts;
                }
            }
        } catch (Exception e) {
            log.error("采集航空器数据失败: {}", endpoint, e);
        }
        return Collections.emptyList();
    }

    public List<AirportVehicle> collectVehicleData(String endpoint, String baseUrl) {
        try {
            String url = UriComponentsBuilder
                    .fromUriString(baseUrl)
                    .path(endpoint)
                    .toUriString();

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", authService.getToken());
            HttpEntity<Void> requestEntity = new HttpEntity<>(headers);

            ResponseEntity<Response<List<ExternalAirportVehicleData>>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    requestEntity,
                    new ParameterizedTypeReference<Response<List<ExternalAirportVehicleData>>>() {}
            );

            if (response.getStatusCode().is2xxSuccessful()) {
                Response<List<ExternalAirportVehicleData>> responseBody = response.getBody();
                if (responseBody != null && responseBody.getData() != null) {
                    List<AirportVehicle> processedVehicles = responseBody.getData().stream().map(rawData -> {
                        if (rawData.getVehicleNo() == null || rawData.getLongitude() == null || rawData.getLatitude() == null) {
                            log.warn("原始机场车辆数据缺失必要字段 (vehicleNo, longitude, latitude)，跳过处理: {}", rawData);
                            return null;
                        }
                        AirportVehicle vehicle = new AirportVehicle();
                        vehicle.setObjectId(rawData.getVehicleNo());
                        vehicle.setObjectName(rawData.getVehicleNo()); // 使用 vehicleNo 作为 objectName
                        vehicle.setCurrentPosition(geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(rawData.getLongitude(), rawData.getLatitude())));
                        vehicle.setCurrentSpeed(0.0); // 暂时设置为0.0，DataCollectorService会处理
                        vehicle.setCurrentHeading(0.0);
                        vehicle.setAltitude(0.0); // 假设默认高度为0，如果API有提供可以设置
                        return vehicle;
                    }).filter(java.util.Objects::nonNull).collect(Collectors.toList());

                    log.info("成功获取机场车辆数据，数量: {}", processedVehicles.size());
                    return processedVehicles;
                }
            }
        } catch (Exception e) {
            log.error("采集机场车辆数据失败: {}", endpoint, e);
        }
        return Collections.emptyList();
    }

    /**
     * 获取无人车位置信息
     * 数据来源：第2章 无人车位置上报 (/api/VehicleLocationInfo)
     * 说明：此接口专门用于获取无人车的实时位置数据，用于数据持久化
     * 
     * @return 无人车位置信息列表
     */
    public List<UnmannedVehicle> getVehicleLocationInfo() {
        try {
            String url = UriComponentsBuilder
                    .fromUriString(vehicleBaseUrl)
                    .path(vehicleLocationEndpoint)
                    .toUriString();

            log.debug("正在从 {} 获取无人车位置信息", url);
            
            HttpHeaders headers = new HttpHeaders();
            HttpEntity<Void> requestEntity = new HttpEntity<>(headers);

            ResponseEntity<List<ExternalUnmannedVehicleData>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    requestEntity,
                    new ParameterizedTypeReference<List<ExternalUnmannedVehicleData>>() {}
            );

            if (response.getStatusCode().is2xxSuccessful()) {
                List<ExternalUnmannedVehicleData> rawDataList = response.getBody();
                if (rawDataList != null) {
                    List<UnmannedVehicle> processedUnmannedVehicles = rawDataList.stream().map(rawData -> {
                        if (rawData.getVehicleID() == null || rawData.getLongitude() == null || rawData.getLatitude() == null) {
                            log.warn("原始无人车数据缺失必要字段 (vehicleID, longitude, latitude)，跳过处理: {}", rawData);
                            return null;
                        }
                        UnmannedVehicle unmannedVehicle = new UnmannedVehicle();
                        unmannedVehicle.setObjectId(rawData.getVehicleID());
                        unmannedVehicle.setObjectName(rawData.getVehicleID()); // 使用 vehicleID 作为 objectName
                        unmannedVehicle.setCurrentPosition(geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(rawData.getLongitude(), rawData.getLatitude())));
                        unmannedVehicle.setCurrentSpeed(rawData.getSpeed() != null ? rawData.getSpeed() * 3.6 : 0.0); // m/s to km/h
                        unmannedVehicle.setCurrentHeading(rawData.getDirection() != null ? Math.toDegrees(rawData.getDirection()) : 0.0); // 弧度 to 角度
                        unmannedVehicle.setAltitude(0.0); // 假设默认高度为0，如果API有提供可以设置
                        unmannedVehicle.setObjectType(MovingObjectType.UNMANNED_VEHICLE); // 显式设置对象类型
                        return unmannedVehicle;
                    }).filter(java.util.Objects::nonNull).collect(Collectors.toList());

                    log.info("成功获取无人车定位信息，数量: {}", processedUnmannedVehicles.size());
                    return processedUnmannedVehicles;
                }
            } 
        } catch (Exception e) {
            log.error("获取无人车定位信息时发生异常", e);
            return Collections.emptyList();
        }
        return Collections.emptyList();
    }

    // 内部 DTOs，精确匹配外部 API 接口返回的 JSON 结构

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class ExternalAircraftData {
        @JsonProperty("flightNo")
        private String flightNo;
        @JsonProperty("longitude")
        private Double longitude;
        @JsonProperty("latitude")
        private Double latitude;
        @JsonProperty("time")
        private Long time;
        // 其他可能存在的但我们不关心的字段将被 @JsonIgnoreProperties 忽略
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class ExternalAirportVehicleData {
        @JsonProperty("vehicleNo")
        private String vehicleNo;
        @JsonProperty("longitude")
        private Double longitude;
        @JsonProperty("latitude")
        private Double latitude;
        @JsonProperty("time")
        private Long time;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    private static class ExternalUnmannedVehicleData {
        @JsonProperty("transId")
        private String transId;
        @JsonProperty("timestamp")
        private Long timestamp;
        @JsonProperty("vehicleID")
        private String vehicleID;
        @JsonProperty("latitude")
        private Double latitude;
        @JsonProperty("longitude")
        private Double longitude;
        @JsonProperty("speed")
        private Double speed;
        @JsonProperty("direction")
        private Double direction;
    }

    // 新增航空器路由和状态数据采集方法

    /**
     * 获取航空器进港路由
     * 
     * @param inRunway 进港跑道编号
     * @param outRunway 出港跑道编号
     * @param contactCross 联络道口
     * @param seat 目的机位
     * @return 进港路由数据
     */
    public AircraftRouteDTO getArrivalRoute(String inRunway, String outRunway, String contactCross, String seat) {
        try {
            String token = authService.getToken();
            if (token == null) {
                log.error("无法获取有效的认证token");
                return null;
            }

            String url = UriComponentsBuilder.fromHttpUrl(vehicleBaseUrl)
                    .path("/runwayPathPlanningController/findArrTaxiwayByRunwayAndContactCrossAndSeat")
                    .queryParam("inRunway", inRunway)
                    .queryParam("outRunway", outRunway)
                    .queryParam("contactCross", contactCross)
                    .queryParam("seat", seat)
                    .toUriString();

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", token);
            headers.set("Content-Type", "application/json");

            HttpEntity<String> requestEntity = new HttpEntity<>(headers);

            ResponseEntity<Response<AircraftRouteDTO>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    requestEntity,
                    new ParameterizedTypeReference<Response<AircraftRouteDTO>>() {}
            );

            Response<AircraftRouteDTO> responseBody = response.getBody();
            if (responseBody != null && responseBody.getStatus() == 200) {
                log.info("成功获取进港路由数据: inRunway={}, outRunway={}, contactCross={}, seat={}", 
                        inRunway, outRunway, contactCross, seat);
                return responseBody.getData();
            } else {
                log.warn("获取进港路由数据失败: {}", responseBody != null ? responseBody.getMsg() : "未知错误");
                return null;
            }
        } catch (Exception e) {
            log.error("获取进港路由数据时发生异常: inRunway={}, outRunway={}, contactCross={}, seat={}", 
                    inRunway, outRunway, contactCross, seat, e);
            return null;
        }
    }

    /**
     * 获取航空器出港路由
     * 
     * @param inRunway 进港跑道编号
     * @param outRunway 出港跑道编号
     * @param startSeat 起始机位
     * @return 出港路由数据
     */
    public AircraftRouteDTO getDepartureRoute(String inRunway, String outRunway, String startSeat) {
        try {
            String token = authService.getToken();
            if (token == null) {
                log.error("无法获取有效的认证token");
                return null;
            }

            String url = UriComponentsBuilder.fromHttpUrl(vehicleBaseUrl)
                    .path("/runwayPathPlanningController/findDepTaxiwayByRunwayAndContactCrossAndSeat")
                    .queryParam("inRunway", inRunway)
                    .queryParam("outRunway", outRunway)
                    .queryParam("startSeat", startSeat)
                    .toUriString();

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", token);
            headers.set("Content-Type", "application/json");

            HttpEntity<String> requestEntity = new HttpEntity<>(headers);

            ResponseEntity<Response<AircraftRouteDTO>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    requestEntity,
                    new ParameterizedTypeReference<Response<AircraftRouteDTO>>() {}
            );

            Response<AircraftRouteDTO> responseBody = response.getBody();
            if (responseBody != null && responseBody.getStatus() == 200) {
                log.info("成功获取出港路由数据: inRunway={}, outRunway={}, startSeat={}", 
                        inRunway, outRunway, startSeat);
                return responseBody.getData();
            } else {
                log.warn("获取出港路由数据失败: {}", responseBody != null ? responseBody.getMsg() : "未知错误");
                return null;
            }
        } catch (Exception e) {
            log.error("获取出港路由数据时发生异常: inRunway={}, outRunway={}, startSeat={}", 
                    inRunway, outRunway, startSeat, e);
            return null;
        }
    }

    /**
     * 获取航空器状态
     * 
     * @return 航空器状态数据
     */
    public AircraftStatusDTO getAircraftStatus() {
        try {
            String token = authService.getToken();
            if (token == null) {
                log.error("无法获取有效的认证token");
                return null;
            }

            String url = vehicleBaseUrl + "/aircraftStatusController/getAircraftStatus";

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", token);
            headers.set("Content-Type", "application/json");

            HttpEntity<String> requestEntity = new HttpEntity<>(headers);

            ResponseEntity<Response<AircraftStatusDTO>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    requestEntity,
                    new ParameterizedTypeReference<Response<AircraftStatusDTO>>() {}
            );

            Response<AircraftStatusDTO> responseBody = response.getBody();
            if (responseBody != null && responseBody.getStatus() == 200) {
                log.info("成功获取航空器状态数据: {}", responseBody.getData().getFlightNo());
                return responseBody.getData();
            } else {
                log.warn("获取航空器状态数据失败: {}", responseBody != null ? responseBody.getMsg() : "未知错误");
                return null;
            }
        } catch (Exception e) {
            log.error("获取航空器状态数据时发生异常", e);
            return null;
        }
    }
}
