package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import shop.alien.entity.result.R;
import shop.alien.entity.store.CommonPushChannelConfig;
import shop.alien.mapper.CommonPushChannelConfigMapper;
import shop.alien.store.service.CommonPushChannelConfigService;
import shop.alien.util.ip.IpConnectTestUtil;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class CommonPushChannelConfigServiceImpl extends ServiceImpl<CommonPushChannelConfigMapper, CommonPushChannelConfig> implements CommonPushChannelConfigService {

    private static final Map<String, String> CHANNEL_TEST_HOST = new HashMap<>();

    static {
        CHANNEL_TEST_HOST.put("apns", "api.push.apple.com");
        CHANNEL_TEST_HOST.put("huawei", "push-api.cloud.huawei.com");
        CHANNEL_TEST_HOST.put("xiaomi", "api.xmpush.xiaomi.com");
        CHANNEL_TEST_HOST.put("oppo", "api.push.oppomobile.com");
        CHANNEL_TEST_HOST.put("vivo", "api-push.vivo.com.cn");
        CHANNEL_TEST_HOST.put("honor", "push-api.cloud.honor.com");
        CHANNEL_TEST_HOST.put("samsung", "apchina.push.samsungosp.com.cn");
    }

    @Override
    public R<String> add(CommonPushChannelConfig config) {
        log.info("CommonPushChannelConfigServiceImpl.add, param={}", config);
        boolean result = this.save(config);
        return result ? R.success("新增成功") : R.fail("新增失败");
    }

    @Override
    public R<String> deleteById(Long id) {
        log.info("CommonPushChannelConfigServiceImpl.deleteById, id={}", id);
        boolean result = this.removeById(id);
        return result ? R.success("删除成功") : R.fail("删除失败");
    }

    @Override
    public R<String> update(CommonPushChannelConfig config) {
        log.info("CommonPushChannelConfigServiceImpl.update, param={}", config);
        if (config.getId() == null) {
            return R.fail("id不能为空");
        }
        boolean result = this.updateById(config);
        return result ? R.success("更新成功") : R.fail("更新失败");
    }

    @Override
    public R<CommonPushChannelConfig> getInfoById(Long id) {
        log.info("CommonPushChannelConfigServiceImpl.getInfoById, id={}", id);
        return R.data(this.getById(id));
    }

    @Override
    public R<IPage<CommonPushChannelConfig>> list(Integer pageNum, Integer pageSize, String channelCode, String platform, Integer enable) {
        log.info("CommonPushChannelConfigServiceImpl.list, pageNum={}, pageSize={}, channelCode={}, platform={}, enable={}",
                pageNum, pageSize, channelCode, platform, enable);
        Page<CommonPushChannelConfig> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<CommonPushChannelConfig> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(channelCode)) {
            wrapper.eq(CommonPushChannelConfig::getChannelCode, channelCode);
        }
        if (StringUtils.isNotBlank(platform)) {
            wrapper.eq(CommonPushChannelConfig::getPlatform, platform);
        }
        if (enable != null) {
            wrapper.eq(CommonPushChannelConfig::getEnable, enable);
        }
        wrapper.orderByDesc(CommonPushChannelConfig::getUpdatedTime);
        return R.data(this.page(page, wrapper));
    }

    @Override
    public R<String> toggleEnable(Long id, Integer enable) {
        log.info("CommonPushChannelConfigServiceImpl.toggleEnable, id={}, enable={}", id, enable);
        if (id == null) {
            return R.fail("id不能为空");
        }
        if (enable == null || (enable != 0 && enable != 1)) {
            return R.fail("enable只能为0（停用）或1（启用）");
        }
        CommonPushChannelConfig config = this.getById(id);
        if (config == null) {
            return R.fail("配置不存在");
        }
        config.setEnable(enable);
        boolean result = this.updateById(config);
        return result ? R.success(enable == 1 ? "启用成功" : "停用成功") : R.fail("操作失败");
    }

    @Override
    public R<String> testConnect(Long id) {
        log.info("CommonPushChannelConfigServiceImpl.testConnect, id={}", id);
        if (id == null) {
            return R.fail("id不能为空");
        }
        CommonPushChannelConfig config = this.getById(id);
        if (config == null) {
            return R.fail("配置不存在");
        }
        if (StringUtils.isBlank(config.getCredentialJson())) {
            saveTestResult(config, false, "凭证未配置");
            return R.fail("凭证未配置");
        }
        try {
            JSONObject.parseObject(config.getCredentialJson());
        } catch (Exception e) {
            saveTestResult(config, false, "凭证JSON格式错误");
            return R.fail("凭证JSON格式错误");
        }
        String host = resolveTestHost(config.getChannelCode());
        if (host == null) {
            saveTestResult(config, false, "不支持的渠道编码");
            return R.fail("不支持的渠道编码");
        }
        boolean connected = Boolean.TRUE.equals(IpConnectTestUtil.ipTest(host, 443));
        if (connected) {
            saveTestResult(config, true, null);
            return R.success("连通成功");
        }
        saveTestResult(config, false, "连通失败，请检查凭证或网络");
        return R.fail("连通失败");
    }

    private void saveTestResult(CommonPushChannelConfig config, boolean success, String warnMsg) {
        config.setLastTestTime(new Date());
        config.setConnectStatus(success ? 1 : 0);
        config.setWarnMsg(warnMsg);
        this.updateById(config);
    }

    private String resolveTestHost(String channelCode) {
        if (StringUtils.isBlank(channelCode)) {
            return null;
        }
        return CHANNEL_TEST_HOST.get(channelCode.trim().toLowerCase());
    }
}
