package me.qwq.doghouse.entity.config;

import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import lombok.experimental.Accessors;
import me.qwq.doghouse.annotation.ConfigInfo;
import me.qwq.doghouse.annotation.StaticAttribute;
import me.qwq.doghouse.constants.UsefulRegex;
import me.qwq.doghouse.interfaces.IConfig;
import me.qwq.doghouse.pojo.bo.CidrBlock;
import me.qwq.doghouse.util.IPUtils;

@SuppressWarnings("serial")
@Data
@Accessors(chain=true)
@ConfigInfo(field="network", name="网络设置", initDefault=true)
public class NetworkConfig implements Serializable, IConfig<NetworkConfig> {

    @StaticAttribute("ProxyTypeEnum")
    private Proxy.Type proxyType = Proxy.Type.DIRECT;
    
    @Pattern(regexp  = UsefulRegex.BLANK + UsefulRegex.OR + UsefulRegex.IPv4,
            message = "非法 Host")
    private String proxyHost = "";
    
    @Min(1)
    @Max(65535)
    private Integer proxyPort = 1;
    
    @NotNull
    private Boolean ignoreHttpsVerification = false;
    
    @Pattern(regexp = "^((\\s*|" + UsefulRegex.IPv4 + ")(\\r?\\n?))*$")
    private String trustedProxies;
    
    @JsonIgnore
    public List<String> getTrustedProxiesList() {
        if (StringUtils.isBlank(trustedProxies)) {
            return new ArrayList<>();
        }
        return new ArrayList<>(trustedProxies.lines().toList());
    }
    
    /**
     * 根据配置获取代理
     * @return
     */
    @JsonIgnore
    public Proxy getProxy () {
        if (getProxyType() != null && getProxyType() != Proxy.Type.DIRECT) {
            return new Proxy(getProxyType(), 
                    new InetSocketAddress(getProxyHost(), getProxyPort()));
        }
        return Proxy.NO_PROXY;
    }
    
    /**
     * 根据配置获取代理 Url
     * @return
     */
    public String getProxyUrl() {
        Proxy.Type type = getProxyType();
        String host = getProxyHost();
        Integer port = getProxyPort();
        if (ObjectUtils.anyNull(type, host, port)) {
            return null;
        }
        if (type == Proxy.Type.DIRECT) return null;
        StringBuilder sb = new StringBuilder()
            .append(type == Proxy.Type.SOCKS ? "socks5://" : "http://")
            .append(host).append(':').append(port);
        return sb.toString();
    }
    
    @JsonIgnore
    private Set<String> trustedIpList;

    @JsonIgnore
    public Set<String> getTrustedIpList() {
        if (trustedIpList == null || trustedIpList.isEmpty()) {
            // 从 trustedProxies 中恢复
            trustedIpList = new HashSet<>();
            for (String potentialIp : getTrustedProxiesList()) {
                if (IPUtils.isIP(potentialIp)) {
                    trustedIpList.add(potentialIp);
                }
            }
        }
        return trustedIpList;
    }
    
    @JsonIgnore
    private Set<CidrBlock> trustedCidrBlockList;

    @JsonIgnore
    public Set<CidrBlock> getTrustedCidrBlockList() {
        if (trustedCidrBlockList == null || trustedCidrBlockList.isEmpty()) {
            // 从 trustedProxies 中恢复
            trustedCidrBlockList = new HashSet<>();
            for (String potentialCidr : getTrustedProxiesList()) {
                if (IPUtils.isCIDR(potentialCidr)) {
                    trustedCidrBlockList.add(new CidrBlock(potentialCidr));
                }
            }
        }
        return trustedCidrBlockList;
    }
    
    public NetworkConfig afterSaving() {
        trustedIpList = null;
        trustedCidrBlockList = null;
        return this;
    }
}
