// Copyright [2026] [Argus]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build unit || integration

package config

import (
	"fmt"
	"os"
	"strings"

	"github.com/release-argus/Argus/internal/test"
)

func writeFile(path string, data string) {
	data = strings.TrimPrefix(data, "\n")
	_ = os.WriteFile(path, []byte(data), 0644)
}

func testYAML_Argus(path string) {
	data := test.TrimYAML(`
		settings:
			data:
				database_file: test-argus.db
			web:
				listen_port: 0
		service:
			SERVICE_NAME:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
	`)

	writeFile(path, data)
}

func testYAML_config_test(path string) {
	data := test.TrimYAML(`
		settings:
			data:
				database_file: test-config_test.db
			web:
				listen_port: 0
		defaults:
			service:
				options:
					interval: 123
					semantic_versioning: false
				latest_version:
					github:
						access_token: ghp_default
				notify:
					default: {}
				command:
					- - bash
						- /opt/default.sh
				webhook:
					default: {}
			notify:
				gotify:
					url_fields:
						host: foo.bar
						token: anonymous
				slack:
					params:
						host: defaultHost
						title: defaultTitle
						username: defaultUsername
			webhook:
				desired_status_code: 0
				delay: 2
				max_tries: 3
				silent_fails: false
		notify:
			default:
				type: gotify
				options:
					message: mainMessage
				params:
					username: mainUsername
		webhook:
			default:
				type: github
				url: https://awx.main.example.com/api/v2/job_templates/XX/github/
				secret: YYYYmain
				desired_status_code: 202
				delay: 3s
				max_tries: 1
		service:
			NoDefaults:
				name: something else
				options:
					interval: 10m
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
					url_commands:
						- type: regex
							regex: v(.*)
					require:
						regex_content: Argus-{{ version }}-linux-amd64
						regex_version: ^[0-9.]+[0-9]$
				notify:
					personal:
						type: mattermost
						options:
							message: overriddenMessage
						url_fields:
							channel: foo
							host: example.com
							token: '123'
						params:
							username: overriddenUsername
				command:
					- - bash
						- /opt/upgrade.sh
				webhook:
					personal:
						type: github
						url: https://awx.example.com/api/v2/job_templates/XX/github/
						secret: YYYY
						desired_status_code: 202
						delay: 3s
						max_tries: 1
			WantDefaults:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
					url_commands:
						- type: regex
							regex: v(.*)
					require:
						regex_content: Argus-{{ version }}-linux-amd64
						regex_version: ^[0-9.]+[0-9]$
			Gitea:
				latest_version:
					type: github
					url: go-gitea/gitea
					url_commands:
						- type: regex
							regex: v(.*)
					require:
						regex_content: gitea-{{ version }}-linux-amd64
						regex_version: ^[0-9.]+[0-9]$
				notify:
					personal:
						type: mattermost
						options:
							delay: 0s
						url_fields:
							host: mattermost.example.com
							port: '443'
							token: ZZZZ
						params:
							icon: https://raw.githubusercontent.com/go-gitea/gitea/main/public/img/logo.png
				webhook:
					personal:
						type: github
						url: https://awx.example.com/api/v2/job_templates/XX/github/
						secret: YYYY
						delay: 0s
			Disabled:
				options:
					active: false
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			EmptyServiceIsDeleted:
	`)

	writeFile(path, data)
}

func testYAML_config_large(path string) {
	var b strings.Builder

	b.WriteString(test.TrimYAML(`
		settings:
			log:
				level: INFO
		service:
	`))

	for i := range 256 {
		fmt.Fprintf(
			&b,
			"  service_%d:\n"+
				"    name: Service %d with padding to enlarge saved output\n"+
				"    latest_version:\n"+
				"      type: github\n"+
				"      url: %s\n",
			i, i, test.ArgusGitHubRepo,
		)
	}
	writeFile(path, b.String())
}

func testYAML_SomeNilServices(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		service:
			a:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			b:
			c:
			d:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
	`)

	writeFile(path, data)
}

func testYAML_NilServiceMap(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder`,
	)

	writeFile(path, data)
}

func testYAML_InvalidYAML(path string) {
	data := test.TrimJSON(`{
		"defaults": {
			"service": {
				"latest_version": {
					"access_token": ""placeholder"
				}
			}
		}`,
	)

	writeFile(path, data)
}

// testYAML_config_small is for `save.go`.
//
// if index < 0 {
//
// boundary check.
func testYAML_config_small(path string) {
	data := test.TrimYAML(`
		settings:
			data: {}
			web: {}
		service:
			some-service:
				options: {}
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
				dashboard: {}
	`)

	writeFile(path, data)
}

// testYAML_config_indent4 is for `save.go`.
//
// A config indented with 4 spaces rather than the marshal-default 2
func testYAML_config_indent4(path string) {
	data := test.TrimYAML(`
		notify:
				gotify:
						type: gotify
						url_fields:
								host: example.com
								token: super-secret
		service:
				awesome:
						options:
								semantic_versioning: false
						latest_version:
								type: url
								url: https://example.com/releases
								url_commands:
										- type: regex
											regex: '[0-9.]+'
						notify:
								gotify: {}
						command:
								- - /bin/echo
									- hello
						dashboard:
								icon: https://example.com/icon.webp
								tags:
										- NEWS
		`)

	writeFile(path, data)
}

func testYAML_Ordering_0(path string) {
	data := test.TrimYAML(`
		settings:
			web:
				listen_port: 0
			data:
				database_file: 'test-ordering_0.db'
		defaults:
			service:
				latest_version:
					access_token: placeholder
				options:
					interval: 123
					semantic_versioning: false

		notify:
			default:
				type: gotify
				options:
					message: mainMessage

		service:
			NoDefaults:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
					access_token: ghp_other
			WantDefaults:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			Disabled:
				options:
					active: false
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			Gitea:
				latest_version:
					type: github
					url: go-gitea/gitea

		webhook:
			default:
				type: github
				url: https://awx.main.example.com/api/v2/job_templates/XX/github/
	`)

	writeFile(path, data)
}

func testYAML_Ordering_1_no_services(path string) {
	data := test.TrimYAML(`
		settings:
			data:
				database_file: test-ordering_1.db
			web:
				listen_port: '0'
		defaults:
			service:
				options:
					interval: 123s
					semantic_versioning: false
				latest_version:
					access_token: placeholder
				deployed_version: {}
			notify:
				gotify:
					url_fields:
						host: foo.bar
						token: anonymous
				slack:
					params:
						host: defaultHost
						title: defaultTitle
						username: defaultUsername
			webhook:
				desired_status_code: 0
				delay: 2s
				max_tries: 3
				silent_fails: false
	`)

	writeFile(path, data)
}

func testYAML_Ordering_2_obscure_service_names(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		service:
			"123":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"foo bar":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"foo: bar":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"foo: \"bar\"":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"\"foo: bar\"":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"'foo: bar'":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"\"foo bar\"":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"'foo bar'":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"foo \"bar\"":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
			"foo: bar, baz":
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
	`)

	writeFile(path, data)
}

func testYAML_Ordering_3_empty_line_after_service_line(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		service:

			C:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
					access_token: ghp_other
			B:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `

			A:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
	`)

	writeFile(path, data)
}

func testYAML_Ordering_4_multiple_empty_lines_after_service_line(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		service:
` + strings.Repeat("\n", 3) + `
			P:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
` + strings.Repeat("\n", 5) + `
			L:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
` + strings.Repeat("\n", 2) + `
			S:
				latest_version:
					type: github
					url: ` + test.ArgusGitHubRepo + `
	`)

	writeFile(path, data)
}

func testYAML_Ordering_5_eof_is_service_line(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		settings:
		data:
		database_file: test-ordering_5.db

		service:`,
	)

	writeFile(path, data)
}

func testYAML_Ordering_6_no_services_after_service_line_another_block(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		service:

		settings:
			data:
				database_file: test-ordering_5.db
	`)

	writeFile(path, data)
}

func testYAML_Ordering_7_no_services_after_service_line(path string) {
	data := test.TrimYAML(`
		defaults:
			service:
				latest_version:
					access_token: placeholder
		settings:
			data:
				database_file: test-ordering_5.db
		service:
	`)

	writeFile(path, data)
}

func testYAML_Edit(path string) {
	data := test.TrimYAML(`
		settings:
			data:
				database_file: test-config_edit.db
		defaults:
			service:
				latest_version:
					access_token: placeholder
		service:
			alpha:
				name: a
				latest_version:
					type: url
					url: ` + test.LookupPlain["url_valid"] + `
					url_commands:
					- type: regex
						regex: v(.*)
			bravo:
				name: b
				latest_version:
					type: url
					url: ` + test.LookupPlain["url_valid"] + `
					url_commands:
					- type: regex
						regex: ([0-9.]+)
			charlie:
				name: c
				latest_version:
					type: url
					url: ` + test.LookupPlain["url_valid"] + `
					url_commands:
					- type: regex
						regex: v?([0-9.]+)
	`)

	writeFile(path, data)
}
