package db

import (
	"git.giftfish.de/ston1th/gowiki/pkg/core"
	"git.giftfish.de/ston1th/gowiki/pkg/log"
	"git.giftfish.de/ston1th/gowiki/pkg/store"
)

const (
	versionKey     = "version/version"
	currentVersion = 1
)

type migrator func(*DB, int) error

var migrators = []migrator{
	func(_ *DB, _ int) error {
		return nil
	},
	func(db *DB, version int) (err error) {
		// recreate all pages with new format
		var pages []string
		db.store.ForEachPrefix(pagePrefix, func(k string, _ []byte) error {
			pages = append(pages, k)
			return nil
		})
		var p core.Page
		for _, v := range pages {
			k := pagePrefix + v
			err := db.store.Get(k, &p)
			if err != nil {
				log.Printf("db: migrator[%d]: pageGet %s: %s", version, k, err)
				continue
			}
			if p.Perm == 3 {
				p.Perm = core.Private
			}
			err = db.store.Set(k, &p)
			if err != nil {
				log.Printf("db: migrator[%d]: pageSet %s: %s", version, k, err)
				continue
			}
		}
		users, err := db.GetUsers()
		if err != nil {
			return
		}
		for _, u := range users {
			err = db.CreateSection(u.Username, []string{u.Username}, true)
			if err != nil {
				log.Printf("db: migrator[%d]: userSection %s: %s", version, u.Username, err)
			}
		}
		return
	},
}

func (db *DB) RunMigrations() (err error) {
	var version int
	err = db.store.Get(versionKey, &version)
	if err == store.ErrKeyNotFound {
		err = db.store.Set(versionKey, currentVersion)
		if err != nil {
			return
		}
		err = db.store.Get(versionKey, &version)
		if err != nil {
			return
		}
	}
	log.Printf("db: database version %d", version)
	for version < currentVersion {
		v := version + 1
		log.Printf("db: running migration verison %d", v)
		err = migrators[v](db, v)
		if err != nil {
			return
		}
		err = db.store.Set(versionKey, v)
		if err != nil {
			return
		}
		version = v
		log.Printf("db: database version %d", version)
	}
	return
}
