package reaper

import (
	"encoding/xml"
	"io"
	"mi6e4ka/yabl-api/schemas"

	"golang.org/x/net/html/charset"
	"gorm.io/gorm"
)

func Parse(filereader io.Reader) *FB2Read {
	// legacy, but normal algo
	bookXML := new(FB2Read)
	decoder := xml.NewDecoder(filereader)
	decoder.CharsetReader = charset.NewReaderLabel

	for t, _ := decoder.Token(); t != nil; t, _ = decoder.Token() {
		if se, ok := t.(xml.StartElement); ok {
			if se.Name.Local == "description" {
				decoder.DecodeElement(&bookXML, &se)
				break
			}
		}
	}
	if bookXML.Title == "" {
		return nil
	}

	return bookXML
}

func RawToFB2(
	reaped FB2Read,
	filename string,
	bookcase *string,
	size uint64,
	hash *string,
) FB2 {
	return FB2{
		SrcFile:      filename,
		Bookcase:     bookcase,
		Title:        reaped.Title,
		Genres:       reaped.Genres,
		Authors:      reaped.Authors,
		HasCover:     reaped.Cover.Id != nil,
		Lang:         reaped.Lang,
		SrcLang:      reaped.SrcLang,
		Translators:  reaped.Translators,
		Sequence:     reaped.Sequence,
		Year:         reaped.Year,
		ISBN:         reaped.ISBN,
		Publisher:    reaped.Publisher,
		Annotation:   &reaped.Annotation.Html,
		SymbolsCount: 0,
		Size:         size,
		Hash:         hash,
	}
}

// omg legacy here ->
func nilCheck(nilString *string) string {
	if nilString == nil {
		return ""
	}
	return *nilString
}

func FB2toDB(tx *gorm.DB, book FB2) uint64 {
	var genres *[]schemas.Genre
	//book.Genres = nil
	if book.Genres != nil {
		var genresNN []schemas.Genre
		for _, genre := range book.Genres {
			genresNN = append(genresNN, schemas.Genre{
				RawTag: genre,
			})
		}
		genres = &genresNN
	}
	var authors []schemas.Author
	for _, author := range book.Authors {
		var dbAuthor schemas.Author
		tx.FirstOrCreate(&dbAuthor, schemas.Author{
			Key:        author.FirstName + nilCheck(author.MiddleName) + nilCheck(author.LastName),
			FirstName:  author.FirstName,
			MiddleName: author.MiddleName,
			LastName:   author.LastName,
		})
		authors = append(authors, dbAuthor)
	}
	var translators []schemas.Translator
	if book.Translators != nil {
		for _, translator := range *book.Translators {
			var dbTranslator schemas.Translator
			tx.FirstOrCreate(&dbTranslator, schemas.Translator{
				Key:        translator.FirstName + nilCheck(translator.MiddleName) + nilCheck(translator.LastName),
				FirstName:  translator.FirstName,
				MiddleName: translator.MiddleName,
				LastName:   translator.LastName,
			})
			translators = append(translators, dbTranslator)
		}
	}
	var sequence *schemas.Sequence
	if book.Sequence.Name != nil {
		sequence = &schemas.Sequence{
			Name: *book.Sequence.Name,
		}
	}
	var publisher *schemas.Publisher
	if book.Publisher != nil {
		publisher = &schemas.Publisher{
			Name: *book.Publisher,
		}
	}
	// var filetype schemas.Filetype
	// tx.FirstOrCreate(&filetype, schemas.Filetype{
	// 	Filetype: "fb2",
	// 	Name:     "FB2",
	// })
	//fmt.Println(book.Lang)
	dbBook := schemas.Book{
		Title:   book.Title,
		Authors: authors,
		Language: schemas.Language{
			Code: book.Lang,
		},
		Genre:        genres,
		Description:  book.Annotation,
		HasCover:     book.HasCover,
		SequenceID:   sequence,
		SequenceBook: book.Sequence.Number,
		IsTranslated: book.Translators != nil,
		Translators:  &translators,
		SrcLanguage: schemas.Language{
			Code: book.Lang,
		},
		Year:         book.Year,
		Isbn:         book.ISBN,
		PublisherID:  publisher,
		SymbolsCount: &book.SymbolsCount,
		Size:         int(book.Size),
		Hash:         book.Hash,
		Bookcase:     book.Bookcase,
		Filename:     book.SrcFile,
		Filetype:     "fb2",
	}
	tx.Create(&dbBook)
	return dbBook.ID
}
