package eventstream

import (
	"context"
	"database/sql"

	"tangled.org/core/tid"
)

func MigrateAddTID(ctx context.Context, tx *sql.Tx) error {
	var hasTid int
	if err := tx.QueryRowContext(ctx,
		`select count(*) from pragma_table_info('events') where name = 'tid'`,
	).Scan(&hasTid); err != nil {
		return err
	}
	if hasTid > 0 {
		_, err := tx.ExecContext(ctx, `create unique index if not exists idx_events_tid on events(tid)`)
		return err
	}

	if _, err := tx.ExecContext(ctx, `
		create table events_new (
			tid text not null,
			rkey text not null,
			nsid text not null,
			event text not null,
			created integer not null,
			primary key (rkey, nsid)
		);
	`); err != nil {
		return err
	}

	rows, err := tx.QueryContext(ctx, `
		select rkey, nsid, event, created
		from events
		order by created asc, rowid asc
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	gen := tid.MonotonicGenerator{}
	insertStmt, err := tx.PrepareContext(ctx,
		`insert or ignore into events_new (tid, rkey, nsid, event, created) values (?, ?, ?, ?, ?)`,
	)
	if err != nil {
		return err
	}
	defer insertStmt.Close()

	for rows.Next() {
		var rkey, nsid, event string
		var created int64
		if err := rows.Scan(&rkey, &nsid, &event, &created); err != nil {
			return err
		}
		t := gen.FromNanos(created)
		if _, err := insertStmt.ExecContext(ctx, t, rkey, nsid, event, created); err != nil {
			return err
		}
	}
	if err := rows.Err(); err != nil {
		return err
	}

	if _, err := tx.ExecContext(ctx, `
		drop table events;
		alter table events_new rename to events;
		create unique index idx_events_tid on events(tid);
	`); err != nil {
		return err
	}
	return nil
}
