/**
 * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
 * <p>
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiaoniu.subsystem.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.xiaoniu.common.core.result.R;
import com.xiaoniu.common.core.utils.BeanUtil;
import com.xiaoniu.common.core.utils.StringUtils;
import com.xiaoniu.subsystem.file.service.ISysFileService;
import com.xiaoniu.subsystem.system.domain.DataBackupn;
import com.xiaoniu.subsystem.system.domain.dto.DataBackupnDTO;
import com.xiaoniu.subsystem.system.domain.dto.DataBackupnPageDTO;
import com.xiaoniu.subsystem.system.domain.vo.DataBackupnVO;
import com.xiaoniu.subsystem.system.service.IDataBackupnService;
import com.xiaoniu.subsystem.system.utils.MysqlDataBackupUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*;

import java.io.FileInputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;
import static com.xiaoniu.common.security.utils.SecurityUtils.getUserId;

/**
 * 数据备份管理表 控制器
 *
 * @author sst
 * @since 2024-11-26
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/databackupn")
@Tag(name = "数据备份管理表", description = "数据备份管理表接口")
public class DataBackupnController {


    private final IDataBackupnService dataBackupnService;
    private final ISysFileService sysFileService;
    /**
     * 数据库用户名
     */
    @Value("${spring.datasource.dynamic.datasource.master.username}")
    private String userName;
    /**
     * 数据库密码
     */
    @Value("${spring.datasource.dynamic.datasource.master..password}")
    private String password;
    /**
     * 数据库url
     */
    @Value("${spring.datasource.dynamic.datasource.master.url}")
    private String url;
    /**
     * 上传文件存储在本地的根路径
     */
    @Value("${file.path}")
    private String localFilePath;

    /**
     * 详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @Operation(summary = "详情", description = "传入dataBackupn")
    public R<DataBackupnVO> detail(DataBackupnDTO dto) {
        DataBackupn detail = dataBackupnService.getOne(new QueryWrapper<>(dto));
        return R.data(BeanUtil.copy(detail, DataBackupnVO.class));
    }

    /**
     * 分页 数据备份管理表
     */
    @GetMapping("/page")
    @ApiOperationSupport(order = 2)
    @Operation(summary = "分页", description = "传入dataBackupn")
    public R<IPage<DataBackupnVO>> page(DataBackupnPageDTO dto) {
        IPage<DataBackupn> pages = dataBackupnService.page(new Page<>(dto.getPageNum(), dto.getPageSize()),
                new LambdaQueryWrapper<DataBackupn>()
                        .like(StringUtils.isNotBlank(dto.getUrl()), DataBackupn::getUrl,
                                dto.getUrl())
                        .orderByDesc(DataBackupn::getCreateTime));
        return R.data(BeanUtil.copy(pages, DataBackupnVO.class));
    }

    /**
     * 备份
     */
    @GetMapping("/backup/copy")
    @ApiOperationSupport(order = 3)
    @Operation(summary = "备份", description = "传入dataBackupn")
    public R backupCopy(DataBackupnDTO dto) throws Exception {
        if (StringUtils.isBlank(url)) {
            return R.fail("备份数据库url不能为空");
        }
        String format = String.valueOf(System.currentTimeMillis());
        String backName = (StringUtils.isBlank(dto.getDataBackupnName()) ? format : dto.getDataBackupnName()) + ".sql";
        String dbBackUp = MysqlDataBackupUtil.dbBackUp(getIP(url),getPort(url),userName, password, getName(url),
                backName);
        log.info("备份数据库临时sql文件地址:{}", dbBackUp);
        String zipName = (StringUtils.isBlank(dto.getDataBackupnName()) ? format : dto.getDataBackupnName()) + ".zip";
        String mysqlPath = MysqlDataBackupUtil.MysqlPath;
        String path = mysqlPath + zipName;
        MysqlDataBackupUtil.zipFile(dbBackUp, path);
        log.info("备份数据库临时zip文件地址:{}", path);
        String fileUrl = sysFileService.uploadFile(
                new MockMultipartFile(zipName, zipName, "", new FileInputStream(path)));
        log.info("备份数据上传文件地址:{}", fileUrl);
        MysqlDataBackupUtil.deleteFiles(dbBackUp);
        MysqlDataBackupUtil.deleteFiles(path);
        return R.status(dataBackupnService.save(BeanUtil.copy(dto, DataBackupn.class)
                .setUrl(fileUrl)
                .setCreateDept(getUnitId())
                .setCreateUser(getUserId())
                .setCreateTime(new Date())));
    }

    /**
     * 新增 数据备份管理表
     */
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @Operation(summary = "新增", description = "传入dto")
    public R save(@Valid @RequestBody DataBackupnDTO dto) {
        return R.status(dataBackupnService.save(
                dto.setCreateDept(getUnitId()).setCreateUser(getUserId()).setCreateTime(new Date())));
    }

    /**
     * 修改 数据备份管理表
     */
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @Operation(summary = "修改", description = "传入dto")
    public R update(@Valid @RequestBody DataBackupnDTO dto) {
        return R.status(dataBackupnService.updateById(
                dto.setUpdateUser(getUserId()).setUpdateTime(new Date())));
    }


    /**
     * 恢复
     */
    @GetMapping("/recover")
    @ApiOperationSupport(order = 6)
    @Operation(summary = "恢复", description = "传入dataBackupn")
    public R recover(@Parameter(description = "主键", required = true) @RequestParam Long dataBackupnId) {
        if (StringUtils.isBlank(url)) {
            return R.fail("备份数据库url不能为空");
        }
        DataBackupn byId = dataBackupnService.getById(dataBackupnId);
        String path = MysqlDataBackupUtil.MysqlPath;
        log.info("获取恢复数据文件：{}", byId.getUrl());
        String name = MysqlDataBackupUtil.unzipFile(byId.getUrl().replaceAll("/statics", localFilePath), path);
        log.info("获取解压数据文件地址:{}", path);
        MysqlDataBackupUtil.dbRestore(getIP(url),getPort(url),userName, password, getName(url), path + name);
        MysqlDataBackupUtil.deleteFiles(path + name);
        return R.status(true);
    }

    /**
     * 删除 数据备份管理表
     */
    @PostMapping("/remove")
    @ApiOperationSupport(order = 7)
    @Operation(summary = "逻辑删除", description = "传入ids")
    public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String dataBackupnIds) {
        List<DataBackupn> backupns = dataBackupnService.listByIds(Arrays.stream(dataBackupnIds.split(",")).toList());
        if (MysqlDataBackupUtil.MysqlPathSystem) {
            backupns.forEach(b ->
                    MysqlDataBackupUtil.deleteFiles(
                            b.getUrl().replaceAll("/statics", localFilePath)));
        }
        return R.status(dataBackupnService.removeByIds(Arrays.stream(dataBackupnIds.split(",")).toList()));
    }


    public String getIP(String url) {
        int begin = url.indexOf("//");
        int end = url.lastIndexOf("/");
        if (begin > -1 && end > -1 && end > begin) {
            String hostStr = url.substring(begin + 2, end);
            int index = hostStr.indexOf(":");
            if (index > 0) {
                return hostStr.substring(0, index);
            } else {
                return hostStr;
            }
        }
        return null;
    }

    public String getPort(String url) {
        int begin = url.indexOf("//");
        int end = url.lastIndexOf("/");
        if (begin > -1 && end > -1 && end > begin) {
            String hostStr = url.substring(begin + 2, end + 1);
            int index = hostStr.indexOf(":");
            int indexE = hostStr.indexOf("/");
            if (index > 0) {
                return hostStr.substring(index + 1, indexE);
            } else {
                return hostStr;
            }
        }
        return null;
    }

    public String getName(String url) {
        int begin = url.indexOf("//");
        int end = url.lastIndexOf("?");
        if (begin > -1 && end > -1 && end > begin) {
            String hostStr = url.substring(begin + 2, end + 1);
            int index = hostStr.indexOf("/");
            int indexE = hostStr.indexOf("?");
            if (index > 0) {
                return hostStr.substring(index + 1, indexE);
            } else {
                return hostStr;
            }
        }
        return null;
    }
}
