<commit_before>﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using Newtonsoft.Json;
using RohlikAPI.Helpers;
using RohlikAPI.Model;
using RohlikAPI.Model.JsonDeserialization;

namespace RohlikAPI
{
    internal class OrderHistory
    {
        private const string BaseUrl = "https://www.rohlik.cz/uzivatel/profil";

        private readonly PersistentSessionHttpClient httpClient;
        private readonly PriceParser priceParser = new PriceParser();

        internal OrderHistory(PersistentSessionHttpClient httpClient)
        {
            this.httpClient = httpClient;
        }

        internal IEnumerable<Order> GetOrdersSinceDate(DateTime getOrdersSince)
        {
            var page = 0;

            var ordersToReturn = new List<Order>();
            var alreadySeenOrders = new HashSet<int>();

            var stopGettingOrders = false;

            while (!stopGettingOrders)
            {
                page++;
                var ordersThisPage = GetOrdersForPage(page);
                foreach (var order in ordersThisPage)
                {
                    if (alreadySeenOrders.Contains(order.Id) || order.Date < getOrdersSince)
                    {
                        stopGettingOrders = true;
                        break;
                    }

                    ordersToReturn.Add(order);
                    alreadySeenOrders.Add(order.Id);
                }
            }

            return ordersToReturn;
        }

        private IEnumerable<Order> GetOrdersForPage(int page)
        {
            var order = GetOrderHistoryForPage(page, BaseUrl);
            var parsedOrders = ParseOrderHistory(order);
            return parsedOrders;
        }

        private IEnumerable<Order> ParseOrderHistory(HtmlDocument document)
        {
            var orderNodes = document.DocumentNode.SelectNodes("//ul/li/div");
           
            var returnList = orderNodes.Select(ParseOrderNode);
            return returnList;
        }

        private Order ParseOrderNode(HtmlNode orderNode)
        {
            var orderIdString = orderNode.SelectSingleNode(".//span[@class='orders__id']").InnerText;

            var orderId = int.Parse(orderIdString.Replace("#", ""));

            var dateString = orderNode.SelectSingleNode(".//span[@class='orders__date']").InnerText;

            var orderDate = DateTime.Parse(dateString.Replace(" ", ""), new CultureInfo("cs-CZ"));

            var paymentNode = orderNode.SelectSingleNode(".//span[@class='orders__payment']");

            var paymentNodeText = paymentNode.InnerText.Replace("&ndash;", "-").Replace("&nbsp;", "").Trim();

            var paymentNodeSplit = paymentNodeText.Split('-');

            var priceString = paymentNodeSplit[1];

            var price = double.Parse(priceString.Replace("Kč", ""));

            var paymentMethod = paymentNodeSplit[0];

            var articlesNode = orderNode.SelectSingleNode($"//div[@data-item='o{orderId}']/div[@class='orders__content-wrapper']/div[@class='products-table']");
            var articles = ParseOrderArticles(articlesNode);

            var order = new Order
            {
                Id = orderId,
                Price = price,
                Date = orderDate,
                PaymentMethod = paymentMethod,
                Articles = articles
                
            };
            return order;
        }

        private IEnumerable<Article> ParseOrderArticles(HtmlNode orderNode)
        {
            var articleNodes = orderNode.SelectNodes(".//article");
            return articleNodes.Select(ParseSingleArticle);
        }

        private Article ParseSingleArticle(HtmlNode articleNode)
        {
            var articleNameNode = articleNode.SelectSingleNode(".//h3/a") ?? articleNode.SelectSingleNode(".//h3");
            string articleName = articleNameNode.InnerText.Trim();

            var articleCountString = articleNode.SelectSingleNode(".//p").InnerText;
            
            var cleanArticleCountString = Regex.Match(articleCountString, @"\d*").Value;
            int articleCount;
            int.TryParse(cleanArticleCountString, out articleCount);
            
            var priceNode = articleNode.SelectSingleNode(".//h6/strong");
            double price = priceParser.ParsePrice(priceNode.InnerText);

            return new Article
            {
                Count = articleCount,
                Name = articleName,
                Price = price<commit_msg>Fix order history<commit_after>﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using Newtonsoft.Json;
using RohlikAPI.Helpers;
using RohlikAPI.Model;
using RohlikAPI.Model.JsonDeserialization;

namespace RohlikAPI
{
    internal class OrderHistory
    {
        private const string BaseUrl = "https://www.rohlik.cz/uzivatel/profil";

        private readonly PersistentSessionHttpClient httpClient;
        private readonly PriceParser priceParser = new PriceParser();

        internal OrderHistory(PersistentSessionHttpClient httpClient)
        {
            this.httpClient = httpClient;
        }

        internal IEnumerable<Order> GetOrdersSinceDate(DateTime getOrdersSince)
        {
            var page = 0;

            var ordersToReturn = new List<Order>();
            var alreadySeenOrders = new HashSet<int>();

            var stopGettingOrders = false;

            while (!stopGettingOrders)
            {
                page++;
                var ordersThisPage = GetOrdersForPage(page);
                foreach (var order in ordersThisPage)
                {
                    if (alreadySeenOrders.Contains(order.Id) || order.Date < getOrdersSince)
                    {
                        stopGettingOrders = true;
                        break;
                    }

                    ordersToReturn.Add(order);
                    alreadySeenOrders.Add(order.Id);
                }
            }

            return ordersToReturn;
        }

        private IEnumerable<Order> GetOrdersForPage(int page)
        {
            var order = GetOrderHistoryForPage(page, BaseUrl);
            var parsedOrders = ParseOrderHistory(order);
            return parsedOrders;
        }

        private IEnumerable<Order> ParseOrderHistory(HtmlDocument document)
        {
            var orderNodes = document.DocumentNode.SelectNodes("//ul/li/div");
           
            var returnList = orderNodes.Select(ParseOrderNode);
            return returnList;
        }

        private Order ParseOrderNode(HtmlNode orderNode)
        {
            var orderIdString = orderNode.SelectSingleNode(".//span[@class='orders__id']").InnerText;

            var orderId = int.Parse(orderIdString.Replace("#", ""));

            var dateString = orderNode.SelectSingleNode(".//span[@class='orders__date']").InnerText;

            var orderDate = DateTime.Parse(dateString.Replace(" ", ""), new CultureInfo("cs-CZ"));

            var paymentNode = orderNode.SelectSingleNode(".//span[@class='orders__payment']");

            var paymentNodeText = paymentNode.InnerText.Replace("&ndash;", "-").Replace("&nbsp;", "").Trim();

            var paymentNodeSplit = paymentNodeText.Split('-');

            var priceString = paymentNodeSplit[1];

            var price = double.Parse(priceString.Replace("Kč", ""));

            var paymentMethod = paymentNodeSplit[0];

            var articlesNode = orderNode.SelectSingleNode($"//div[@data-item='o{orderId}']/div[@class='orders__content-wrapper']/div[@class='products-table']");
            var articles = ParseOrderArticles(articlesNode);

            var order = new Order
            {
                Id = orderId,
                Price = price,
                Date = orderDate,
                PaymentMethod = paymentMethod,
                Articles = articles
                
            };
            return order;
        }

        private IEnumerable<Article> ParseOrderArticles(HtmlNode orderNode)
        {
            var articleNodes = orderNode.SelectNodes(".//div[@class='products-table__product']");
            return articleNodes.Select(ParseSingleArticle);
        }

        private Article ParseSingleArticle(HtmlNode articleNode)
        {
            var articleNameNode = articleNode.SelectSingleNode(".//a[@class='products-table__name']");
            string articleName = articleNameNode.InnerText.Trim();
            
            var articleCountNode = articleNode.SelectSingleNode(".//div[@class='products-table__quantity products-table__quantity--number']");
            var articleCountString = articleCountNode.InnerText;
            
            var cleanArticleCountString = Regex.Match(articleCountString, @"\d+").Value;
            int articleCount;
            int.TryParse(cleanArticleCountString, out articleCount);
            
            var priceNode = articleNode.SelectSingleNode(".//div[@class='products-table__price']");
            double price = priceParser.ParsePrice(priceNode.InnerText);

            return new Article
            {
                Count = articleCount,
                Name = articleName,
                Price = price
{'fraction_non_alphanumeric': 0.09872476089266738, 'fraction_numerical': 0.0009564293304994687, 'mean_word_length': 2.030917874396135, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '630041', 'n_tokens_mistral': 2378, 'n_tokens_neox': 2260, 'n_words': 442}