package com.chenyang.nse.bussiness.controller.ip;

import com.chenyang.nse.bussiness.commmon.json.RespHelper;
import com.chenyang.nse.bussiness.commmon.json.Response;
import com.chenyang.nse.bussiness.entity.ip.Ip;
import com.chenyang.nse.bussiness.tools.command.CommandTool;
import com.chenyang.nse.bussiness.tools.msg.MesUtil;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping({"/ip"})
public class ChangeIPController {
   public static final String QUOTATION_MARK = "\"";
   public static final String IP_START = "IPADDR=\"";
   public static final String SUBNET_MASK_START = "PREFIX=\"";
   public static final String GATEWAY_START = "GATEWAY=\"";
   public static final String DNS_START = "DNS1=\"";
   public static final String LINUX_IP_PATH = "/etc/sysconfig/network-scripts/ifcfg-";

   @GetMapping({"/show"})
   public Response show() {
      return RespHelper.successResp(this.showIpList());
   }

   @PostMapping({"/update"})
   public Response update(@RequestBody Map<String, String> param) throws UnknownHostException {
      String networkInterfaceName = (String)param.get("networkInterface");
      if (StringUtils.isEmpty(networkInterfaceName)) {
         return RespHelper.createResp(false, "IP_ERR_001", MesUtil.getMsg("IP_ERR_001", new String[0]));
      } else {
         String newIpAddress = (String)param.get("inetAddress");
         if (StringUtils.isEmpty(newIpAddress)) {
            return RespHelper.createResp(false, "IP_ERR_002", MesUtil.getMsg("IP_ERR_002", new String[0]));
         } else if (!this.validateIP(newIpAddress)) {
            return RespHelper.createResp(false, "IP_ERR_004", MesUtil.getMsg("IP_ERR_004", new String[0]));
         } else {
            String newSubnetMask = (String)param.get("subnetMask");
            if (StringUtils.isEmpty(newSubnetMask)) {
               return RespHelper.createResp(false, "IP_ERR_003", MesUtil.getMsg("IP_ERR_003", new String[0]));
            } else if (!this.validateSubnetMask(newSubnetMask)) {
               return RespHelper.createResp(false, "IP_ERR_005", MesUtil.getMsg("IP_ERR_005", new String[0]));
            } else {
               Thread thread = new Thread(() -> this.asyncMethodChangeIp(param));
               thread.start();
               return RespHelper.successResp();
            }
         }
      }
   }

   public void asyncMethodChangeIp(Map<String, String> param) {
      this.changeIpFromFile(param);
      CommandTool.command("systemctl restart network");
   }

   private List<Ip> showIpList() {
      List<Ip> list = new ArrayList();

      try {
         Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();

         while(networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
            if (!networkInterface.isLoopback() && !networkInterface.isVirtual()) {
               Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();

               while(inetAddresses.hasMoreElements()) {
                  InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();
                  String subnetMask = this.getSubnetMask(networkInterface);
                  if (inetAddress.getAddress().length == 4) {
                     Ip ip = new Ip();
                     ip.setNetworkInterface(networkInterface.getName());
                     ip.setInetAddress(inetAddress.getHostAddress());
                     ip.setSubnetMask(subnetMask);
                     ip.setGateway(this.getDefaultGateway(networkInterface));
                     ip.setDns(this.getDNSServers());
                     list.add(ip);
                  }
               }
            }
         }
      } catch (SocketException e) {
         e.printStackTrace();
      } catch (Exception e) {
         e.printStackTrace();
      }

      return list;
   }

   private String getSubnetMask(NetworkInterface networkInterface) throws SocketException {
      for(InterfaceAddress address : networkInterface.getInterfaceAddresses()) {
         if (address.getAddress() instanceof Inet4Address) {
            int maskLength = address.getNetworkPrefixLength();
            int mask = -1 << 32 - maskLength;
            String subnetMask = Integer.toString(mask >> 24 & 255) + "." + Integer.toString(mask >> 16 & 255) + "." + Integer.toString(mask >> 8 & 255) + "." + Integer.toString(mask & 255);
            return subnetMask;
         }
      }

      return null;
   }

   public void changeIpFromFile(Map<String, String> params) {
      String filePath = "/etc/sysconfig/network-scripts/ifcfg-" + (String)params.get("networkInterface");
      String newIpAddress = (String)params.get("inetAddress");
      String newSubnetMask = (String)params.get("subnetMask");
      String gateway = (String)params.get("gateway");
      String dns = (String)params.get("dns");

      try {
         CommandTool.command("cp " + filePath + " " + filePath + ".bak");
         File file = new File(filePath);
         File tempFile = new File(filePath + ".tmp");
         BufferedReader reader = new BufferedReader(new FileReader(file));
         BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));

         String line;
         while((line = reader.readLine()) != null) {
            if (line.startsWith("IPADDR=\"")) {
               line = "IPADDR=\"" + newIpAddress + "\"";
            } else if (line.startsWith("PREFIX=\"")) {
               line = "PREFIX=\"" + newSubnetMask + "\"";
            } else if (line.startsWith("GATEWAY=\"") && StringUtils.isNotEmpty(gateway)) {
               line = "GATEWAY=\"" + gateway + "\"";
            } else if (line.startsWith("DNS1=\"") && StringUtils.isNotEmpty(dns)) {
               line = "DNS1=\"" + dns + "\"";
            }

            writer.write(line);
            writer.newLine();
         }

         reader.close();
         writer.close();
         file.delete();
         tempFile.renameTo(file);
         System.out.println("IP地址和子网掩码修改成功！");
      } catch (IOException e) {
         System.out.println("发生异常：" + e.getMessage());
      }

   }

   private int subnetMaskToDecimal(String subnetMask) throws UnknownHostException {
      InetAddress inetAddress = InetAddress.getByName(subnetMask);
      byte[] addressBytes = inetAddress.getAddress();
      int cidrNotation = 0;

      for(byte b : addressBytes) {
         for(int i = 7; i >= 0; --i) {
            if ((b >> i & 1) == 0) {
               return cidrNotation;
            }

            ++cidrNotation;
         }
      }

      return cidrNotation;
   }

   public boolean validateIP(String ipAddress) {
      String ipPattern = "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
      return Pattern.matches(ipPattern, ipAddress);
   }

   public boolean validateSubnetMask(String subnetMask) {
      String subnetMaskPattern = "^(128|192|224|240|248|252|254|255)\\.((0|128|192|224|240|248|252|254|255)\\.){2}(0|128|192|224|240|248|252|254|255)$";
      return Pattern.matches(subnetMaskPattern, subnetMask);
   }

   private String getDefaultGateway(NetworkInterface networkInterface) throws Exception {
      Process process = Runtime.getRuntime().exec("ip route show dev " + networkInterface.getName());
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

      String line;
      while((line = reader.readLine()) != null) {
         if (line.startsWith("default")) {
            String[] parts = line.split("\\s+");
            String gateway = parts[2];
            reader.close();
            process.destroy();
            return gateway;
         }
      }

      reader.close();
      process.destroy();
      return null;
   }

   private String getDNSServers() throws Exception {
      Process process = Runtime.getRuntime().exec("cat /etc/resolv.conf");
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
      StringBuilder dnsServers = new StringBuilder();

      String line;
      while((line = reader.readLine()) != null) {
         if (line.startsWith("nameserver")) {
            String[] parts = line.split("\\s+");
            if (parts.length >= 2) {
               String dnsServer = parts[1];
               dnsServers.append(dnsServer).append(", ");
            }
         }
      }

      reader.close();
      process.destroy();
      String dns = "";
      if (dnsServers != null && dnsServers.length() > 0) {
         dns = dnsServers.substring(0, dnsServers.length() - 2).trim();
      }

      return dns;
   }

   public static void main(String[] args) {
      try {
         InetAddress localHost = InetAddress.getLocalHost();
         String hostName = localHost.getHostName();
         System.out.println("主机名: " + hostName);
         InetAddress[] addresses = InetAddress.getAllByName(hostName);
         System.out.println("DNS IP 地址:");

         for(InetAddress address : addresses) {
            System.out.println(address.getHostAddress());
         }
      } catch (UnknownHostException e) {
         System.out.println("无法获取DNS信息：" + e.getMessage());
      }

   }
}
