/*
 * Copyright (c) 2025-2026, Антон Аксенов
 * This file is part of iptvc project
 * MIT License: https://git.axenov.dev/IPTV/iptvc/src/branch/master/LICENSE
 */

package cmd

import (
	"axenov/iptv-checker/app"
	"axenov/iptv-checker/app/config"

	"github.com/spf13/cobra"
)

// addCommonCheckFlags добавляет общие флаги, используемые как командой check,
// так и serve. Значения по умолчанию совпадают с config.yml.example;
// переопределение config.yml происходит через cmd.Flags().Changed()
// в applyCacheOverrides() и applyCheckOverrides().
func addCommonCheckFlags(cmd *cobra.Command, repeatDefault uint) {
	// paths
	cmd.Flags().StringVarP(&app.Args.IniPath, "ini", "i", "./playlists.ini", "path to a local ini-file (overrides config.yml)")
	cmd.Flags().StringVarP(&app.Args.TagsPath, "tags", "t", "./channels.json", "path to a local tagfile (overrides config.yml)")

	// iteration
	cmd.Flags().UintVarP(&app.Args.RandomCount, "random", "r", 0, "take this count of random playlists to check from ini-file")
	cmd.Flags().UintVarP(&app.Args.RepeatCount, "repeat", "", repeatDefault, "repeat same check X times (0 = infinite)")

	// check.playlists
	cmd.Flags().IntVar(&app.Args.PlTimeout, "playlists-timeout", 10, "playlist request timeout in seconds (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.PlAllCooldown, "playlists-all-cooldown", 1800, "cooldown after all playlists in seconds (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.PlOneCooldown, "playlists-one-cooldown", 2, "cooldown after each playlist in seconds (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.PlMaxRoutines, "playlists-max-routines", 1, "max concurrent playlist checks (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.PlPerRoutine, "playlists-per-routine", 1, "playlists per routine (overrides config.yml)")
	cmd.Flags().StringSliceVar(&app.Args.PlUserAgent, "playlists-user-agent", []string{"Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer"}, "user-agent for playlist requests (overrides config.yml)")

	// check.channels
	cmd.Flags().IntVar(&app.Args.ChTimeout, "channels-timeout", 10, "channel request timeout in seconds (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.ChByteRange, "channels-byte-range", 512, "bytes to fetch from server per channel (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.ChCooldown, "channels-cooldown", 0, "cooldown after each channel in seconds (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.ChMaxRoutines, "channels-max-routines", 50, "max concurrent channel checks (overrides config.yml)")
	cmd.Flags().IntVar(&app.Args.ChPerRoutine, "channels-per-routine", 10, "channels per routine (overrides config.yml)")
	cmd.Flags().StringSliceVar(&app.Args.ChUserAgent, "channels-user-agent", []string{"Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer"}, "user-agent for channel requests (overrides config.yml)")

	// cache
	cmd.Flags().BoolVar(&app.Args.CacheEnabled, "cache-enabled", true, "enable cache (overrides config.yml)")
	cmd.Flags().StringVar(&app.Args.CacheHost, "cache-host", "cache", "cache host (overrides config.yml)")
	cmd.Flags().UintVar(&app.Args.CachePort, "cache-port", 6379, "cache port (overrides config.yml)")
	cmd.Flags().StringVar(&app.Args.CacheUsername, "cache-username", "", "cache username (overrides config.yml)")
	cmd.Flags().StringVar(&app.Args.CachePassword, "cache-password", "", "cache password (overrides config.yml)")
	cmd.Flags().UintVar(&app.Args.CacheDb, "cache-db", 0, "cache database number (overrides config.yml)")
	cmd.Flags().UintVar(&app.Args.CacheTtl, "cache-ttl", 3600, "cache TTL in seconds (overrides config.yml)")
}

// addCheckOnlyFlags добавляет флаги, доступные только в команде check.
func addCheckOnlyFlags(cmd *cobra.Command) {
	cmd.Flags().BoolVarP(&app.Args.NeedJson, "json", "j", false, "print results in JSON format in the end")
	cmd.Flags().BoolVarP(&app.Args.NeedQuiet, "quiet", "q", false, "suppress logs (does not affect on -j)")
	cmd.Flags().StringSliceVarP(&app.Args.Files, "file", "f", []string{}, "path to a local playlist file (m3u/m3u8)")
	cmd.Flags().StringSliceVarP(&app.Args.Urls, "url", "u", []string{}, "URL to a remote playlist (http/https)")
	cmd.Flags().StringSliceVarP(&app.Args.Codes, "code", "c", []string{}, "code of playlist from ini-file")
}

// applyAppOverrides применяет CLI-флаги для app.* поверх конфигурации.
// Использует Changed() — переопределение срабатывает только при явной передаче флага.
func applyAppOverrides(cmd *cobra.Command) {
	if cmd.Flags().Changed("debug") {
		app.Config.App.Debug = app.Args.Debug
	}
	if cmd.Flags().Changed("log-level") {
		app.Config.App.LogLevel = app.Args.LogLevel
	}
	if cmd.Flags().Changed("ini") {
		app.Config.App.Playlists = app.Args.IniPath
	}
	if cmd.Flags().Changed("tags") {
		app.Config.App.Tags = app.Args.TagsPath
	}
}

// applyCacheOverrides применяет CLI-флаги для cache.* поверх конфигурации.
// Использует Changed() — переопределение срабатывает только при явной передаче флага.
// Вызывается между app.Init() и app.InitCache().
func applyCacheOverrides(cmd *cobra.Command) {
	c := &app.Config.Cache
	if cmd.Flags().Changed("cache-enabled") {
		c.Enabled = app.Args.CacheEnabled
	}
	if cmd.Flags().Changed("cache-host") {
		c.Host = app.Args.CacheHost
	}
	if cmd.Flags().Changed("cache-port") {
		c.Port = app.Args.CachePort
	}
	if cmd.Flags().Changed("cache-username") {
		c.Username = app.Args.CacheUsername
	}
	if cmd.Flags().Changed("cache-password") {
		c.Password = app.Args.CachePassword
	}
	if cmd.Flags().Changed("cache-db") {
		c.Db = app.Args.CacheDb
	}
	if cmd.Flags().Changed("cache-ttl") {
		c.Ttl = app.Args.CacheTtl
	}
}

// applyCheckOverrides применяет CLI-флаги для check.* поверх конфигурации.
// Значения времени передаются в секундах и переводятся в миллисекунды.
// Вызывается в обработчиках check и serve после app.Init().
func applyCheckOverrides(cmd *cobra.Command) {
	pp := &app.Config.Check.Playlists
	if cmd.Flags().Changed("playlists-timeout") {
		pp.Timeout = config.DurationSeconds(app.Args.PlTimeout * 1000)
	}
	if cmd.Flags().Changed("playlists-all-cooldown") {
		pp.AllCooldown.Min = app.Args.PlAllCooldown * 1000
		pp.AllCooldown.Max = app.Args.PlAllCooldown * 1000
	}
	if cmd.Flags().Changed("playlists-one-cooldown") {
		pp.OneCooldown.Min = app.Args.PlOneCooldown * 1000
		pp.OneCooldown.Max = app.Args.PlOneCooldown * 1000
	}
	if cmd.Flags().Changed("playlists-max-routines") {
		pp.MaxRoutines = app.Args.PlMaxRoutines
	}
	if cmd.Flags().Changed("playlists-per-routine") {
		pp.PerRoutine = app.Args.PlPerRoutine
	}
	if cmd.Flags().Changed("playlists-user-agent") {
		pp.UserAgent = app.Args.PlUserAgent
	}

	cc := &app.Config.Check.Channels
	if cmd.Flags().Changed("channels-timeout") {
		cc.Timeout = config.DurationSeconds(app.Args.ChTimeout * 1000)
	}
	if cmd.Flags().Changed("channels-byte-range") {
		cc.ByteRange = app.Args.ChByteRange
	}
	if cmd.Flags().Changed("channels-cooldown") {
		cc.Cooldown.Min = app.Args.ChCooldown * 1000
		cc.Cooldown.Max = app.Args.ChCooldown * 1000
	}
	if cmd.Flags().Changed("channels-max-routines") {
		cc.MaxRoutines = app.Args.ChMaxRoutines
	}
	if cmd.Flags().Changed("channels-per-routine") {
		cc.PerRoutine = app.Args.ChPerRoutine
	}
	if cmd.Flags().Changed("channels-user-agent") {
		cc.UserAgent = app.Args.ChUserAgent
	}
}
