// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package systemd // import "miniflux.app/v2/internal/systemd"

import (
	"errors"
	"fmt"
	"net"
	"os"
	"strconv"
	"time"
)

const (
	// SdNotifyReady tells the service manager that service startup is
	// finished, or the service finished loading its configuration.
	// https://www.freedesktop.org/software/systemd/man/sd_notify.html#READY=1
	SdNotifyReady = "READY=1"

	// SdNotifyWatchdog the service manager to update the watchdog timestamp.
	// https://www.freedesktop.org/software/systemd/man/sd_notify.html#WATCHDOG=1
	SdNotifyWatchdog = "WATCHDOG=1"
)

// HasNotifySocket checks if the process is supervised by Systemd and has the notify socket.
func HasNotifySocket() bool {
	return os.Getenv("NOTIFY_SOCKET") != ""
}

// HasSystemdWatchdog checks if the watchdog is configured in Systemd unit file.
func HasSystemdWatchdog() bool {
	return os.Getenv("WATCHDOG_USEC") != ""
}

// WatchdogInterval returns the watchdog interval configured in systemd unit file.
func WatchdogInterval() (time.Duration, error) {
	s, err := strconv.Atoi(os.Getenv("WATCHDOG_USEC"))
	if err != nil {
		return 0, fmt.Errorf(`systemd: error converting WATCHDOG_USEC: %v`, err)
	}

	if s <= 0 {
		return 0, errors.New(`systemd: error WATCHDOG_USEC must be a positive number`)
	}

	return time.Duration(s) * time.Microsecond, nil
}

// SdNotify sends a message to systemd using the sd_notify protocol.
// See https://www.freedesktop.org/software/systemd/man/sd_notify.html.
func SdNotify(state string) error {
	addr := &net.UnixAddr{
		Net:  "unixgram",
		Name: os.Getenv("NOTIFY_SOCKET"),
	}

	if addr.Name == "" {
		// We're not running under systemd (NOTIFY_SOCKET is not set).
		return nil
	}

	conn, err := net.DialUnix(addr.Net, nil, addr)
	if err != nil {
		return err
	}
	defer conn.Close()

	if _, err = conn.Write([]byte(state)); err != nil {
		return err
	}

	return nil
}
