package com.ruoyi.web.controller.druid;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.druid.domain.DruidConfig;
import com.ruoyi.druid.service.IDruidConfigService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import sun.applet.Main;

/**
 * 多数据源配置Controller
 *
 * @author ruoyi
 * @date 2024-07-14
 */
@Slf4j
@RestController
@RequestMapping("/druidConfig")
public class DruidConfigController extends BaseController
{
    @Autowired
    private IDruidConfigService druidConfigService;
    @Autowired
    private ServerConfig serverConfig;

    private String getUrl(DruidConfig druidConfig) {
        String url = "";
        if(StringUtils.equals(druidConfig.getType(), "MySQL")) {//jdbc:mysql://localhost:3306/dataCenter
            url = "jdbc:mysql://"+druidConfig.getHost()+":"+druidConfig.getPort()+"/"+druidConfig.getDataBase();
        }
        else if(StringUtils.equals(druidConfig.getType(), "SQLServer")) {//jdbc:sqlserver://localhost:7777;database=sqlserver
            url = "jdbc:sqlserver://"+druidConfig.getHost()+":"+druidConfig.getPort()+";database="+druidConfig.getDataBase()+";encrypt=true;trustServerCertificate=true;";
        }
        else if(StringUtils.equals(druidConfig.getType(), "Oracle")) {//jdbc:oracle:thin:@localhost:1521:oracle
            url = "jdbc:oracle:thin:@"+druidConfig.getHost()+":"+druidConfig.getPort()+":"+druidConfig.getDataBase();
        }
        else if(StringUtils.equals(druidConfig.getType(), "PostgreSQL")) {//jdbc:postgresql://localhost:5432/postgres
            url = "jdbc:postgresql://"+druidConfig.getHost()+":"+druidConfig.getPort()+"/"+druidConfig.getDataBase();
        }

        return url;
    }
    private DruidConfig urlSplit(String url, String type) {
        DruidConfig druidConfig = new DruidConfig();
        if(StringUtils.equals(type, "MySQL") || StringUtils.equals(type, "PostgreSQL")) {//jdbc:mysql://localhost:3306/dataCenter
            if(url.contains("?")) {
                druidConfig.setDataBase(url.substring(url.lastIndexOf("/")+1, url.indexOf("?")));
            } else {
                druidConfig.setDataBase(url.substring(url.lastIndexOf("/")+1));
            }
            druidConfig.setHost(url.substring(url.indexOf("://")+3, url.lastIndexOf(":")));
            druidConfig.setPort(url.substring(url.lastIndexOf(":")+1, url.lastIndexOf("/")));
        }
        else if(StringUtils.equals(type, "SQLServer")) {//jdbc:sqlserver://localhost:7777;database=sqlserver
            druidConfig.setDataBase(url.substring(url.lastIndexOf("database=")+9, url.indexOf(";encrypt")));
            druidConfig.setHost(url.substring(url.indexOf("://")+3, url.lastIndexOf(":")));
            druidConfig.setPort(url.substring(url.lastIndexOf(":")+1, url.indexOf(";database=")));
        }
        else if(StringUtils.equals(type, "Oracle")) {//jdbc:oracle:thin:@localhost:1521:oracle
            String str = url.substring(url.indexOf(":@")+2);
            druidConfig.setDataBase(str.substring(str.lastIndexOf(":")+1));
            druidConfig.setHost(str.substring(0,str.indexOf(":")));
            druidConfig.setPort(str.substring(str.indexOf(":")+1, str.lastIndexOf(":")));
        }

        return druidConfig;
    }

    /**
     * 查询多数据源配置文件——application-druid.yml
     */
    @GetMapping("/list")
    public TableDataInfo list()
    {
        startPage();
        //List<DruidConfig> list = druidConfigService.selectDruidConfigList(druidConfig);
        try {
            String path = "D:\\langhengcode\\DataCenter\\ruoyi-admin\\src\\main\\resources\\application-druid.yml";
            FileInputStream fis = new FileInputStream(path);

            DumperOptions options = new DumperOptions();
            options.setIndent(4);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(options);
            Map<String, Object> config = yaml.load(fis);

            Map<String, Object> spring = (Map) config.get("spring");
            Map<String, Object> datasource = (Map) spring.get("datasource");
            Map<String, Object> druid = (Map) datasource.get("druid");

            List<DruidConfig> list = new ArrayList<>();
            for (Map.Entry<String, Object> entry : druid.entrySet()) {
                String propertyName = entry.getKey();
                Map<String, Object> map = (Map) entry.getValue();

                String url = map.get("url").toString();
                DruidConfig druidConfig = urlSplit(url, String.valueOf(map.get("type")));

                druidConfig.setPropertyName(propertyName);
                druidConfig.setType(String.valueOf(map.get("type")));
                druidConfig.setVersion(String.valueOf(map.get("version")));
                druidConfig.setDriverClass(String.valueOf(map.get("driverClassName")));
                druidConfig.setUser(String.valueOf(map.get("username")));
                druidConfig.setPassword(String.valueOf(map.get("password")));
                druidConfig.setEnabled((Boolean) map.get("enabled"));
                druidConfig.setJarName(String.valueOf(map.get("jarName")));

                list.add(druidConfig);
            }

            fis.close();
            return getDataTable(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 导出多数据源配置列表
     */
    /*@PreAuthorize("@ss.hasPermi('druid:druid:export')")
    @Log(title = "多数据源配置", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DruidConfig druidConfig)
    {
        List<DruidConfig> list = druidConfigService.selectDruidConfigList(druidConfig);
        ExcelUtil<DruidConfig> util = new ExcelUtil<DruidConfig>(DruidConfig.class);
        util.exportExcel(response, list, "多数据源配置数据");
    }*/

    /**
     * 获取多数据源配置详细信息
     */
    /*@PreAuthorize("@ss.hasPermi('druid:druid:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(druidConfigService.selectDruidConfigById(id));
    }*/

    /**
     * 新增多数据源配置
     */
    /*@PreAuthorize("@ss.hasPermi('druid:druid:add')")
    @Log(title = "多数据源配置", businessType = BusinessType.INSERT)*/
    @PostMapping
    public AjaxResult add(@RequestBody DruidConfig druidConfig)
    {
        try {
            // 读取YAML文件[
            //D:\langhengcode\DataCenter\ruoyi-admin\src\main\resources\application-druid.yml
            String path = "D:\\langhengcode\\DataCenter\\ruoyi-admin\\src\\main\\resources\\application-druid.yml";
            FileInputStream fis = new FileInputStream(path);

            DumperOptions options = new DumperOptions();
            options.setIndent(4);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(options);
            Map<String, Object> config = yaml.load(fis);

            Map<String, Object> spring = (Map) config.get("spring");
            Map<String, Object> datasource = (Map) spring.get("datasource");
            Map<String, Object> druid = (Map) datasource.get("druid");

            String url = getUrl(druidConfig);
            Map<String, Object> map = new HashMap<>();
            map.put("type", druidConfig.getType());
            map.put("enabled", druidConfig.getEnabled());
            map.put("url", url);
            map.put("username", druidConfig.getUser());
            map.put("password", druidConfig.getPassword());
            map.put("driverClassName", druidConfig.getDriverClass());
            map.put("version", druidConfig.getVersion());

            // 修改配置项
            druid.put(druidConfig.getPropertyName(), map);

            // 将修改后的配置写回文件
            FileWriter output = new FileWriter(path);
            yaml.dump(config, output);

            fis.close();
            output.close();
            return AjaxResult.success("操作成功");
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("操作失败");
        }
    }

    /**
     * 修改多数据源配置
     */
    /*@PreAuthorize("@ss.hasPermi('druid:druid:edit')")
    @Log(title = "多数据源配置", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody DruidConfig druidConfig)
    {
        try {
            // 读取YAML文件[
            //D:\langhengcode\DataCenter\ruoyi-admin\src\main\resources\application-druid.yml
            String path = "D:\\langhengcode\\DataCenter\\ruoyi-admin\\src\\main\\resources\\application-druid.yml";
            FileInputStream fis = new FileInputStream(path);

            DumperOptions options = new DumperOptions();
            options.setIndent(4);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(options);
            Map<String, Object> config = yaml.load(fis);

            Map<String, Object> spring = (Map) config.get("spring");
            Map<String, Object> datasource = (Map) spring.get("datasource");
            Map<String, Object> druid = (Map) datasource.get("druid");

            String url = "jdbc:"+druidConfig.getType()+"://"+druidConfig.getHost()+":"+druidConfig.getPort()+"/"+druidConfig.getDataBase();
            Map<String, Object> map = new HashMap<>();
            map.put("enabled", druidConfig.getEnabled());
            map.put("url", url);
            map.put("username", druidConfig.getUser());
            map.put("password", druidConfig.getPassword());
            map.put("driverClassName", druidConfig.getDriverClass());
            map.put("version", druidConfig.getVersion());

            // 修改配置项
            druid.put(druidConfig.getPropertyName(), map);

            // 将修改后的配置写回文件
            FileWriter output = new FileWriter(path);
            yaml.dump(config, output);

            fis.close();
            output.close();
            return AjaxResult.success("修改成功");
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("修改失败");
        }
    }*/

    /**
     * 删除多数据源配置
     */
    /*@PreAuthorize("@ss.hasPermi('druid:druid:remove')")
    @Log(title = "多数据源配置", businessType = BusinessType.DELETE)*/
	@DeleteMapping("/{propertyName}")
    public AjaxResult remove(@PathVariable String propertyName)
    {
        try {
            // 读取YAML文件[
            //D:\langhengcode\DataCenter\ruoyi-admin\src\main\resources\application-druid.yml
            String path = "D:\\langhengcode\\DataCenter\\ruoyi-admin\\src\\main\\resources\\application-druid.yml";
            FileInputStream fis = new FileInputStream(path);

            DumperOptions options = new DumperOptions();
            options.setIndent(4);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(options);
            Map<String, Object> config = yaml.load(fis);

            Map<String, Object> spring = (Map) config.get("spring");
            Map<String, Object> datasource = (Map) spring.get("datasource");
            Map<String, Object> druid = (Map) datasource.get("druid");

            // 删除配置项
            druid.remove(propertyName);

            // 将修改后的配置写回文件
            FileWriter output = new FileWriter(path);
            yaml.dump(config, output);

            fis.close();
            output.close();
            return AjaxResult.success("删除成功");
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("删除失败");
        }
    }

    /**
     * 通过下载路径下载数据库驱动
     * @param downloadPath 数据库驱动下载路径
     * @param response
     */
    @PostMapping("/driverClassDownload")
    public AjaxResult driverClassDownload(String downloadPath, String propertyName, HttpServletResponse response) {
        try {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

            String fileName = StringUtils.substringAfterLast(downloadPath, "/");
            FileUtils.setAttachmentResponseHeader(response, fileName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
            return AjaxResult.success();
        } catch (Exception e) {
            log.error("下载文件失败", e);
            e.printStackTrace();
        }
        return AjaxResult.error("下载文件失败");
    }

    /**
     * 数据库驱动上传
     * @param file 数据库驱动
     */
    @PostMapping("/driverClassUpload")
    public AjaxResult driverClassUpload(MultipartFile file, String propertyName) {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getDriverClassUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.uploadDriverClass(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());

            String path = "D:\\langhengcode\\DataCenter\\ruoyi-admin\\src\\main\\resources\\application-druid.yml";
            FileInputStream fis = new FileInputStream(path);

            DumperOptions options = new DumperOptions();
            options.setIndent(4);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(options);
            Map<String, Object> config = yaml.load(fis);

            Map<String, Object> spring = (Map) config.get("spring");
            Map<String, Object> datasource = (Map) spring.get("datasource");
            Map<String, Object> druid = (Map) datasource.get("druid");


            Map<String, Object> map = (Map) druid.get(propertyName);
            map.put("jarName",file.getOriginalFilename());

            // 修改配置项
            druid.put(propertyName, map);

            // 将修改后的配置写回文件
            FileWriter output = new FileWriter(path);
            yaml.dump(config, output);

            fis.close();
            output.close();
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    public static void main(String[] args) {
        Properties properties = System.getProperties();
        String rootPath = properties.getProperty("user.dir");
        String path = rootPath + File.separator + "config" + File.separator + "application-druid.yml";
        System.out.println(path);



        /*try {
            // 读取YAML文件
            //D:\langhengcode\DataCenter\ruoyi-admin\src\main\resources\application-druid.yml
            String path = "D:\\langhengcode\\DataCenter\\ruoyi-admin\\src\\main\\resources\\application-druid.yml";
            FileInputStream fis = new FileInputStream(path);

            DumperOptions options = new DumperOptions();
            options.setIndent(4);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            Yaml yaml = new Yaml(options);

            Map<String, Object> config = yaml.load(fis);


            Map<String, Object> spring = (Map) config.get("spring");
            Map<String, Object> datasource = (Map) spring.get("datasource");
            Map<String, Object> druid = (Map) datasource.get("druid");

            List<DruidConfig> list = new ArrayList<>();
            for (Map.Entry<String, Object> entry : druid.entrySet()) {
                String propertyName = entry.getKey();
                Map<String, Object> map = (Map) entry.getValue();
                String url = map.get("url").toString();
                String str = "";
                if(url.contains("?")) {
                    str = url.substring(url.indexOf("://") + 3, url.indexOf("?"));
                } else {
                    str = url.substring(url.indexOf("://") + 3);
                }

                DruidConfig druidConfig = new DruidConfig();
                druidConfig.setPropertyName(propertyName);
                druidConfig.setType(String.valueOf(map.get("type")));
                druidConfig.setVersion(String.valueOf(map.get("version")));
                druidConfig.setDriverClass(String.valueOf(map.get("driverClassName")));
                druidConfig.setDataBase(str.substring(str.indexOf("/")+1));
                druidConfig.setHost(str.substring(0,str.indexOf(":")));
                druidConfig.setPort(str.substring(str.indexOf(":")+1,str.indexOf("/")));
                druidConfig.setUser(String.valueOf(map.get("username")));
                druidConfig.setPassword(String.valueOf(map.get("password")));
                druidConfig.setEnabled(String.valueOf(map.get("enabled")));

                list.add(druidConfig);
            }

            System.out.println(list.toString());
            *//*Map<String, Object> master = new HashMap<>();
            master.put("url", "jdbc:mysql://localhost:3306/dataCenter?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8");
            master.put("username", "root");
            master.put("password", 123456);
            master.put("driverClassName", "com.mysql.cj.jdbc.Driver");

            Map<String, Object> slave = new HashMap<>();
            slave.put("enabled", true);
            slave.put("url", "jdbc:mysql://localhost:3306/dataexchange?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8");
            slave.put("username", "root");
            slave.put("password", 123456);
            slave.put("driverClassName", "com.mysql.cj.jdbc.Driver");

            // 修改配置项
            druid.put("master", master);
            druid.put("slave", slave);

            // 将修改后的配置写回文件
            FileWriter output = new FileWriter(path);
            yaml.dump(config, output);*//*

            fis.close();
            //output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }*/

    }

}
