package service

import (
	"encoding/xml"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

// DarwinServiceManager macOS服务管理器
type DarwinServiceManager struct {
	*BaseServiceManager
	launchAgentPath string
}

// PlistEntry LaunchAgent plist条目
type PlistEntry struct {
	XMLName xml.Name `xml:"plist"`
	Dict    struct {
		Key     []string `xml:"key"`
		Entries []struct {
			String  string `xml:"string"`
			True    bool   `xml:"true"`
			False   bool   `xml:"false"`
			Integer int    `xml:"integer"`
		} `xml:",any"`
	} `xml:"dict"`
}

// NewDarwinServiceManager 创建macOS服务管理器
func NewDarwinServiceManager(detector *PlatformDetector) *DarwinServiceManager {
	homeDir, _ := os.UserHomeDir()
	base := &BaseServiceManager{
		detector: detector,
		config:   createDefaultServiceConfig(detector),
	}

	// 设置LaunchAgent路径
	launchAgentPath := filepath.Join(homeDir, "Library", "LaunchAgents", base.config.ServiceName+".plist")

	return &DarwinServiceManager{
		BaseServiceManager: base,
		launchAgentPath:    launchAgentPath,
	}
}

// InstallService 安装LaunchAgent服务
func (d *DarwinServiceManager) InstallService() error {
	info := d.GetPlatformInfo()

	// 验证可执行文件路径
	if err := checkExecutablePath(d.config.ExecPath); err != nil {
		return fmt.Errorf("可执行文件路径验证失败: %v", err)
	}

	// 确保LaunchAgent目录存在
	launchAgentDir := filepath.Dir(d.launchAgentPath)
	if err := os.MkdirAll(launchAgentDir, 0755); err != nil {
		return fmt.Errorf("创建LaunchAgent目录失败: %v", err)
	}

	// 确保日志目录存在
	if err := ensureLogDirectory(d.config.LogFile); err != nil {
		return fmt.Errorf("创建日志目录失败: %v", err)
	}

	// 生成plist文件
	plistContent := d.generatePlistContent()
	if err := os.WriteFile(d.launchAgentPath, []byte(plistContent), 0644); err != nil {
		return fmt.Errorf("写入LaunchAgent文件失败: %v", err)
	}

	// 加载LaunchAgent
	if _, err := runCommand("launchctl", "load", d.launchAgentPath); err != nil {
		// 清理已创建的文件
		os.Remove(d.launchAgentPath)
		return fmt.Errorf("加载LaunchAgent失败: %v", err)
	}

	fmt.Printf("✅ macOS LaunchAgent服务安装成功\n")
	fmt.Printf("   服务文件: %s\n", d.launchAgentPath)
	fmt.Printf("   服务名称: %s\n", d.config.ServiceName)
	fmt.Printf("   日志文件: %s\n", d.config.LogFile)

	if info.UserLevel {
		fmt.Printf("   提示: 用户登录时自动启动，无需管理员权限\n")
	}

	return nil
}

// UninstallService 卸载LaunchAgent服务
func (d *DarwinServiceManager) UninstallService() error {
	if !d.IsServiceInstalled() {
		return fmt.Errorf("服务未安装")
	}

	// 停止服务
	d.StopService()

	// 卸载LaunchAgent
	if _, err := runCommand("launchctl", "unload", d.launchAgentPath); err != nil {
		fmt.Printf("⚠️ 卸载LaunchAgent时出现警告: %v\n", err)
	}

	// 删除plist文件
	if err := os.Remove(d.launchAgentPath); err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("删除LaunchAgent文件失败: %v", err)
	}

	fmt.Printf("✅ macOS LaunchAgent服务卸载成功\n")
	fmt.Printf("   已删除服务文件: %s\n", d.launchAgentPath)

	return nil
}

// StartService 启动服务
func (d *DarwinServiceManager) StartService() error {
	if !d.IsServiceInstalled() {
		return fmt.Errorf("服务未安装，请先安装服务")
	}

	if d.IsServiceRunning() {
		fmt.Printf("⚠️ 服务已在运行中\n")
		return nil
	}

	if _, err := runCommand("launchctl", "start", d.config.ServiceName); err != nil {
		return fmt.Errorf("启动服务失败: %v", err)
	}

	fmt.Printf("✅ 服务启动成功\n")
	return nil
}

// StopService 停止服务
func (d *DarwinServiceManager) StopService() error {
	if !d.IsServiceInstalled() {
		return fmt.Errorf("服务未安装")
	}

	if !d.IsServiceRunning() {
		fmt.Printf("⚠️ 服务未在运行\n")
		return nil
	}

	if _, err := runCommand("launchctl", "stop", d.config.ServiceName); err != nil {
		return fmt.Errorf("停止服务失败: %v", err)
	}

	fmt.Printf("✅ 服务停止成功\n")
	return nil
}

// RestartService 重启服务
func (d *DarwinServiceManager) RestartService() error {
	if err := d.StopService(); err != nil {
		return err
	}
	time.Sleep(1 * time.Second) // 等待1秒
	return d.StartService()
}

// IsServiceInstalled 检查服务是否已安装
func (d *DarwinServiceManager) IsServiceInstalled() bool {
	_, err := os.Stat(d.launchAgentPath)
	return err == nil
}

// IsServiceRunning 检查服务是否正在运行
func (d *DarwinServiceManager) IsServiceRunning() bool {
	// 使用launchctl list检查服务状态
	output, err := runCommand("launchctl", "list")
	if err != nil {
		return false
	}

	lines := strings.Split(strings.TrimSpace(output), "\n")
	for _, line := range lines {
		if strings.Contains(line, d.config.ServiceName) {
			// launchctl list 输出格式: PID | ExitStatus | Label
			fields := strings.Fields(line)
			if len(fields) >= 3 {
				// 如果PID不是"-"，说明服务正在运行
				return fields[0] != "-"
			}
		}
	}

	return false
}

// GetServiceStatus 获取服务状态
func (d *DarwinServiceManager) GetServiceStatus() *ServiceStatus {
	status := &ServiceStatus{
		Platform:     "macOS",
		ServiceName:  d.config.ServiceName,
		IsInstalled:  d.IsServiceInstalled(),
		IsRunning:    d.IsServiceRunning(),
		Autostart:    d.IsAutostartEnabled(),
		LastModified: time.Now(),
	}

	if status.IsInstalled {
		if info, err := os.Stat(d.launchAgentPath); err == nil {
			status.LastModified = info.ModTime()
		}
	}

	// 获取PID
	if status.IsRunning {
		if pid := d.getServicePID(); pid > 0 {
			status.Pid = pid
			status.Uptime = d.getServiceUptime(pid)
		}
	}

	return status
}

// getServicePID 获取服务进程ID
func (d *DarwinServiceManager) getServicePID() int {
	output, err := runCommand("launchctl", "list")
	if err != nil {
		return 0
	}

	lines := strings.Split(strings.TrimSpace(output), "\n")
	for _, line := range lines {
		if strings.Contains(line, d.config.ServiceName) {
			fields := strings.Fields(line)
			if len(fields) >= 3 && fields[0] != "-" {
				var pid int
				fmt.Sscanf(fields[0], "%d", &pid)
				return pid
			}
		}
	}

	return 0
}

// getServiceUptime 获取服务运行时长
func (d *DarwinServiceManager) getServiceUptime(pid int) string {
	// 使用ps命令获取进程启动时间
	output, err := runCommand("ps", "-p", fmt.Sprintf("%d", pid), "-o", "lstart=")
	if err != nil {
		return ""
	}

	startTime := strings.TrimSpace(output)
	if startTime == "" {
		return ""
	}

	// 简单计算运行时长
	startTimeParsed, err := time.Parse("Mon Jan 2 15:04:05 2006", startTime)
	if err != nil {
		return startTime
	}

	uptime := time.Since(startTimeParsed)
	days := int(uptime.Hours()) / 24
	hours := int(uptime.Hours()) % 24
	minutes := int(uptime.Minutes()) % 60

	if days > 0 {
		return fmt.Sprintf("%d天%d小时%d分钟", days, hours, minutes)
	} else if hours > 0 {
		return fmt.Sprintf("%d小时%d分钟", hours, minutes)
	} else {
		return fmt.Sprintf("%d分钟", minutes)
	}
}

// EnableAutostart 启用开机自启
func (d *DarwinServiceManager) EnableAutostart() error {
	if !d.IsServiceInstalled() {
		return fmt.Errorf("服务未安装")
	}

	// macOS LaunchAgent默认就是开机自启的
	// 需要修改plist文件中的RunAtLoad键
	return d.updatePlistRunAtLoad(true)
}

// DisableAutostart 禁用开机自启
func (d *DarwinServiceManager) DisableAutostart() error {
	if !d.IsServiceInstalled() {
		return fmt.Errorf("服务未安装")
	}

	return d.updatePlistRunAtLoad(false)
}

// IsAutostartEnabled 检查开机自启是否启用
func (d *DarwinServiceManager) IsAutostartEnabled() bool {
	if !d.IsServiceInstalled() {
		return false
	}

	// 读取plist文件检查RunAtLoad键
	content, err := os.ReadFile(d.launchAgentPath)
	if err != nil {
		return false
	}

	return strings.Contains(string(content), "<key>RunAtLoad</key>") &&
		strings.Contains(string(content), "<true/>")
}

// updatePlistRunAtLoad 更新plist文件中的RunAtLoad设置
func (d *DarwinServiceManager) updatePlistRunAtLoad(enable bool) error {
	// 先卸载服务
	d.StopService()
	runCommand("launchctl", "unload", d.launchAgentPath)

	// 重新生成plist内容
	plistContent := d.generatePlistContentWithRunAtLoad(enable)

	// 写入新内容
	if err := os.WriteFile(d.launchAgentPath, []byte(plistContent), 0644); err != nil {
		return fmt.Errorf("更新plist文件失败: %v", err)
	}

	// 重新加载服务
	if _, err := runCommand("launchctl", "load", d.launchAgentPath); err != nil {
		return fmt.Errorf("重新加载LaunchAgent失败: %v", err)
	}

	if enable {
		fmt.Printf("✅ 已启用开机自启\n")
	} else {
		fmt.Printf("✅ 已禁用开机自启\n")
	}

	return nil
}

// GetServiceLogs 获取服务日志
func (d *DarwinServiceManager) GetServiceLogs(lines int) ([]string, error) {
	if _, err := os.Stat(d.config.LogFile); os.IsNotExist(err) {
		return []string{"日志文件不存在: " + d.config.LogFile}, nil
	}

	// 使用tail命令读取日志
	output, err := runCommand("tail", "-n", fmt.Sprintf("%d", lines), d.config.LogFile)
	if err != nil {
		return nil, fmt.Errorf("读取日志失败: %v", err)
	}

	if output == "" {
		return []string{"日志文件为空"}, nil
	}

	return strings.Split(strings.TrimSpace(output), "\n"), nil
}

// FollowLogs 实时跟踪日志
func (d *DarwinServiceManager) FollowLogs() error {
	fmt.Printf("📋 实时跟踪服务日志 (按Ctrl+C退出):\n")
	fmt.Printf("   日志文件: %s\n", d.config.LogFile)
	fmt.Printf("------------------------------------------------------------\n")

	// 使用tail -f实时跟踪日志
	cmd := exec.Command("tail", "-f", d.config.LogFile)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	return cmd.Run()
}

// generatePlistContent 生成plist文件内容
func (d *DarwinServiceManager) generatePlistContent() string {
	return d.generatePlistContentWithRunAtLoad(true)
}

// generatePlistContentWithRunAtLoad 生成带RunAtLoad设置的plist文件内容
func (d *DarwinServiceManager) generatePlistContentWithRunAtLoad(runAtLoad bool) string {
	runAtLoadStr := "<false/>"
	if runAtLoad {
		runAtLoadStr = "<true/>"
	}

	// 构建参数数组
	var argsBuilder strings.Builder
	argsBuilder.WriteString(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>%s</string>
    <key>ProgramArguments</key>
    <array>
        <string>%s</string>`,
		d.config.ServiceName,
		d.config.ExecPath))

	// 添加参数
	for _, arg := range d.config.Args {
		argsBuilder.WriteString(fmt.Sprintf(`
        <string>%s</string>`, arg))
	}

	return fmt.Sprintf(`%s
    </array>
    <key>WorkingDirectory</key>
    <string>%s</string>
    <key>StandardOutPath</key>
    <string>%s</string>
    <key>StandardErrorPath</key>
    <string>%s</string>
    <key>RunAtLoad</key>
    %s
    <key>KeepAlive</key>
    <true/>
    <key>StartInterval</key>
    <integer>3600</integer>
    <key>ThrottleInterval</key>
    <integer>60</integer>
</dict>
</plist>`,
		argsBuilder.String(),
		d.config.WorkingDir,
		d.config.LogFile,
		d.config.ErrorFile,
		runAtLoadStr)
}
