package quotedb

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"time"
)

type QuoteDB struct {
	DB *sql.DB
}

func New(filename string) (*QuoteDB, error) {
	dbh, err := sql.Open("sqlite3", filename)
	if err != nil {
		return nil, err
	}

	if _, err := dbh.Exec(SCHEMA); err != nil {
		dbh.Close()
		return nil, err
	}

	return &QuoteDB{DB: dbh}, nil
}

func (q *QuoteDB) AddQuote(channel string, data string, author string) (*Quote, error) {
	now := time.Now().UTC()

	result, insertErr := q.DB.Exec(insertQuote, channel, data, author, now)
	if insertErr != nil {
		log.Printf("Error inserting a quote:", insertErr)
		return nil, insertErr
	}

	id, idErr := result.LastInsertId()
	if idErr != nil {
		log.Printf("InsertIdUnknown while adding a quote")
		return nil, errInsertIdUnknown
	}

	return q.findQuoteById(id)
}

func (q *QuoteDB) findQuoteById(id int64) (*Quote, error) {
	quote, err := scanQuotesRow(q.DB.QueryRow(findQuoteById, id))

	if err != nil && err != sql.ErrNoRows {
		log.Println("Encountered", err, "looking up quote with rowid", id)
	}

	return quote, err
}

func (q *QuoteDB) FindQuoteByQuoteId(id int, channel string) (*Quote, error) {
	quote, err := scanQuotesRow(q.DB.QueryRow(findQuoteByQuoteId, id, channel))

	if err != nil && err != sql.ErrNoRows {
		log.Println("Encountered", err, "looking up quote", id, "on channel", channel)
	}

	return quote, err
}

func (q *QuoteDB) FindRandomQuote(channel string) (*Quote, error) {
	quote, err := scanQuotesRow(q.DB.QueryRow(findRandomQuote, channel))

	if err != nil && err != sql.ErrNoRows {
		log.Println("Encountered", err, "looking up random quote on channel", channel)
	}

	return quote, err

}

func (q *QuoteDB) FindLastQuote(channel string) (*Quote, error) {
	quote, err := scanQuotesRow(q.DB.QueryRow(findLastQuote, channel))

	if err != nil && err != sql.ErrNoRows {
		log.Println("Encountered", err, "looking up last quote on channel", channel)
	}

	return quote, err
}

func (q QuoteDB) FindQuotesByString(search string, channel string) ([]*Quote, error) {
	term := fmt.Sprintf("%%%s%%", search)

	rows, err := q.DB.Query(findQuotesByTerm, channel, term)

	if err != nil {
		log.Println("Encountered", err, "searching for quotes on channel", channel, "with term", term)
		return nil, err
	}

	quotes := make([]*Quote, 0)

	defer rows.Close()
	for rows.Next() {
		quote, err := scanQuotesRows(rows)
		if err != nil {
			log.Println("Encountered", err, "searching for quotes on channel", channel, "with term", term)
			return nil, err
		}

		quotes = append(quotes, quote)
	}

	err = rows.Err()
	if err != nil {
		log.Println("Encountered", err, "searching for quotes on channel", channel, "with term", term)
		return nil, err
	}

	return quotes, nil
}
