package main

import (
	// External
	werr "git.ahall.se/go/wrappederror"
	"github.com/jackc/pgx/v5/pgconn"

	// Internal
	"smon/notification"

	// Standard
	"context"
	"encoding/json"
	"errors"
)

type DbNotificationService struct {
	ID            int
	Service       string
	Configuration string
	Prio          int
}

func initNotificationManager() (nm notification.Manager, err error) { // {{{
	var dbServices []DbNotificationService
	row := db.QueryRow(
		context.Background(),
		`
		WITH services AS (
			SELECT
				id,
				prio,
				service,
				configuration::varchar
			FROM notification n
			ORDER BY
				prio ASC
		)
		SELECT COALESCE(jsonb_agg(s.*), '[]')
		FROM services s
		`,
	)

	var dbData []byte
	err = row.Scan(&dbData)
	if err != nil {
		err = werr.Wrap(err).WithCode("002-0006")
		return
	}

	err = json.Unmarshal(dbData, &dbServices)
	if err != nil {
		err = werr.Wrap(err).WithCode("002-0007")
		return
	}

	nm = notification.NewManager(logger)
	var service notification.Service
	for _, dbService := range dbServices {
		service, err = notification.ServiceFactory(
			dbService.Service,
			[]byte(dbService.Configuration),
			dbService.Prio,
			"blah",
			//config.Application.NotificationBaseURL,
			logger,
		)
		if err != nil {
			err = werr.Wrap(err).WithData(dbService.Service)
		}
		nm.AddService(service)
	}

	return
} // }}}
func UpdateNotificationService(svc notification.Service) (created bool, err error) { // {{{
	if svc.Exists() {
		_, err = db.Exec(
			context.Background(),
			`
			UPDATE public.notification
			SET
				prio=$2,
				configuration=$3
			WHERE
				prio=$1
			`,
			svc.GetPrio(),
			svc.Updated().GetPrio(),
			svc.Updated().JSON(),
		)
	} else {
		_, err = db.Exec(
			context.Background(),
			`
			INSERT INTO public.notification(prio, configuration, service)
			VALUES($1, $2, $3)
			`,
			svc.Updated().GetPrio(),
			svc.Updated().JSON(),
			svc.GetType(),
		)
		created = true
	}

	if err != nil {
		// Check if this is just a duplicated prio, which isn't allowed.
		var pgErr *pgconn.PgError
		if errors.As(err, &pgErr); pgErr.Code == "23505" {
			return false, werr.New("Prio %d is already used by another service", svc.Updated().GetPrio())
		}

		return false, werr.Wrap(err).WithData(
			struct {
				Prio          int
				Configuration []byte
			}{
				svc.GetPrio(),
				svc.JSON(),
			},
		)
	}
	return
} // }}}
func DeleteNotificationService(prio int) (err error) { // {{{
	_, err = db.Exec(
		context.Background(),
		`
		DELETE FROM public.notification
		WHERE
			prio = $1
		`,
		prio,
	)

	if err != nil {
		return werr.Wrap(err).WithData(struct{ Prio int }{prio})
	}
	return
} // }}}

func AcknowledgeNotification(uuid string) (err error) { // {{{
	/*
		_, err = db.Exec(context.Background(), `UPDATE schedule SET acknowledged=true WHERE schedule_uuid=$1`, uuid)
		if err != nil {
			err = werr.Wrap(err).WithData(uuid)
		}
	*/
	return
} // }}}
