package menu

import (
	"bufio"
	"context"
	"fmt"
	"os"
	"strings"
	"unicode"

	"frpc-tool/internal/autostart"
	"frpc-tool/internal/runner"
	"frpc-tool/internal/util"
)

const (
	colorGreen   = "\033[32m"
	colorYellow  = "\033[33m"
	colorReset   = "\033[0m"
	bannerWidth  = 53
	statusIndent = "    "
)

func green(text string) string {
	return colorGreen + text + colorReset
}

func yellow(text string) string {
	return colorYellow + text + colorReset
}

func formatFrpcStatus(status string) string {
	switch {
	case status == "运行中":
		return green(status)
	case status == "不支持":
		return yellow(status)
	default:
		return yellow("未知")
	}
}

func formatAutostartStatus(status string) string {
	switch {
	case status == "已启用":
		return green(status)
	case status == "不支持":
		return yellow(status)
	default:
		return yellow("未知")
	}
}

// Run 启动交互式菜单。
func Run(ctx context.Context, env util.Environment) {
	reader := bufio.NewReader(os.Stdin)
	for {
		statusSummary := fetchStatusSummary(ctx, env)
		autostartSummary := fetchAutostartSummary(ctx, env)
		clearScreen()
		printHeader(statusSummary, autostartSummary)
		printMainMenu()
		fmt.Fprint(os.Stdout, "请选择操作编号并回车: ")
		input, err := reader.ReadString('\n')
		if err != nil {
			fmt.Fprintf(os.Stderr, "读取输入失败：%v\n", err)
			return
		}
		input = strings.TrimSpace(input)
		if input == "" {
			continue
		}
		if input == "5" || input == "0" || strings.EqualFold(input, "q") {
			fmt.Fprintln(os.Stdout, "已退出。")
			return
		}

		needPause := true

		switch input {
		case "1":
			_ = HandleInstall(env, os.Stdout, os.Stderr)
		case "2":
			_ = deployConfigInteractive(ctx, reader, env)
		case "3":
			needPause = false
			manageRuntime(ctx, reader, env)
		case "4":
			needPause = false
			manageAutostart(ctx, reader, env)
		default:
			fmt.Fprintln(os.Stdout, "未知选项，请重新选择。")
		}

		if needPause {
			waitForEnter(reader)
		}
	}
}

func prompt(reader *bufio.Reader, msg string) string {
	fmt.Fprint(os.Stdout, msg)
	input, _ := reader.ReadString('\n')
	return strings.TrimSpace(input)
}

func printHeader(status, autostartStatus string) {
	fmt.Fprintln(os.Stdout, banner(" 服务状态 "))
	fmt.Fprintf(os.Stdout, "%sfrpc: %s | 自启: %s\n", statusIndent, formatFrpcStatus(status), formatAutostartStatus(autostartStatus))
	fmt.Fprintln(os.Stdout, banner(" frpc + 管理 "))
}

func banner(text string) string {
	textWidth := displayWidth(text)
	if textWidth >= bannerWidth {
		return text
	}
	total := bannerWidth - textWidth
	left := total / 2
	right := total - left
	if left < 0 {
		left = 0
	}
	if right < 0 {
		right = 0
	}
	return strings.Repeat("=", left) + text + strings.Repeat("=", right)
}

func displayWidth(s string) int {
	width := 0
	for _, r := range s {
		width += runeWidth(r)
	}
	return width
}

func runeWidth(r rune) int {
	switch {
	case r == 0:
		return 0
	case r == '\t':
		return 4
	case unicode.Is(unicode.Han, r),
		unicode.In(r, unicode.Hangul, unicode.Hiragana, unicode.Katakana),
		(r >= 0x1100 && r <= 0x115F),
		(r >= 0x2329 && r <= 0x232A),
		(r >= 0x2E80 && r <= 0xA4CF),
		(r >= 0xAC00 && r <= 0xD7A3),
		(r >= 0xF900 && r <= 0xFAFF),
		(r >= 0xFE30 && r <= 0xFE6F),
		(r >= 0xFF00 && r <= 0xFF60),
		(r >= 0xFFE0 && r <= 0xFFE6):
		return 2
	default:
		return 1
	}
}

func printMainMenu() {
	fmt.Fprintln(os.Stdout, " 1) 立即安装")
	fmt.Fprintln(os.Stdout, " 2) 配置设置")
	fmt.Fprintln(os.Stdout, " 3) 启动管理")
	fmt.Fprintln(os.Stdout, " 4) 开机自启")
	fmt.Fprintln(os.Stdout, " 5) 退出菜单")
	fmt.Fprintln(os.Stdout)
}

func clearScreen() {
	// 使用 ANSI 转义序列清空终端并将光标移至左上角。
	fmt.Print("\033[H\033[2J")
}

func deployConfigInteractive(ctx context.Context, reader *bufio.Reader, env util.Environment) error {
	if exists, err := configExists(env.ConfigPath); err == nil && exists {
		if !confirmOverwrite(reader, env.ConfigPath) {
			fmt.Fprintln(os.Stdout, "已取消配置部署。")
			return nil
		}
	}

	source, ok := selectConfigSource(reader)
	if !ok {
		fmt.Fprintln(os.Stdout, "已取消配置部署。")
		return nil
	}
	return HandleDeployConfig(ctx, env, source, os.Stdout, os.Stderr)
}

func configExists(path string) (bool, error) {
	if path == "" {
		return false, nil
	}
	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}

func confirmOverwrite(reader *bufio.Reader, path string) bool {
	msg := fmt.Sprintf("检测到已存在配置文件 %s，是否覆盖？(y/N): ", path)
	answer := prompt(reader, msg)
	switch strings.ToLower(answer) {
	case "y", "yes":
		return true
	default:
		return false
	}
}

func selectConfigSource(reader *bufio.Reader) (string, bool) {
	for {
		clearScreen()
		fmt.Fprintln(os.Stdout, "配置部署来源选择")
		fmt.Fprintln(os.Stdout, "----------------")
		fmt.Fprintln(os.Stdout, " 1) 远程 URL（默认）")
		fmt.Fprintln(os.Stdout, " 2) 本地模板")
		fmt.Fprintln(os.Stdout, " 0) 返回上一层")
		fmt.Fprintln(os.Stdout)
		fmt.Fprint(os.Stdout, "请选择并回车（直接回车等同选择 1）: ")

		input, _ := reader.ReadString('\n')
		input = strings.TrimSpace(input)
		if input == "" {
			input = "1"
		}

		switch strings.ToLower(input) {
		case "1":
			url := prompt(reader, "请输入远程配置 URL (回车重新选择): ")
			if strings.TrimSpace(url) == "" {
				continue
			}
			return url, true
		case "2":
			fmt.Fprintln(os.Stdout, "将使用内置本地模板。")
			return "", true
		case "0", "q", "quit":
			return "", false
		default:
			fmt.Fprintln(os.Stdout, "无效选择，请重试。按回车继续...")
			_, _ = reader.ReadString('\n')
		}
	}
}

func manageAutostart(ctx context.Context, reader *bufio.Reader, env util.Environment) {
	for {
		clearScreen()
		current := fetchAutostartSummary(ctx, env)
		fmt.Fprintln(os.Stdout, "==================== 开机自启 =====================")
		fmt.Fprintf(os.Stdout, "当前状态: %s\n\n", formatAutostartStatus(current))
		fmt.Fprintln(os.Stdout, " 1) 开启开机自启")
		fmt.Fprintln(os.Stdout, " 2) 关闭开机自启")
		fmt.Fprintln(os.Stdout, " 0) 返回上一级")
		fmt.Fprintln(os.Stdout)
		fmt.Fprint(os.Stdout, "请选择并回车: ")

		input, _ := reader.ReadString('\n')
		input = strings.TrimSpace(strings.ToLower(input))

		switch input {
		case "1":
			if err := HandleEnableService(ctx, env, os.Stdout, os.Stderr); err == nil {
				fmt.Fprintf(os.Stdout, "当前状态：%s\n", formatAutostartStatus(fetchAutostartSummary(ctx, env)))
			}
			waitForEnter(reader)
		case "2":
			if err := HandleDisableService(ctx, env, os.Stdout, os.Stderr); err == nil {
				fmt.Fprintf(os.Stdout, "当前状态：%s\n", formatAutostartStatus(fetchAutostartSummary(ctx, env)))
			}
			waitForEnter(reader)
		case "0", "q", "quit":
			return
		default:
			fmt.Fprintln(os.Stdout, "无效选择，请重试。")
			waitForEnter(reader)
		}
	}
}

func manageRuntime(ctx context.Context, reader *bufio.Reader, env util.Environment) {
	for {
		clearScreen()
		status := fetchStatusSummary(ctx, env)
		fmt.Fprintln(os.Stdout, "==================== 启动管理 =====================")
		fmt.Fprintf(os.Stdout, "当前状态: %s\n\n", formatFrpcStatus(status))
		fmt.Fprintln(os.Stdout, " 1) 启动 frpc")
		fmt.Fprintln(os.Stdout, " 2) 停止 frpc")
		fmt.Fprintln(os.Stdout, " 3) 重启 frpc")
		fmt.Fprintln(os.Stdout, " 4) 查看运行状态")
		fmt.Fprintln(os.Stdout, " 0) 返回上一级")
		fmt.Fprintln(os.Stdout)
		fmt.Fprint(os.Stdout, "请选择并回车: ")

		input, _ := reader.ReadString('\n')
		input = strings.TrimSpace(strings.ToLower(input))

		switch input {
		case "1":
			_ = HandleStart(ctx, env, os.Stdout, os.Stderr)
			waitForEnter(reader)
		case "2":
			_ = HandleStop(ctx, env, os.Stdout, os.Stderr)
			waitForEnter(reader)
		case "3":
			_ = HandleRestart(ctx, env, os.Stdout, os.Stderr)
			waitForEnter(reader)
		case "4":
			_ = HandleStatus(ctx, env, os.Stdout, os.Stderr)
			waitForEnter(reader)
		case "0", "q", "quit":
			return
		default:
			fmt.Fprintln(os.Stdout, "无效选择，请重试。")
			waitForEnter(reader)
		}
	}
}

func waitForEnter(reader *bufio.Reader) {
	fmt.Fprintln(os.Stdout, "\n按回车继续...")
	_, _ = reader.ReadString('\n')
}

func fetchStatusSummary(ctx context.Context, env util.Environment) string {
	r := runner.New(env)
	raw, err := r.Status(ctx)
	if err != nil {
		return fmt.Sprintf("未知（%v）", err)
	}
	return summarizeStatus(raw)
}

func fetchAutostartSummary(ctx context.Context, env util.Environment) string {
	manager := autostart.NewManager(env)
	if manager == nil {
		return "不支持"
	}
	installed, err := manager.IsInstalled(ctx)
	if err != nil {
		return fmt.Sprintf("状态未知（%v）", err)
	}
	if installed {
		return "已启用"
	}
	return "未启用"
}

func summarizeStatus(raw string) string {
	s := strings.TrimSpace(raw)
	if s == "" {
		return "未知"
	}

	lower := strings.ToLower(s)
	compact := strings.ReplaceAll(lower, " ", "")

	notRunningMarkers := []string{
		"未运行", "not running", "inactive", "stopped", "dead", "failed", "disabled",
		"exit status = 1", "exit status: 1", "last exit status = 1", "last exit status: 1",
		"state = stopped", "state=stopped", "state: stopped",
		"state = inactive", "state=inactive", "state: inactive",
	}
	for _, marker := range notRunningMarkers {
		if strings.Contains(lower, marker) {
			return "未运行"
		}
	}
	if strings.Contains(compact, "\"active\":false") ||
		strings.Contains(compact, "active=false") ||
		strings.Contains(compact, "\"active\"=0") ||
		strings.Contains(compact, "active=0") ||
		strings.Contains(compact, "pid=0") ||
		strings.Contains(compact, "\"pid\"=0") {
		return "未运行"
	}

	runningMarkers := []string{
		"正在运行", "active (running)", "active: active",
		"state = running", "state=running", "state: running",
	}
	for _, marker := range runningMarkers {
		if strings.Contains(lower, marker) {
			return "运行中"
		}
	}
	if (strings.Contains(lower, "running") && !strings.Contains(lower, "not running")) ||
		strings.Contains(compact, "\"active\":true") ||
		strings.Contains(compact, "active=true") ||
		strings.Contains(compact, "\"active\"=1") ||
		strings.Contains(compact, "active=1") ||
		strings.Contains(lower, "pid=") ||
		strings.Contains(lower, "pid =") ||
		strings.Contains(compact, "\"pid\":") ||
		strings.Contains(compact, "\"pid\"=") {
		return "运行中"
	}

	if idx := strings.IndexRune(s, '\n'); idx >= 0 {
		s = s[:idx]
	}
	s = strings.TrimSpace(s)
	if len(s) <= 2 && strings.Trim(s, "{}") == "" {
		return "未知"
	}
	if len(s) > 60 {
		s = s[:60] + "…"
	}
	return s
}
