/*Task 3: */

    //Note: Please note that the connection strings must be corrected for each task. Thank you ! 

    static void Main(string[] args)
    {
        var dbCon = new BookstoreDbEntities();

        using (dbCon)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("../../simple-books.xml");
            string xPathQuery = "/catalog/book";

            XmlNodeList books = xmlDoc.SelectNodes(xPathQuery);

            //Reading the XML with XPath
            foreach (XmlNode book in books)
            {
                var bookEntry = new Book();
                bookEntry.title = book.GetChildText("title");
                if (bookEntry.title == null)
                {
                    throw new ArgumentException("Provided book does not have an title!");
                }

                var authors = book.SelectNodes("author");

                if (authors.Count == 0)
                {
                    throw new ArgumentException("Provided book does not have an author(s)!");
                }

                //Making sure that all the authors are processed.
                foreach (XmlNode author in authors)
                {
                    var name = author.InnerText;
                    bookEntry.Authors.Add(CreateOrLoadAuthor(dbCon, name));
                }

                var price = book.GetChildText("price");
                if (price != null)
                {
                    bookEntry.Price = decimal.Parse(price);
                }
                else
                {
                    bookEntry.Price = null;
                }

                var webSite = book.GetChildText("web-site");
                if (webSite != null)
                {
                    bookEntry.Website = book.GetChildText("web-site");
                }

                var isbn = book.GetChildText("isbn");

                if (isbn != null)
                {
                    bookEntry.ISBN = book.GetChildText("isbn");
                }

                dbCon.Books.Add(bookEntry);
            }

            dbCon.SaveChanges();
        }
    }
    private static Author CreateOrLoadAuthor(
            BookstoreDbEntities context, string name)
    {
        Author existingAuthor =
            (from a in context.Authors
             where a.Name.ToLower() == name.ToLower()
             select a).FirstOrDefault();

        if (existingAuthor != null)
        {
            return existingAuthor;
        }

        var newAuthor = new Author();
        newAuthor.Name = name;
        context.Authors.Add(newAuthor);
        context.SaveChanges();

        return newAuthor;
    }
    /*Task 4*/

    static void Main(string[] args)
    {
        //As Nakov told us book ISBN should not be unique, thus, same books can be added. It's not a bug, its a feature :) 
        var dbCon = new BookstoreDbEntities();

        using (dbCon)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("../../complex-books.xml");
            string xPathQuery = "/catalog/book";

            XmlNodeList books = xmlDoc.SelectNodes(xPathQuery);

            //Reading the XML with XPath
            foreach (XmlNode book in books)
            {
                //Processing each query in different transaction, so we can be sure that if one fails, the correct ones will be processed. 
                //There should be an easier way, but for now this works as well :) 
                var tran = new TransactionScope();

                using (tran)
                {
                    try
                    {
                        var bookEntry = new Book();
                        bookEntry.title = book.GetChildText("title");
                        if (bookEntry.title == null)
                        {
                            throw new ArgumentException("Provided book does not have an title!");
                        }

                        var authors = book.SelectNodes("authors/author");
                        if (authors.Count == 0)
                        {
                            throw new ArgumentException("Cannot create book with missing author!");
                        }

                        foreach (XmlNode author in authors)
                        {
                            var name = author.InnerText;
                            bookEntry.Authors.Add(CreateOrLoadAuthor(dbCon, name));
                        }

                        foreach (XmlNode review in book.SelectNodes("reviews/review"))
                        {
                            string authorName = null;
                            var currentReview = new Review();
                            DateTime date = DateTime.Now;

                            if (review.Attributes["author"] != null)
                            {
                                authorName = review.Attributes["author"].Value;
                                var author = CreateOrLoadAuthor(dbCon, authorName);
                                currentReview.AuthorId = author.Id;
                            }
                            if (review.Attributes["date"] != null)
                            {
                                date = DateTime.Parse(review.Attributes["date"].Value);
                            }

                            var text = review.InnerText;
                            currentReview.DateOfCreation = date;
                            currentReview.Text = text;
                            dbCon.Reviews.Add(currentReview);

                            dbCon.SaveChanges();
                            bookEntry.Reviews.Add(currentReview);
                        }

                        var price = book.GetChildText("price");
                        if (price != null)
                        {
                            bookEntry.Price = decimal.Parse(price);
                        }
                        else
                        {
                            bookEntry.Price = null;
                        }

                        var webSite = book.GetChildText("web-site");
                        if (webSite != null)
                        {
                            bookEntry.Website = book.GetChildText("web-site");
                        }

                        var isbn = book.GetChildText("isbn");

                        if (isbn != null)
                        {
                            bookEntry.ISBN = book.GetChildText("isbn");
                        }

                        dbCon.Books.Add(bookEntry);
                        dbCon.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Transaction failed to complete with the following error: \n" + ex.Message.ToString());

                        Environment.Exit(2);
                    }
                    tran.Complete();
                }
            }
        }
    }