package shop.alien.store.service.impl;

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.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import shop.alien.entity.store.ProtocolManagement;
import shop.alien.mapper.ProtocolManagementMapper;
import shop.alien.store.service.ProtocolManagementService;
import shop.alien.store.util.FileUploadUtil;
import shop.alien.util.common.RandomCreateUtil;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.file.FileUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 协议管理表 服务实现类
 *
 * @author alien
 * @since 2025-12-09
 */
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class ProtocolManagementServiceImpl extends ServiceImpl<ProtocolManagementMapper, ProtocolManagement> implements ProtocolManagementService {

    private final ProtocolManagementMapper protocolManagementMapper;

    private final FileUploadUtil fileUploadUtil;

    private final AliOSSUtil aliOSSUtil;

    @Override
    public IPage<ProtocolManagement> getProtocolPage(Integer pageNum, Integer pageSize, String protocolFileName, String displayPosition) {
        log.info("协议管理-分页查询, pageNum: {}, pageSize: {}, protocolFileName: {}, displayPosition: {}", 
                pageNum, pageSize, protocolFileName, displayPosition);
        
        IPage<ProtocolManagement> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<ProtocolManagement> queryWrapper = new LambdaQueryWrapper<>();
        
        // 协议名称模糊查询
        if (StringUtils.isNotBlank(protocolFileName)) {
            queryWrapper.like(ProtocolManagement::getProtocolFileName, protocolFileName);
        }
        
        // 展示位置模糊查询
        if (StringUtils.isNotBlank(displayPosition)) {
            queryWrapper.like(ProtocolManagement::getDisplayPosition, displayPosition);
        }
        
        // 按创建时间倒序排列
        queryWrapper.orderByDesc(ProtocolManagement::getCreatedTime);
        
        return protocolManagementMapper.selectPage(page, queryWrapper);
    }

    @Override
    public void getProtocolById(Integer id, HttpServletResponse response) {
        log.info("协议管理-查询详情, id: {}", id);

        if (id == null) {
            throw new IllegalArgumentException("协议ID不能为空");
        }

        ProtocolManagement protocol = protocolManagementMapper.selectById(id);

        if (protocol == null) {
            throw new IllegalArgumentException("协议不存在");
        }

        String protocolUrl = protocol.getProtocolFilePath();
        if (StringUtils.isBlank(protocolUrl)) {
            throw new IllegalArgumentException("协议文件路径不存在");
        }

        // 添加域名判断和转换逻辑
        String newDomain = "https://ossfile.ailien.shop/";
        String oldDomain = "https://alien-volume.oss-cn-beijing.aliyuncs.com/";

        if (protocolUrl.startsWith(oldDomain) && !protocolUrl.contains(newDomain)) {
            protocolUrl = newDomain + protocolUrl.substring(oldDomain.length());
        }

        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            URL url = new URL(protocolUrl);

            // 绕过SSL证书验证
            if (protocolUrl.startsWith("https://ossfile.ailien.shop/")) {
                // 对于自定义域名，暂时回退到原始OSS域名
                String fallbackUrl = protocolUrl.replace(
                        "https://ossfile.ailien.shop/",
                        "https://alien-volume.oss-cn-beijing.aliyuncs.com/"
                );
                url = new URL(fallbackUrl);
            }

            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(10000);

            // 推断文件名与Content-Type
            String path = url.getPath();
            int lastSlash = path.lastIndexOf('/');
            String fileName = lastSlash >= 0 ? path.substring(lastSlash + 1) : "protocol.html";
            if (fileName.contains("?")) {
                fileName = fileName.substring(0, fileName.indexOf('?'));
            }
            if (StringUtils.isBlank(fileName)) {
                fileName = "protocol.html";
            }
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");

            String contentType = connection.getContentType();
            if (StringUtils.isBlank(contentType)) {
                // 默认按照html返回，兜底八进制流
                contentType = protocolUrl.toLowerCase().endsWith(".html")
                        ? "text/html;charset=utf-8"
                        : "application/octet-stream";
            }

            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType(contentType);
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + encodedFileName);

            inputStream = connection.getInputStream();
            outputStream = response.getOutputStream();
            byte[] buffer = new byte[8192];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();
        } catch (IOException e) {
            log.error("协议管理-协议文件流输出失败, id: {}, url: {}", id, protocolUrl, e);
            throw new RuntimeException("协议文件下载失败");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭协议文件输入流失败", e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("关闭协议文件输出流失败", e);
                }
            }
        }
    }

    @Override
    public boolean addProtocol(MultipartFile multipartFile, ProtocolManagement protocolManagement) {
        log.info("协议管理-新增, 请求参数: {}", protocolManagement);

        // 参数校验
        if (StringUtils.isBlank(protocolManagement.getProtocolFileName())) {
            throw new IllegalArgumentException("协议名称不能为空");
        }
        String prefix;
        prefix = "privacy/";
        Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);

        String s = aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type"));
        // 修改oss路径为域名路径
        String newDomain = "https://ossfile.ailien.shop/";
        String oldDomain = "https://alien-volume.oss-cn-beijing.aliyuncs.com/";

        if (s.startsWith(oldDomain)) {
            s = newDomain + s.substring(oldDomain.length());
        }


        protocolManagement.setProtocolFilePath(s);

        // 根据 type(displayPosition) 和名称(protocolFileName) 查询是否存在
        LambdaQueryWrapper<ProtocolManagement> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProtocolManagement::getProtocolFileName, protocolManagement.getProtocolFileName());
        if (StringUtils.isNotBlank(protocolManagement.getDisplayPosition())) {
            queryWrapper.eq(ProtocolManagement::getDisplayPosition, protocolManagement.getDisplayPosition());
        } else {
            queryWrapper.isNull(ProtocolManagement::getDisplayPosition);
        }
        
        ProtocolManagement existProtocol = protocolManagementMapper.selectOne(queryWrapper);
        
        int result;
        if (existProtocol != null) {
            // 如果存在，则覆盖（更新）
            log.info("协议管理-发现已存在记录，执行更新操作, id: {}", existProtocol.getId());
            protocolManagement.setId(existProtocol.getId());
            result = protocolManagementMapper.updateById(protocolManagement);
            log.info("协议管理-更新, 结果: {}", result > 0 ? "成功" : "失败");
        } else {
            // 如果不存在，则新增
            result = protocolManagementMapper.insert(protocolManagement);
            log.info("协议管理-新增, 结果: {}", result > 0 ? "成功" : "失败");
        }

        return result > 0;
    }

    @Override
    public boolean updateProtocol(MultipartRequest multipartRequest, ProtocolManagement protocolManagement) {
        log.info("协议管理-修改, 请求参数: {}", protocolManagement);
        
        // 参数校验
        if (protocolManagement.getId() == null) {
            throw new IllegalArgumentException("协议ID不能为空");
        }
        
        // 检查协议是否存在
        ProtocolManagement existProtocol = protocolManagementMapper.selectById(protocolManagement.getId());
        if (existProtocol == null) {
            throw new IllegalArgumentException("协议不存在");
        }
        
        // 如果修改了协议名称，检查新名称是否与其他协议重复
        if (StringUtils.isNotBlank(protocolManagement.getProtocolFileName()) 
                && !protocolManagement.getProtocolFileName().equals(existProtocol.getProtocolFileName())) {
            LambdaQueryWrapper<ProtocolManagement> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProtocolManagement::getProtocolFileName, protocolManagement.getProtocolFileName());
            queryWrapper.ne(ProtocolManagement::getId, protocolManagement.getId());
            Integer count = protocolManagementMapper.selectCount(queryWrapper);
            
            if (count > 0) {
                throw new IllegalArgumentException("协议名称已存在");
            }
        }

        protocolManagement.setProtocolFilePath(fileUploadUtil.uploadMoreFile(multipartRequest).get(0));
        
        int result = protocolManagementMapper.updateById(protocolManagement);
        log.info("协议管理-修改, 结果: {}", result > 0 ? "成功" : "失败");
        
        return result > 0;
    }

    @Override
    public boolean deleteProtocol(Integer id) {
        log.info("协议管理-删除, id: {}", id);
        
        if (id == null) {
            throw new IllegalArgumentException("协议ID不能为空");
        }
        
        // 检查协议是否存在
        ProtocolManagement protocol = protocolManagementMapper.selectById(id);
        if (protocol == null) {
            throw new IllegalArgumentException("协议不存在");
        }
        
        // 逻辑删除
        int result = protocolManagementMapper.deleteById(protocol);
        log.info("协议管理-删除, 结果: {}", result > 0 ? "成功" : "失败");
        
        return result > 0;
    }

    @Override
    public boolean batchDeleteProtocol(String ids) {
        log.info("协议管理-批量删除, ids: {}", ids);
        
        if (StringUtils.isBlank(ids)) {
            throw new IllegalArgumentException("协议ID不能为空");
        }
        
        // 将ID字符串转换为列表
        List<Integer> idList = Arrays.stream(ids.split(","))
                .map(String::trim)
                .filter(StringUtils::isNotBlank)
                .map(Integer::parseInt)
                .collect(Collectors.toList());
        
        if (idList.isEmpty()) {
            throw new IllegalArgumentException("协议ID不能为空");
        }
        
        // 批量逻辑删除
        int result = protocolManagementMapper.deleteBatchIds(idList);
        log.info("协议管理-批量删除, 删除数量: {}", result);
        
        return result > 0;
    }

    @Override
    public Boolean checkFileNameDuplicate(String protocolFileName) {
        log.info("协议管理-校验文件名是否重复, protocolFileName: {}", protocolFileName);

        if (StringUtils.isBlank(protocolFileName)) {
            throw new IllegalArgumentException("协议文件名不能为空");
        }

        // 查询数据库中是否存在同名文件
        LambdaQueryWrapper<ProtocolManagement> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProtocolManagement::getProtocolFileName, protocolFileName);
        Integer count = protocolManagementMapper.selectCount(queryWrapper);

        if (count > 0) {
            log.info("协议管理-校验文件名, 结果: 已重复");
            return true;
        } else {
            log.info("协议管理-校验文件名, 结果: 不重复");
            return false;
        }
    }
}

