package com.wmyun.module.infra.service.file;

import cn.hutool.core.io.IoUtil;
import com.wmyun.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.wmyun.framework.security.core.LoginUser;
import com.wmyun.framework.security.core.util.SecurityFrameworkUtils;
import com.wmyun.module.infra.controller.admin.file.vo.preview.CheckFileInfoVo;
import com.wmyun.module.infra.dal.dataobject.config.ConfigDO;
import com.wmyun.module.infra.dal.dataobject.file.FileDO;
import com.wmyun.module.infra.dal.mysql.file.FileMapper;
import com.wmyun.module.infra.enums.config.ConfigEnum;
import com.wmyun.module.infra.framework.file.core.client.FileClient;
import com.wmyun.module.infra.framework.file.core.utils.FileTypeUtils;
import com.wmyun.module.infra.service.config.ConfigService;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.wmyun.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;

/**
 * @Description: TODO
 * @Date: 2025/2/26 18:25
 * @Created: by ZZSLL
 */

@Service

public class FilePreviewServiceImpl implements FilePreviewService {

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private FileConfigService fileConfigService;

    @Autowired
    private ConfigService configService;

    @Override
    public CheckFileInfoVo createPreviewInfo(String fileId) {
        FileDO file = queryFileInfoByFileId(fileId);
        if (file == null) {
            return null;
        }
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        ConfigDO WOPI_SERVER_IP = configService.getConfigByKey(ConfigEnum.WOPI_SERVER_IP.getKey());
        String hostUrl = WOPI_SERVER_IP.getValue() + "/admin-api/infra/file/preview/wopi/files/" + fileId;
        return CheckFileInfoVo.builder()
                .baseFileName(file.getName())
                .ownerId(file.getUpdater())
                .size(Long.valueOf(file.getSize()))
                .userId(String.valueOf(Optional.ofNullable(user)
                        .map(LoginUser::getId)
                        .orElse(0L)))
                .userFriendlyName(Optional.ofNullable(user)
                        .map(LoginUser::getInfo)
                        .map(info -> info.get(LoginUser.INFO_KEY_NICKNAME))
                        .orElse("user_xx"))
                .version("")
                .supportsDeleteFile(false)
                .supportsRename(false)
                .supportsUpdate(true)
                .supportsUserInfo(true)
                .readOnly(true)
                .userCanRename(true)
                .userCanWrite(true)
                .downloadUrl(file.getUrl())
                .fileUrl(file.getUrl())
                .hostViewUrl(hostUrl)
                .hostEditUrl(hostUrl)
                .build();
    }

    /**
     * 查询文件信息
     * @param fileId 文件id
     * @return
     */
    public FileDO queryFileInfoByFileId(String fileId) {
        LambdaQueryWrapperX<FileDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(FileDO::getId, fileId).eq(FileDO::getDeleted, false);
        List<FileDO> files = fileMapper.selectList(queryWrapperX);
        FileDO file = CollectionUtils.isNotEmpty(files) ? files.get(0) : null;

        if (file != null) {
            ConfigDO config = configService.getConfigByKey(ConfigEnum.WOPI_SERVER_IP.getKey());
            String wopiServerIp = config.getValue();
            file.setUrl(replaceWithSelfAddress(file.getUrl(), wopiServerIp));
        }
        return file;
    }

    /**
     * 替换url中ip地址
     * @param url 文件下载url
     * @param targetIP 本机ip
     * @return
     */
    private String replaceWithSelfAddress(String url, String targetIP) {
        // 正则匹配 http(s):// 后的 IPv4 地址
        Pattern pattern = Pattern.compile("(https?://)(\\d+\\.\\d+\\.\\d+\\.\\d+)");
        Matcher matcher = pattern.matcher(url);
        return matcher.replaceAll("$1" + targetIP);
    }

    @Override
    public void saveFile(String fileId, InputStream content, Long size) {
        FileDO existFile = queryFileInfoByFileId(fileId);
        FileClient client = fileConfigService.getMasterFileClient();
        if (existFile == null) {
            throw new RuntimeException("不支持创建文件");
        }
        byte[] data = IoUtil.readBytes(content);
        String type = FileTypeUtils.getMineType(data, existFile.getName());
        try {
            String url = client.upload(data, existFile.getPath(), type);
            existFile.setUrl(url);
            existFile.setSize(Integer.valueOf(size.toString()));
            fileMapper.updateById(existFile);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void getFileContent(String fileId, HttpServletResponse response) {
        FileDO file = queryFileInfoByFileId(fileId);
        if (file == null) {
            return;
        }
        FileClient client = fileConfigService.getFileClient(file.getConfigId());
        try {
            writeAttachment(response, file.getName(), client.getContent(file.getPath()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
