# Gitea Service Management
#
# Start, stop, and manage Gitea service (local mode)
#
# Version: 1.0.0

use api_client.nu get-gitea-config

# Check if Docker is available
def has-docker [] -> bool {
    (^docker --version | complete).exit_code == 0
}

# Check if Gitea Docker container is running
def is-gitea-docker-running [] -> bool {
    let config = get-gitea-config

    if $config.mode != "local" or $config.local.deployment != "docker" {
        return false
    }

    let container_name = $config.local.docker.container_name

    let result = ^docker ps --filter $"name=($container_name)" --format "{{.Names}}" | complete

    ($result.stdout | str trim) == $container_name
}

# Start Gitea via Docker
export def start-gitea-docker [
    --detach: bool = true
] -> bool {
    let config = get-gitea-config

    if $config.mode != "local" {
        error make {
            msg: "Gitea is configured in remote mode"
            help: "Cannot start remote Gitea instance"
        }
    }

    if $config.local.deployment != "docker" {
        error make {
            msg: "Gitea is configured for binary deployment"
            help: "Use start-gitea-binary instead"
        }
    }

    if not (has-docker) {
        error make {
            msg: "Docker is not available"
            help: "Install Docker to use Docker deployment mode"
        }
    }

    # Check if already running
    if (is-gitea-docker-running) {
        print "Gitea is already running"
        return true
    }

    let docker_config = $config.local.docker
    let port = $config.local.port
    let ssh_port = $docker_config.ssh_port
    let data_dir = $config.local.data_dir | path expand

    # Create data directory
    mkdir $data_dir

    # Build environment variables
    let env_vars = $docker_config.environment
        | items {|k, v| ["-e" $"($k)=($v)"]}
        | flatten

    # Build volume mounts
    let volumes = $docker_config.volumes
        | each {|v|
            if ($v | str starts-with "gitea-data:") {
                # Replace named volume with local path
                let vol_path = $v | str replace "gitea-data:" $"($data_dir):"
                ["-v" $vol_path]
            } else {
                ["-v" $v]
            }
        }
        | flatten

    # Start container
    let cmd_parts = [
        "docker" "run"
        "--name" $docker_config.container_name
        "-p" $"($port):3000"
        "-p" $"($ssh_port):22"
    ]
    | append $env_vars
    | append $volumes
    | append ["--restart" $docker_config.restart_policy]

    let cmd_parts_final = if $detach {
        $cmd_parts | append ["-d" $docker_config.image]
    } else {
        $cmd_parts | append $docker_config.image
    }

    print $"Starting Gitea Docker container..."
    ^docker ...$cmd_parts_final

    # Wait for Gitea to be ready
    if $detach {
        print "Waiting for Gitea to start..."
        sleep 5sec

        # Check if running
        if (is-gitea-docker-running) {
            print $"✓ Gitea started successfully"
            print $"   URL: http://localhost:($port)"
            print $"   SSH port: ($ssh_port)"
            true
        } else {
            error make {
                msg: "Gitea failed to start"
                help: "Check Docker logs: docker logs ($docker_config.container_name)"
            }
        }
    } else {
        true
    }
}

# Stop Gitea Docker container
export def stop-gitea-docker [
    --remove: bool = false
] -> bool {
    let config = get-gitea-config

    if not (is-gitea-docker-running) {
        print "Gitea is not running"
        return true
    }

    let container_name = $config.local.docker.container_name

    print $"Stopping Gitea Docker container..."
    ^docker stop $container_name

    if $remove {
        ^docker rm $container_name
        print $"✓ Gitea container stopped and removed"
    } else {
        print $"✓ Gitea container stopped"
    }

    true
}

# Start Gitea binary
export def start-gitea-binary [] -> bool {
    let config = get-gitea-config

    if $config.mode != "local" {
        error make {
            msg: "Gitea is configured in remote mode"
        }
    }

    if $config.local.deployment != "binary" {
        error make {
            msg: "Gitea is configured for Docker deployment"
            help: "Use start-gitea-docker instead"
        }
    }

    let binary_path = $config.local.binary.binary_path | path expand
    let config_path = $config.local.binary.config_path | path expand

    if not ($binary_path | path exists) {
        error make {
            msg: $"Gitea binary not found: ($binary_path)"
            help: "Install Gitea binary or use Docker deployment"
        }
    }

    # Start Gitea
    print $"Starting Gitea from binary: ($binary_path)"
    ^$binary_path --config $config_path web

    true
}

# Start Gitea (auto-detect mode)
export def start-gitea [] -> bool {
    let config = get-gitea-config

    if $config.mode == "remote" {
        error make {
            msg: "Gitea is configured in remote mode"
            help: "Cannot start remote Gitea instance"
        }
    }

    if $config.local.deployment == "docker" {
        start-gitea-docker
    } else {
        start-gitea-binary
    }
}

# Stop Gitea
export def stop-gitea [] -> bool {
    let config = get-gitea-config

    if $config.mode == "remote" {
        error make {
            msg: "Gitea is configured in remote mode"
        }
    }

    if $config.local.deployment == "docker" {
        stop-gitea-docker
    } else {
        # For binary, need to find and kill process
        # This is platform-specific
        print "Stopping Gitea binary..."
        let result = (do {
            ^pkill -f "gitea.*web"
        } | complete)

        if $result.exit_code == 0 {
            print "✓ Gitea stopped"
            true
        } else {
            print "⚠️  Could not stop Gitea (may not be running)"
            false
        }
    }
}

# Get Gitea status
export def get-gitea-status [] -> record {
    let config = get-gitea-config

    if $config.mode == "remote" {
        # For remote, check if accessible
        let health = check-gitea-health $config

        {
            mode: "remote"
            url: $config.remote.url
            accessible: $health
            running: $health
        }
    } else {
        # For local, check if running
        if $config.local.deployment == "docker" {
            let running = is-gitea-docker-running

            {
                mode: "local"
                deployment: "docker"
                container_name: $config.local.docker.container_name
                running: $running
                port: $config.local.port
                url: $"http://localhost:($config.local.port)"
            }
        } else {
            # For binary, check if process is running
            let result = (do {
                ^pgrep -f "gitea.*web"
            } | complete)

            let running = $result.exit_code == 0

            {
                mode: "local"
                deployment: "binary"
                binary_path: $config.local.binary.binary_path
                running: $running
                port: $config.local.port
                url: $"http://localhost:($config.local.port)"
            }
        }
    }
}

# Check Gitea health
export def check-gitea-health [
    gitea_config?: record
] -> bool {
    let config = if ($gitea_config | is-empty) {
        get-gitea-config
    } else {
        $gitea_config
    }

    let url = if $config.mode == "local" {
        $"http://localhost:($config.local.port)"
    } else {
        $config.remote.url
    }

    # Check if Gitea is accessible
    let result = (do {
        http get $"($url)/api/healthz"
    } | complete)

    $result.exit_code == 0
}

# Install Gitea binary
export def install-gitea [
    version?: string = "latest"
    --install-dir: string = "/usr/local/bin"
] -> bool {
    let os = ^uname -s | str downcase
    let arch = ^uname -m

    # Map architecture
    let gitea_arch = if $arch == "x86_64" {
        "amd64"
    } else if $arch == "aarch64" or $arch == "arm64" {
        "arm64"
    } else {
        $arch
    }

    # Get latest version if not specified
    let gitea_version = if $version == "latest" {
        # Fetch latest from GitHub API
        let releases = http get "https://api.github.com/repos/go-gitea/gitea/releases/latest"
        $releases.tag_name | str replace "v" ""
    } else {
        $version
    }

    let download_url = $"https://dl.gitea.com/gitea/($gitea_version)/gitea-($gitea_version)-($os)-($gitea_arch)"

    print $"Downloading Gitea ($gitea_version)..."
    let temp_file = $"/tmp/gitea-($gitea_version)"

    ^curl -L -o $temp_file $download_url

    # Make executable
    ^chmod +x $temp_file

    # Move to install directory
    let install_path = $"($install_dir)/gitea"
    print $"Installing to ($install_path)..."

    ^sudo mv $temp_file $install_path

    print $"✓ Gitea ($gitea_version) installed successfully"
    print $"   Path: ($install_path)"

    true
}

# Restart Gitea
export def restart-gitea [] -> bool {
    stop-gitea
    sleep 2sec
    start-gitea
}

# Get Gitea logs (Docker only)
export def get-gitea-logs [
    --lines: int = 100
    --follow: bool = false
] -> nothing {
    let config = get-gitea-config

    if $config.mode != "local" or $config.local.deployment != "docker" {
        error make {
            msg: "Logs only available for Docker deployment"
        }
    }

    let container_name = $config.local.docker.container_name

    if $follow {
        ^docker logs -f --tail $lines $container_name
    } else {
        ^docker logs --tail $lines $container_name
    }
}
