package service

import (
	"context"
	"fmt"
	"net/url"
	"strconv"
	"strings"
)

// ImportResult 是批量导入的汇总结果。
type ImportResult struct {
	Created []ProxyView  `json:"created"`
	Failed  []ImportFail `json:"failed"`
}

// ImportFail 记录解析或入库失败的行;Line 已脱敏,凭据段以 *** 代替。
type ImportFail struct {
	LineNo int    `json:"lineNo"`
	Line   string `json:"line"`
	Reason string `json:"reason"`
}

// Import 逐行解析并创建代理;空行与 # 注释跳过,失败行不阻断后续。
func (s *ProxyService) Import(ctx context.Context, text string) (ImportResult, error) {
	res := ImportResult{Created: []ProxyView{}, Failed: []ImportFail{}}
	for i, raw := range strings.Split(text, "\n") {
		line := strings.TrimSpace(raw)
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		in, err := parseProxyLine(line)
		if err == nil {
			var view ProxyView
			if view, err = s.Create(ctx, in); err == nil {
				res.Created = append(res.Created, view)
				continue
			}
		}
		res.Failed = append(res.Failed, ImportFail{
			LineNo: i + 1, Line: maskProxyLine(line), Reason: err.Error(),
		})
	}
	return res, nil
}

// parseProxyLine 解析一行代理,支持两种格式:
//
//	scheme://[user:pass@]host:port(scheme 为 socks5 / http / https)
//	host:port[:user:pass](缺省按 socks5)
func parseProxyLine(line string) (ProxyInput, error) {
	if strings.Contains(line, "://") {
		return parseProxyURI(line)
	}
	parts := strings.Split(line, ":")
	if len(parts) != 2 && len(parts) != 4 {
		return ProxyInput{}, fmt.Errorf("格式应为 host:port 或 host:port:user:pass: %w", ErrProxyInvalid)
	}
	port, err := strconv.Atoi(parts[1])
	if err != nil {
		return ProxyInput{}, fmt.Errorf("端口非数字: %w", ErrProxyInvalid)
	}
	in := ProxyInput{Type: "socks5", Host: parts[0], Port: port}
	if len(parts) == 4 {
		in.Username = parts[2]
		in.Password = &parts[3]
	}
	return in, nil
}

// parseProxyURI 解析 scheme://[user:pass@]host:port。
func parseProxyURI(line string) (ProxyInput, error) {
	u, err := url.Parse(line)
	if err != nil {
		return ProxyInput{}, fmt.Errorf("URI 解析失败: %w", ErrProxyInvalid)
	}
	port, err := strconv.Atoi(u.Port())
	if err != nil {
		return ProxyInput{}, fmt.Errorf("缺少或非法端口: %w", ErrProxyInvalid)
	}
	in := ProxyInput{Type: u.Scheme, Host: u.Hostname(), Port: port}
	if u.User != nil {
		in.Username = u.User.Username()
		if pw, ok := u.User.Password(); ok {
			in.Password = &pw
		}
	}
	return in, nil
}

// maskProxyLine 把行内可能的凭据段替换为 ***,避免密码回显到响应。
func maskProxyLine(line string) string {
	if i := strings.Index(line, "://"); i >= 0 {
		if j := strings.LastIndex(line, "@"); j > i {
			return line[:i+3] + "***@" + line[j+1:]
		}
		return line
	}
	if parts := strings.Split(line, ":"); len(parts) > 2 {
		return strings.Join(parts[:2], ":") + ":***"
	}
	return line
}
