package backend

import (
	"fmt"
	"log"
)

func (db *DB) WriteArticleAuthors(articleID int64, authorIDs []int64) error {
	query := "INSERT INTO articles_authors (article_id, author_id) VALUES (?, ?)"

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

			for _, authorID := range authorIDs {
				if _, err := tx.Exec(query, articleID, authorID); err != nil {
					if rollbackErr := tx.Rollback(); rollbackErr != nil {
						log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
					}
					return fmt.Errorf("error inserting into articles_authors: %v", err)
				}
			}

			if err = tx.Commit(); err != nil {
				return fmt.Errorf("error committing transaction: %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)
}

func (db *DB) GetArticleAuthors(c *Config, articleID int64) ([]*User, error) {
	query := `
    SELECT u.id
    FROM articles a
        INNER JOIN articles_authors aa ON a.id = aa.article_id
        INNER JOIN users u ON aa.author_id = u.id
    WHERE a.id = ?
    `
	rows, err := db.Query(query, articleID)
	if err != nil {
		return nil, fmt.Errorf("error querying articles_authors: %v", err)
	}

	authors := make([]*User, 0)
	for rows.Next() {
		var authorID int64

		if err = rows.Scan(&authorID); err != nil {
			return nil, fmt.Errorf("error scanning rows: %v", err)
		}

		author, err := db.GetUser(c, authorID)
		if err != nil {
			return nil, fmt.Errorf("error getting user info for article author: %v", err)
		}

		authors = append(authors, author)
	}

	return authors, nil
}

func (db *DB) UpdateArticleAuthors(articleID int64, authorIDs []int64) error {
	deleteQuery := "DELETE FROM articles_authors WHERE article_id = ?"
	insertQuery := "INSERT INTO articles_authors (article_id, author_id) VALUES (?, ?)"

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

			if _, err := tx.Exec(deleteQuery, articleID); err != nil {
				if rollbackErr := tx.Rollback(); rollbackErr != nil {
					log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
				}
				return fmt.Errorf("error deleting entries from articles_authors before inserting new ones: %v", err)
			}

			for _, authorID := range authorIDs {
				if _, err := tx.Exec(insertQuery, articleID, authorID); err != nil {
					if rollbackErr := tx.Rollback(); rollbackErr != nil {
						log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr)
					}
					return fmt.Errorf("error inserting new entries into articles_authors: %v", err)
				}
			}

			if err = tx.Commit(); err != nil {
				return fmt.Errorf("error committing transaction: %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)
}