using Microsoft.Azure.WebJobs; // [FunctionName], [TimerTrigger]
using Microsoft.Extensions.Logging; // ILogger
using System.IO; // Stream, StreamReader
using System.IO.Compression; // GZipStream, CompressionMode
using System.Net.Http; // IHttpClientFactory, HttpClient
using System.Threading.Tasks; // Task<T>

namespace Northwind.AzureFunctions.Service;

public class ScrapeAmazonFunction
{
  private const string relativePath = 
    "10-NET-Cross-Platform-Development-websites/dp/1801077363/";

  private readonly IHttpClientFactory clientFactory;

  public ScrapeAmazonFunction(IHttpClientFactory clientFactory)
  {
    this.clientFactory = clientFactory;
  }

  [FunctionName(nameof(ScrapeAmazonFunction))]
  public async Task Run( // Wywoływanie co godzinę.
    [TimerTrigger("0 0 * * * *")] TimerInfo timer,
    ILogger log)
  {
    log.LogInformation("Funkcja C# czasomierza wywołana o godz. {0}.",
      System.DateTime.UtcNow);

    log.LogInformation(
      "Trzy następne wywołania funkcji C# czasomierza o godz. " +
      $"{timer.FormatNextOccurrences(3, System.DateTime.UtcNow)}.");

    HttpClient client = clientFactory.CreateClient("Amazon");
    HttpResponseMessage response = await client.GetAsync(relativePath);
    log.LogInformation($"Zapytanie: GET {client.BaseAddress}{relativePath}");

    if (response.IsSuccessStatusCode)
    {
      log.LogInformation($"Zapytanie HTTP obsłużone pomyślnie.");

      // Odczytanie zawartości strumienia GZIP i zapisanie w zmiennej tekstowej.
      Stream stream = await response.Content.ReadAsStreamAsync();
      GZipStream gzipStream = new(stream, CompressionMode.Decompress);
      StreamReader reader = new(gzipStream);
      string page = reader.ReadToEnd();

      // Wyodrębnienie pozycji w rankingu.
      int posBsr = page.IndexOf("Best Sellers Rank");
      string bsrSection = page.Substring(posBsr, 45);

      // Sekcja bsrSection zawiera mniej więcej taką treść:
      //   "Best Sellers Rank: </span> #22,258 in Books ("

      // Uzyskanie pozycji znaku # i następującej po nim spacji.
      int posHash = bsrSection.IndexOf("#") + 1;
      int posSpaceAfterHash = bsrSection.IndexOf(" ", posHash);

      // Wyodrębnienie numeru pozycji w formacie tekstowym.
      string bsr = bsrSection.Substring(
        posHash, posSpaceAfterHash - posHash);
      bsr = bsr.Replace(",", null); // Usunięcie przecinków.

      // Konwersja tekstu na liczbę.
      if (int.TryParse(bsr, out int bestSellersRank))
      {
        log.LogInformation($"Pozycja w rankingu: {bestSellersRank:N0}.");
      }
      else
      {
        log.LogError($"Błąd podczas wyodrębniania pozycji w rankingu z sekcji {bsrSection}.");
      }
    }
    else
    {
      log.LogError($"Błędne zapytanie HTTP.");
    }
  }
}
