package migrations

import (
	"log"

	"github.com/jmoiron/sqlx"
	"github.com/knadh/koanf/v2"
	"github.com/knadh/stuffbin"
)

func V6_2_0(db *sqlx.DB, fs stuffbin.FileSystem, ko *koanf.Koanf, lo *log.Logger) error {
	// Add `msg_retry_delay` and `from_addresses` to each SMTP server entry in the `smtp`
	// Idempotent: only updates rows where at least one entry is missing the key.
	if _, err := db.Exec(`
		UPDATE settings
		SET value = (
			SELECT JSONB_AGG(
				JSONB_SET(
					JSONB_SET(
						v,
						'{msg_retry_delay}',
						COALESCE(v->'msg_retry_delay', '"10ms"'::JSONB)
					),
					'{from_addresses}',
					COALESCE(v->'from_addresses', '[]'::JSONB)
				)
				ORDER BY ord
			)
			FROM JSONB_ARRAY_ELEMENTS(value) WITH ORDINALITY AS t(v, ord)
		)
		WHERE key = 'smtp'
		AND EXISTS (
			SELECT 1 FROM JSONB_ARRAY_ELEMENTS(value) AS v
			WHERE NOT (v ? 'msg_retry_delay') OR NOT (v ? 'from_addresses')
		);
	`); err != nil {
		return err
	}

	// Update app language settings that used incorrect locale codes.
	if _, err := db.Exec(`
		UPDATE settings SET value = langs.new_value
		FROM (VALUES
			('"cs-cz"'::JSONB, '"cs"'::JSONB),
			('"jp"'::JSONB, '"ja"'::JSONB),
			('"se"'::JSONB, '"sv"'::JSONB)
		) AS langs(old_value, new_value)
		WHERE key = 'app.lang' AND value = langs.old_value;
	`); err != nil {
		return err
	}

	// Add `bounce.azure` for ACS/Event Grid bounce handling; upsert if the row already exists.
	if _, err := db.Exec(`
		INSERT INTO settings (key, value) VALUES('bounce.azure', '{"enabled": false, "shared_secret": "", "shared_secret_header": ""}')
		ON CONFLICT (key) DO UPDATE
		SET value = jsonb_build_object(
			'enabled', COALESCE((settings.value->>'enabled')::boolean, false),
			'shared_secret', COALESCE(settings.value->>'shared_secret', ''),
			'shared_secret_header', COALESCE(settings.value->>'shared_secret_header', '')
		);
	`); err != nil {
		return err
	}

	if _, err := db.Exec(`INSERT INTO settings (key, value) VALUES ('app.show_optin_page', 'true') ON CONFLICT (key) DO NOTHING	`); err != nil {
		return err
	}

	// Rename `security.cors_origins` to `security.trusted_urls`.
	if _, err := db.Exec(`UPDATE settings SET key = 'security.trusted_urls'
		WHERE key = 'security.cors_origins'
		AND NOT EXISTS (SELECT 1 FROM settings WHERE key = 'security.trusted_urls')`); err != nil {
		return err
	}

	// Hash existing API tokens. This is idempotent by skipping values that
	// already look like lowercase SHA-256 hex digests.
	if _, err := db.Exec(`
		UPDATE users
		SET password = ENCODE(DIGEST(password, 'sha256'), 'hex')
		WHERE type = 'api'
			AND password IS NOT NULL
			AND password != ''
			AND password !~ '^[a-f0-9]{64}$';
	`); err != nil {
		return err
	}

	return nil
}
