package notification

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"time"

	"jiraport/service/jira"
	"jiraport/service/lark"
)

type Notification struct {
	ID         uint   `gorm:"primaryKey"`
	Policy     string `gorm:"type:varchar(255);uniqueIndex:idx_key_policy"`
	State      NotificationState
	UpdateTime time.Time   `gorm:"type:timestamp"`
	IssueKey   string      `gorm:"type:varchar(255);uniqueIndex:idx_key_policy"`
	Issue      *jira.Issue `gorm:"foreignKey:IssueKey;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}

type NotificationTransitionEvent string

const (
	NotifyEvent      NotificationTransitionEvent = "NotifyEvent"
	CreatedEvent     NotificationTransitionEvent = "CreatedEvent"
	TimeoutEvent     NotificationTransitionEvent = "TimeoutEvent"
	AcknowledgeEvent NotificationTransitionEvent = "AcknowledgeEvent"
)

type NotificationState string

const (
	Inited NotificationState = "Inited"
)

type NotificationAction struct {
	Cmd       []string `yaml:"cmd"`
	OnSuccess string   `yaml:"on_sucess"`
	OnFailure string   `yaml:"on_failure"`
	OnError   string   `yaml:"on_error"`
}

// read NotificationAction of json string format from database
func (a *NotificationAction) Scan(value interface{}) error {
	bytes, ok := value.([]byte)
	if !ok {
		return fmt.Errorf("unsupported value: %v", value)
	}

	result := NotificationAction{}

	err := json.Unmarshal(bytes, &result)
	*a = result
	return err
}

// store NotificationAction as json string in database
func (a NotificationAction) Value() (driver.Value, error) {
	b, err := json.Marshal(a)
	if err != nil {
		return nil, err
	}
	s := string(b)
	return s, err
}

type TransitionEndpoint struct {
	State  NotificationState  `yaml:"state"`
	Action NotificationAction `yaml:"action"`
}

type NotificationPolicy map[NotificationState]map[NotificationTransitionEvent]TransitionEndpoint

type NotificationActionExecInfo struct {
	ID             uint `gorm:"primaryKey"`
	NotificationID uint
	Notification   *Notification      `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
	Action         NotificationAction `gorm:"type:text"`
	Done           uint
	ErrorCount     uint
}

type Message struct {
	ID             uint `gorm:"primaryKey"`
	NotificationID uint
	Notification   *Notification `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
	MessageIndex   *lark.MessageIndex
}
