package com.sikey.wa04.business.application.service.location;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.sikey.wa04.business.domain.adapter.ChildAdapter;
import com.sikey.wa04.business.domain.adapter.ChildQueryAdapter;
import com.sikey.wa04.business.domain.entity.Child;
import com.sikey.wa04.business.domain.usecase.ChildIdFactory;
import com.sikey.wa04.business.domain.usecase.CoordinateConverter;
import com.sikey.wa04.business.infrastructure.dto.model.ChildFenceModel;
import com.sikey.wa04.business.infrastructure.dto.request.fence.*;
import com.sikey.wa04.business.infrastructure.dto.response.fence.CreateFenceResponse;
import com.sikey.wa04.business.infrastructure.dto.response.fence.GetFenceResponse;
import com.sikey.wa04.business.infrastructure.dto.response.fence.TotalSwitchFenceResponse;
import com.sikey.wa04.business.infrastructure.repository.ChildFenceRepository;
import com.sikey.wa04.common.enums.CoordinateType;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


/**
 * 围栏服务
 *
 * @author luoyangwei
 * @date 2024年11月01日10:06:11
 */
@Slf4j
@Service
public class FenceService {

    @Resource
    private ChildFenceRepository childFenceRepository;

    @Resource
    private ChildQueryAdapter childQueryAdapter;

    @Resource
    private ChildAdapter childAdapter;

    /**
     * 获取围栏
     *
     * @param request 请求
     * @return 响应
     */
    public GetFenceResponse get(GetFenceRequest request) {
        List<ChildFenceModel> models = childFenceRepository.findByChildId(request.cid());
        List<GetFenceResponse.GetFenceResult> fences = new ArrayList<>();
        for (ChildFenceModel model : models) {
            fences.add(new GetFenceResponse.GetFenceResult()
                    .setFid(model.getId())
                    .setCid(model.getChildId())
                    .setFenceName(model.getFenceName())
                    .setFenceType(model.getFenceType())
                    .setState(model.getState())
                    .setLongitude(model.getLongitude())
                    .setLatitude(model.getLatitude())
                    .setRange(model.getRange())
                    .setAddress(model.getAddress())
                    .setCreatedAt(model.getCreatedAt().toEpochMilli())
                    .setUpdatedAt(model.getUpdatedAt().toEpochMilli()));
        }
        Child child = childQueryAdapter.findByChildId(ChildIdFactory.create(request.cid()));
        return new GetFenceResponse()
                .setFences(fences)
                .setTotalSwitch(child.getIsEnableFence());
    }

    /**
     * 创建围栏
     *
     * @param request 请求
     * @return 响应
     */
    public CreateFenceResponse create(CreateFenceRequest request) {
        CoordinateType coordinateType = CoordinateType.valueOf(request.coordinateType());
        GlobalCoordinates coordinatesConverted = convertPoints(coordinateType,
                Double.parseDouble(request.longitude()), Double.parseDouble(request.latitude()));

        ChildFenceModel model = new ChildFenceModel()
                .setChildId(request.cid())
                .setFenceName(request.fenceName())
                .setFenceType(request.fenceType())
                .setState(true) // 默认启用围栏
                .setLongitude(String.format("%.6f", coordinatesConverted.getLongitude()))
                .setLatitude(String.format("%.6f", coordinatesConverted.getLatitude()))
                .setRange(request.range())
                .setAddress(request.address());
        childFenceRepository.save(model);
        log.info("Fence created successfully : {}", model);
        return new CreateFenceResponse().setFid(model.getId());
    }

    /**
     * 转换坐标
     *
     * @param coordinateType 坐标类型
     * @param longitude      经度
     * @param latitude       纬度
     * @return 转换后的坐标
     */
    private GlobalCoordinates convertPoints(CoordinateType coordinateType, double longitude, double latitude) {
        CoordinateConverter coordinateConverter = CoordinateConverter.getInstance(CoordinateConverter.defaultPoints());
        return switch (coordinateType) {
            case GCJ02 -> coordinateConverter.GCJ02toWGS84(longitude, latitude);
            case BD09 -> coordinateConverter.BD09toWGS84(longitude, latitude);
            // GlobalCoordinates 的入参和我们系统的是反的，这里也就不纠正了
            case WGS84 -> new GlobalCoordinates(latitude, longitude);
        };
    }

    /**
     * 更新围栏
     *
     * @param request 请求
     */
    public void update(UpdateFenceRequest request) {
        CoordinateType coordinateType = CoordinateType.valueOf(request.coordinateType());
        GlobalCoordinates coordinatesConverted = convertPoints(coordinateType,
                Double.parseDouble(request.longitude()), Double.parseDouble(request.latitude()));

        Optional<ChildFenceModel> optional = childFenceRepository.findById(request.fid());
        optional.orElseThrow(() -> new RuntimeException("Fence not found : %d".formatted(request.fid())));

        ChildFenceModel model = optional.get()
                .setFenceName(request.fenceName())
                .setFenceType(request.fenceType())
                .setState(request.state()) // 默认启用围栏
                .setLongitude(String.format("%.6f", coordinatesConverted.getLongitude()))
                .setLatitude(String.format("%.6f", coordinatesConverted.getLatitude()))
                .setRange(request.range())
                .setAddress(request.address());
        model.setUpdatedAt(Instant.now());
        childFenceRepository.save(model);
        log.info("Fence updated successfully : {}", model);
    }

    /**
     * 删除围栏
     *
     * @param request 请求
     */
    public void delete(DeleteFenceRequest request) {
        childFenceRepository.deleteById(request.fid());
        log.info("Fence deleted successfully : {}", request.fid());
    }

    /**
     * 总开关
     *
     * @param request 请求
     * @return 响应
     */
    public TotalSwitchFenceResponse totalSwitch(TotalSwitchFenceRequest request) {
        Child child = childQueryAdapter.findByChildId(ChildIdFactory.create(request.cid()));
        child.setIsEnableFence(request.state());
        childAdapter.update(child);
        log.info("Update master switch successfully : {}", child);
        return new TotalSwitchFenceResponse()
                .setAfterTotalSwitch(child.getIsEnableFence());
    }
}
