package com.ruoyi.cc.service.impl;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.cc.service.ICcParamsService;
import com.ruoyi.cc.utils.FsConfPathUtils;
import com.ruoyi.cc.utils.FsEslNameUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import link.thingscloud.freeswitch.esl.EslConnectionUtil;
import link.thingscloud.freeswitch.esl.transport.message.EslMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.cc.mapper.CcGatewaysMapper;
import com.ruoyi.cc.domain.CcGateways;
import com.ruoyi.cc.service.ICcGatewaysService;
import com.ruoyi.common.core.text.Convert;

/**
 * 线路配置Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-12-22
 */
@Service
@Slf4j
public class CcGatewaysServiceImpl implements ICcGatewaysService 
{
    @Autowired
    private CcGatewaysMapper ccGatewaysMapper;
    @Autowired
    private ICcParamsService ccParamsService;

    /**
     * 查询线路配置
     * 
     * @param id 线路配置主键
     * @return 线路配置
     */
    @Override
    public CcGateways selectCcGatewaysById(Long id)
    {
        return ccGatewaysMapper.selectCcGatewaysById(id);
    }

    /**
     * 查询线路配置列表
     * 
     * @param ccGateways 线路配置
     * @return 线路配置
     */
    @Override
    public List<CcGateways> selectCcGatewaysList(CcGateways ccGateways)
    {
        return ccGatewaysMapper.selectCcGatewaysList(ccGateways);
    }

    /**
     * 新增线路配置
     * 
     * @param ccGateways 线路配置
     * @return 结果
     */
    @Override
    public int insertCcGateways(CcGateways ccGateways)
    {
        return ccGatewaysMapper.insertCcGateways(ccGateways);
    }

    /**
     * 修改线路配置
     * 
     * @param ccGateways 线路配置
     * @return 结果
     */
    @Override
    public int updateCcGateways(CcGateways ccGateways)
    {
        return ccGatewaysMapper.updateCcGateways(ccGateways);
    }

    /**
     * 批量删除线路配置
     * 
     * @param ids 需要删除的线路配置主键
     * @return 结果
     */
    @Override
    public int deleteCcGatewaysByIds(String ids)
    {
        return ccGatewaysMapper.deleteCcGatewaysByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除线路配置信息
     * 
     * @param id 线路配置主键
     * @return 结果
     */
    @Override
    public int deleteCcGatewaysById(Long id)
    {
        return ccGatewaysMapper.deleteCcGatewaysById(id);
    }

    @Override
    public CcGateways selectCcGatewaysByGwName(String gwName) {
        List<CcGateways> list = this.selectCcGatewaysList(new CcGateways().setGwName(gwName));
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public Integer refreshGatewaysFiles() {
        List<CcGateways> list = this.selectCcGatewaysList(new CcGateways());
        Map<String, List<String>> profileNames = new HashMap<>();
        for (CcGateways ccGateways : list) {
            List<String> gatewayNames = profileNames.getOrDefault(ccGateways.getProfileName(), new ArrayList<>());
            // 废弃的配置，也删除
            if (ccGateways.getPurpose() != 0) {
                gatewayNames.add(ccGateways.getGwName() + ".xml");
            }
            profileNames.put(ccGateways.getProfileName(), gatewayNames);
        }

        String fsConfDirectory = ccParamsService.getParamValueByCode("fs_conf_directory", "");
        int deletedCount = 0;

        // 遍历每个profile及其对应的gateway名称集合
        for (Map.Entry<String, List<String>> entry : profileNames.entrySet()) {
            String profile = entry.getKey();
            List<String> gatewayNames = entry.getValue();
            log.info("==========profile:{}, gatewayNames:{}", profile, JSONObject.toJSONString(gatewayNames));
            if (!FsEslNameUtils.isSafeName(profile)) {
                log.warn("skip unsafe profile name in refreshGatewaysFiles: {}", profile);
                continue;
            }
            Path profileDir = FsConfPathUtils.resolveProfileDir(fsConfDirectory, profile);
            if (profileDir == null || !Files.exists(profileDir) || !Files.isDirectory(profileDir)) {
                continue;
            }

            try {
                File[] files = profileDir.toFile().listFiles();
                if (files == null) {
                    continue;
                }

                for (File file : files) {
                    String gwName = file.getName().replace(".xml", "");
                    log.info("====================gwName:" + gwName);
                    log.info("=====================" + (file.isFile() && !gatewayNames.contains(file.getName())));
                    log.info("=====================" + (gatewayNames.contains(file.getName())));
                    if (file.isFile() && !gatewayNames.contains(file.getName())) {
                        if (!FsEslNameUtils.isSafeName(gwName)) {
                            log.warn("skip unsafe gwName when cleaning: {}", gwName);
                            continue;
                        }
                        boolean deleted = file.delete();
                        if (deleted) {
                            EslMessage eslMessage1 = EslConnectionUtil.sendSyncApiCommand(
                                    "sofia", "profile " + profile + " killgw " + gwName);
                            if (null != eslMessage1) {
                                log.info(StringUtils.joinWith("/r/n", eslMessage1.getBodyLines().toArray()));
                            }
                            deletedCount++;
                            log.info("=======Deleted orphaned file: {}", file.getAbsolutePath());
                        } else {
                            log.warn("========Failed to delete file: {}", file.getAbsolutePath());
                        }
                    }
                }
            } catch (Exception e) {
                log.error("Error processing directory: {}", profileDir, e);
            }
        }

        return deletedCount;
    }
}
