package renderer

import (
	"image"
	"image/color"
	"log/slog"
	"os/exec"
	"strings"
	"time"

	"git.eeqj.de/sneak/hdmistat/internal/layout"
	"git.eeqj.de/sneak/hdmistat/internal/statcollector"
	"github.com/golang/freetype/truetype"
)

// Screen represents a displayable screen
type Screen interface {
	Name() string
	Render(canvas *layout.Canvas, info *statcollector.SystemInfo) error
}

// Renderer manages screen rendering
type Renderer struct {
	font   *truetype.Font
	logger *slog.Logger
	width  int
	height int
}

// NewRenderer creates a new renderer
func NewRenderer(font *truetype.Font, logger *slog.Logger) *Renderer {
	return &Renderer{
		font:   font,
		logger: logger,
		width:  1920, // Default HD resolution
		height: 1080,
	}
}

// SetResolution sets the rendering resolution
func (r *Renderer) SetResolution(width, height int) {
	r.width = width
	r.height = height
}

// RenderScreen renders a screen to an image
func (r *Renderer) RenderScreen(screen Screen, info *statcollector.SystemInfo) (*image.RGBA, error) {
	canvas := layout.NewCanvas(r.width, r.height, r.font, r.logger)

	// Draw common header
	r.drawHeader(canvas, info)

	if err := screen.Render(canvas, info); err != nil {
		return nil, err
	}

	return canvas.Image(), nil
}

// drawHeader draws the common header with system info
func (r *Renderer) drawHeader(canvas *layout.Canvas, _ *statcollector.SystemInfo) {
	width, _ := canvas.Size()
	headerColor := color.RGBA{150, 150, 150, 255}
	headerStyle := layout.TextStyle{Size: 14, Color: headerColor, Bold: true}

	// Get uname info
	uname := "Unknown System"
	if output, err := exec.Command("uname", "-a").Output(); err == nil {
		uname = strings.TrimSpace(string(output))
		// Truncate if too long
		if len(uname) > 150 {
			uname = uname[:147] + "..."
		}
	}

	// Draw uname on left
	_ = canvas.DrawText(uname, layout.Point{X: 20, Y: 20}, headerStyle)

	// Check NTP sync status
	ntpSynced := r.checkNTPSync()
	var syncIndicator string
	var syncColor color.Color
	if ntpSynced {
		syncIndicator = "*"
		syncColor = color.RGBA{0, 255, 0, 255} // Green
	} else {
		syncIndicator = "?"
		syncColor = color.RGBA{255, 0, 0, 255} // Red
	}

	// Time formats
	now := time.Now()
	utcTime := now.UTC().Format("Mon 2006-01-02 15:04:05 UTC")
	localTime := now.Format("Mon 2006-01-02 15:04:05 MST")

	// Draw times on the right with sync indicators
	// For simplicity, we'll use a fixed position approach

	// Draw UTC time
	_ = canvas.DrawText(utcTime, layout.Point{X: width - 40, Y: 20}, layout.TextStyle{
		Size:      headerStyle.Size,
		Color:     color.RGBA{255, 255, 255, 255}, // White
		Alignment: layout.AlignRight,
		Bold:      true,
	})
	// UTC sync indicators
	_ = canvas.DrawText(syncIndicator, layout.Point{X: width - 280, Y: 20}, layout.TextStyle{
		Size:  headerStyle.Size,
		Color: syncColor,
		Bold:  true,
	})
	_ = canvas.DrawText(syncIndicator, layout.Point{X: width - 20, Y: 20}, layout.TextStyle{
		Size:  headerStyle.Size,
		Color: syncColor,
		Bold:  true,
	})

	// Draw local time
	_ = canvas.DrawText(localTime, layout.Point{X: width - 40, Y: 35}, layout.TextStyle{
		Size:      headerStyle.Size,
		Color:     color.RGBA{255, 255, 255, 255}, // White
		Alignment: layout.AlignRight,
		Bold:      true,
	})
	// Local sync indicators
	_ = canvas.DrawText(syncIndicator, layout.Point{X: width - 280, Y: 35}, layout.TextStyle{
		Size:  headerStyle.Size,
		Color: syncColor,
		Bold:  true,
	})
	_ = canvas.DrawText(syncIndicator, layout.Point{X: width - 20, Y: 35}, layout.TextStyle{
		Size:  headerStyle.Size,
		Color: syncColor,
		Bold:  true,
	})

	// Get uptime command output
	uptimeStr := "uptime unavailable"
	if output, err := exec.Command("uptime").Output(); err == nil {
		uptimeStr = strings.TrimSpace(string(output))
	}

	// Draw uptime on second line
	_ = canvas.DrawText(uptimeStr, layout.Point{X: 20, Y: 40}, headerStyle)

	// Draw horizontal rule with more space
	canvas.DrawHLine(0, 70, width, color.RGBA{100, 100, 100, 255})
}

// checkNTPSync checks if the system clock is synchronized with NTP
func (r *Renderer) checkNTPSync() bool {
	// Try timedatectl first (systemd systems)
	if output, err := exec.Command("timedatectl", "status").Output(); err == nil {
		outputStr := string(output)
		// Look for "System clock synchronized: yes" or "NTP synchronized: yes"
		if strings.Contains(outputStr, "synchronized: yes") {
			return true
		}
		return false
	}

	// Try chronyc (chrony)
	if output, err := exec.Command("chronyc", "tracking").Output(); err == nil {
		outputStr := string(output)
		// Look for "Leap status     : Normal"
		if strings.Contains(outputStr, "Leap status     : Normal") {
			return true
		}
		return false
	}

	// Try ntpstat (ntpd)
	if err := exec.Command("ntpstat").Run(); err == nil {
		// ntpstat returns 0 if synchronized
		return true
	}

	// Default to not synced if we can't determine
	return false
}
