package main

import (
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
)

// setupFileLogging tees the standard logger to a file alongside the config.
// Returns the log file path. Stderr is kept as a secondary sink so dev runs
// (linux, console) still print, while windowsgui builds rely on the file.
func setupFileLogging(cfgDir string) (string, error) {
	if err := os.MkdirAll(cfgDir, 0755); err != nil {
		return "", err
	}
	p := filepath.Join(cfgDir, "companion.log")
	f, err := os.OpenFile(p, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return "", err
	}
	log.SetOutput(io.MultiWriter(f, os.Stderr))
	return p, nil
}

// tailLog returns the last n lines of the log file. Reads only the trailing
// chunk of the file so the cost is bounded regardless of log size.
func tailLog(p string, n int) ([]string, error) {
	const tailBytes = 32 * 1024
	f, err := os.Open(p)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	info, err := f.Stat()
	if err != nil {
		return nil, err
	}
	size := info.Size()
	var off int64
	if size > tailBytes {
		off = size - tailBytes
	}
	buf := make([]byte, size-off)
	if _, err := f.ReadAt(buf, off); err != nil && err != io.EOF {
		return nil, err
	}
	s := string(buf)
	// Drop the (likely partial) first line when we didn't start at 0.
	if off > 0 {
		if i := strings.IndexByte(s, '\n'); i >= 0 {
			s = s[i+1:]
		}
	}
	s = strings.TrimRight(s, "\n")
	if s == "" {
		return nil, nil
	}
	lines := strings.Split(s, "\n")
	if len(lines) > n {
		lines = lines[len(lines)-n:]
	}
	return lines, nil
}
