using Microsoft.AspNetCore.Mvc;
using Northwind.Grpc.Client.Mvc.Models;
using System.Diagnostics;
using Grpc.Net.ClientFactory; // GrpcClientFactory
using Grpc.Core; // AsyncUnaryCall<T>

namespace Northwind.Grpc.Client.Mvc.Controllers
{
  public class HomeController : Controller
  {
    private readonly ILogger<HomeController> _logger;
    protected readonly Greeter.GreeterClient greeterClient;
    protected readonly Shipper.ShipperClient shipperClient;

    public HomeController(ILogger<HomeController> logger,
      GrpcClientFactory factory)
    {
      _logger = logger;
      greeterClient = factory.CreateClient<Greeter.GreeterClient>("Greeter");
      shipperClient = factory.CreateClient<Shipper.ShipperClient>("Shipper");
    }

    public async Task<IActionResult> Index(string name = "Halinka", int id = 1)
    {
      try
      {
        HelloReply reply = await greeterClient.SayHelloAsync(
          new HelloRequest { Name = name });

        ViewData["greeting"] = "Pozdrowienia z usługi gRPC: " + reply.Message;

        // ShipperReply shipperReply = await shipperClient.GetShipperAsync(
        //   new ShipperRequest { ShipperId = id });

        // To samo wywołanie co wyżej, ale bez await.
        AsyncUnaryCall<ShipperReply> shipperCall = shipperClient.GetShipperAsync(
          new ShipperRequest { ShipperId = id },
          deadline: DateTime.UtcNow.AddSeconds(3) // Musi to być UTC DateTime.
          );

        Metadata metadata = await shipperCall.ResponseHeadersAsync;

        foreach (Metadata.Entry entry in metadata)
        {
          // Instrukcja bez większego znaczenia, po prostu poprawiająca czytelność.
          _logger.LogCritical($"Klucz: {entry.Key}, wartość: {entry.Value}");
        }

        ShipperReply shipperReply = await shipperCall.ResponseAsync;

        ViewData["shipper"] = "Dane spedytora z usługi gRPC: " + 
          $"ID: {shipperReply.ShipperId}, nazwa: {shipperReply.CompanyName},"
          + $" tel.: {shipperReply.Phone}.";
      }
      catch (RpcException rpcex) when (rpcex.StatusCode == 
        global::Grpc.Core.StatusCode.DeadlineExceeded)
      {
        _logger.LogWarning("Usługa Northwind.Grpc.Service przekroczyła limit czasu.");
        ViewData["exception"] = rpcex.Message;
      }
      catch (Exception ex)
      {
        _logger.LogWarning($"Usługa Northwind.Grpc.Service nie odpowiada.");
        ViewData["exception"] = ex.Message;
      }

      return View();
    }

    public IActionResult Privacy()
    {
      return View();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
      return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
  }
}