package model

import (
	"context"
	"database/sql"
	"fmt"
	"log"
)

func (db *DB) AddIssue() (int64, error) {
	query := "INSERT INTO issues (published) VALUES (?)"
	result, err := db.Exec(query, false)
	if err != nil {
		return 0, fmt.Errorf("error inserting issue into DB: %v", err)
	}

	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("error getting ID of added issue: %v", err)
	}

	return id, nil
}

func (db *DB) PublishLatestIssue() error {
	txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable}
	updateQuery := "UPDATE issues SET published = true WHERE published = false"
	insertQuery := "INSERT INTO issues (published) VALUES (?)"

	for i := 0; i < TxMaxRetries; i++ {
		err := func() error {
			tx, err := db.BeginTx(context.Background(), txOptions)
			if err != nil {
				return fmt.Errorf("error starting transaction: %v", err)
			}

			if _, err := tx.Exec(updateQuery); err != nil {
				if rollbackErr := tx.Rollback(); rollbackErr != nil {
					log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
				}
				return fmt.Errorf("error publishing issue: %v", err)
			}

			if _, err := tx.Exec(insertQuery, false); err != nil {
				if rollbackErr := tx.Rollback(); rollbackErr != nil {
					log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
				}
				return fmt.Errorf("error inserting new issue into DB: %v", err)
			}

			if err = tx.Commit(); err != nil {
				return fmt.Errorf("error committing transaction when publishing issue: %v", err)
			}
			return nil
		}()
		if err == nil {
			return nil
		}

		log.Println(err)
		wait(i)
	}

	return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries)
}