package db

import (
	"encoding/json"
	"fmt"
	"time"

	"tangled.org/core/notifier"
	"tangled.org/core/tid"
)

type Event struct {
	Rkey      string `json:"rkey"`
	Nsid      string `json:"nsid"`
	EventJson string `json:"event"`
	Created   int64  `json:"created"`
}

func (d *DB) InsertEvent(event Event, notifier *notifier.Notifier) error {

	_, err := d.db.Exec(
		`insert into events (rkey, nsid, event, created) values (?, ?, ?, ?)`,
		event.Rkey,
		event.Nsid,
		event.EventJson,
		time.Now().UnixNano(),
	)

	notifier.NotifyAll()

	return err
}

func (d *DB) EmitDIDAssign(n *notifier.Notifier, ownerDid, repoName, repoDid, oldRepoAt string) error {
	payload := RepoDIDAssign{
		OwnerDid:  ownerDid,
		RepoName:  repoName,
		RepoDid:   repoDid,
		OldRepoAt: oldRepoAt,
	}

	eventJson, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal didAssign event: %w", err)
	}

	return d.InsertEvent(Event{
		Rkey:      tid.TID(),
		Nsid:      RepoDIDAssignNSID,
		EventJson: string(eventJson),
	}, n)
}

func (d *DB) GetEvents(cursor int64) ([]Event, error) {
	whereClause := ""
	args := []any{}
	if cursor > 0 {
		whereClause = "where created > ?"
		args = append(args, cursor)
	}

	query := fmt.Sprintf(`
		select rkey, nsid, event, created
		from events
		%s
		order by created asc
		limit 100
	`, whereClause)

	rows, err := d.db.Query(query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var evts []Event
	for rows.Next() {
		var ev Event
		if err := rows.Scan(&ev.Rkey, &ev.Nsid, &ev.EventJson, &ev.Created); err != nil {
			return nil, err
		}
		evts = append(evts, ev)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return evts, nil
}
