package com.multictrl.modules.business.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.multictrl.common.config.MinioConfig;
import com.multictrl.common.config.SysConfig;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.exception.ErrorCode;
import com.multictrl.common.exception.RenException;
import com.multictrl.common.page.PageData;
import com.multictrl.common.service.impl.CrudServiceImpl;
import com.multictrl.common.utils.DJIErrorCodeUtils;
import com.multictrl.common.utils.JsonUtils;
import com.multictrl.common.utils.Utils;
import com.multictrl.modules.business.dao.RemoteLogDao;
import com.multictrl.modules.business.dto.RemoteLogDTO;
import com.multictrl.modules.business.dto.error.DJICloudErrorCode;
import com.multictrl.modules.business.dto.remote.log.SyncRemoteLog;
import com.multictrl.modules.business.dto.remote.log.RemoteLog;
import com.multictrl.modules.business.entity.RemoteLogEntity;
import com.multictrl.modules.business.service.DJIBaseService;
import com.multictrl.modules.business.service.MinioService;
import com.multictrl.modules.business.service.RemoteLogService;
import io.minio.credentials.Credentials;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 远程日志
 *
 * @author Sdy
 * @since 1.0.0 2026/5/10
 */
@Service
@RequiredArgsConstructor
public class RemoteLogServiceImpl extends CrudServiceImpl<RemoteLogDao, RemoteLogEntity, RemoteLogDTO> implements RemoteLogService {
    private final DJIBaseService djiBaseService;
    private final MinioService minioService;
    private final MinioConfig minioConfig;
    private final SysConfig sysConfig;

    @Override
    public QueryWrapper<RemoteLogEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");
        String module = (String) params.get("module");
        String dockSn = (String) params.get("dockSn");

        QueryWrapper<RemoteLogEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
        wrapper.like(StrUtil.isNotBlank(module), "module", module);
        wrapper.eq(StrUtil.isNotBlank(dockSn), "dock_sn", dockSn);
        wrapper.orderByDesc("create_date");

        return wrapper;
    }

    @Override
    public List<RemoteLog> getRemoteLogList(String dockSn, String module) {
        String topic = "thing/product/" + dockSn + "/services";
        JSONObject data = new JSONObject();
        JSONArray moduleList = new JSONArray();
        moduleList.add(module);
        data.set("module_list", moduleList);
        JSONObject payload = djiBaseService.getPayload("fileupload_list", data);
        JSONObject result = djiBaseService.sendWaitReply(topic, payload);
        if (result == null || !result.containsKey("files") || result.getJSONArray("files").isEmpty()) {
            throw new RenException(ErrorCode.DOCK_NOT_REPLY);
        }
        JSONObject files = result.getJSONArray("files").getJSONObject(0);
        if (files.getInt("result") != 0) {
            DJICloudErrorCode errorMsg = DJIErrorCodeUtils.getErrorMsg(files.getStr("result"));
            String message = errorMsg != null ? JsonUtils.toJsonString(errorMsg) : "大疆未知错误：" + files.getStr("result");
            throw new RenException(message);
        }
        List<RemoteLog> remoteLogList = new ArrayList<>();
        JSONArray fileList = files.getJSONArray("list");
        for (int i = fileList.size() - 1; i >= 0; i--) {
            JSONObject file = fileList.getJSONObject(i);
            RemoteLog remoteLog = new RemoteLog();
            remoteLog.setBootIndex(file.getInt("boot_index"));
            remoteLog.setStartDate(new Date(file.getLong("start_time") * 1000));
            remoteLog.setEndDate(new Date(file.getLong("end_time") * 1000));
            remoteLog.setSize(Utils.formatBytes(file.getLong("size")));
            remoteLogList.add(remoteLog);
        }
        return remoteLogList;
    }

    @Override
    public String syncRemoteLog(String dockSn, SyncRemoteLog remoteLog) {
        JSONObject data = new JSONObject();
        minioService.createBucket(BusinessConstant.REMOTE_LOG_BUCKET);
        data.set("bucket", BusinessConstant.REMOTE_LOG_BUCKET);
        JSONObject credentials = new JSONObject();
        credentials.set("expire", 3600);
        Credentials cds = minioService.getCredentials();
        if (cds != null) {
            credentials.set("access_key_id", cds.accessKey());
            credentials.set("access_key_secret", cds.secretKey());
            credentials.set("security_token", cds.sessionToken());
        }
        data.set("credentials", credentials);
        data.set("endpoint", minioConfig.getEndpoint());
        data.set("provider", "minio");
        data.set("region", "us-east-1");
        JSONObject params = new JSONObject();
        JSONArray files = new JSONArray();
        JSONObject fileObject = new JSONObject();
        JSONArray list = new JSONArray();
        for (SyncRemoteLog.FileInfo fileInfo : remoteLog.getFileInfoList()) {
            JSONObject t1 = new JSONObject();
            t1.set("boot_index", fileInfo.getBootIndex());
            list.add(t1);
        }
        fileObject.set("list", list);
        fileObject.set("module", remoteLog.getModule());
        String tarName = "report_" + DateUtil.format(new Date(), "yyyy_MM_dd_HH_mm_ss") + ".tar";
        fileObject.set("object_key", dockSn + "/" + remoteLog.getModule() + "/" + tarName);
        files.add(fileObject);
        params.set("files", files);
        data.set("params", params);
        data.set("provider", "minio");
        data.set("region", "us-east-1");
        //入库
        RemoteLogEntity entity = new RemoteLogEntity();
        entity.setDockSn(dockSn);
        entity.setModule(remoteLog.getModule());
        entity.setFilename(tarName);
        StringBuilder times = new StringBuilder();
        for (SyncRemoteLog.FileInfo fileInfo : remoteLog.getFileInfoList()) {
            times.append(fileInfo.getBootIndex())
                    .append("_")
                    .append(fileInfo.getStartDateStr())
                    .append("_")
                    .append(fileInfo.getEndDateStr())
                    .append(",");
        }
        entity.setTimes(times.substring(0, times.length() - 1));
        baseDao.insert(entity);

        return djiBaseService.executeAndReturnResult(dockSn, "fileupload_start", data);
    }

    @Override
    public String cancelSyncRemoteLog(String dockSn, String module) {
        JSONObject data = new JSONObject();
        data.set("status", "cancel");
        JSONArray moduleList = new JSONArray();
        moduleList.add(module);
        data.set("module_list", moduleList);
        return djiBaseService.executeAndReturnResult(dockSn, "fileupload_update", data);
    }

    @Override
    public PageData<RemoteLogDTO> queryPage(Map<String, Object> params) {
        PageData<RemoteLogDTO> page = page(params);
        for (RemoteLogDTO dto : page.getList()) {
            Integer code = dto.getCode();
            if (code > 0) {
                DJICloudErrorCode errorMsg = DJIErrorCodeUtils.getErrorMsg(String.valueOf(code));
                dto.setCloudErrorCode(errorMsg);
            }
            String path = dto.getPath();
            if (StrUtil.isNotBlank(path)) {
                dto.setPath(BusinessConstant.FILE_PATH + BusinessConstant.REMOTE_LOG_BUCKET + "/" + path);
            }
            if (dto.getUploadRate() != null) {
                dto.setUploadRateText(Utils.formatBytes(dto.getUploadRate()) + "/S");
            }
            if (dto.getSize() != null) {
                dto.setSizeText(Utils.formatBytes(dto.getSize()));
            }
        }
        return page;
    }

    @Override
    public RemoteLogDao getDao() {
        return baseDao;
    }
}
