using System;
using Xunit;
using Egil.RazorComponents.Testing;
using Egil.RazorComponents.Testing.Diffing;
using Egil.RazorComponents.Testing.Asserting;
using Egil.RazorComponents.Testing.Mocking.JSInterop;
using Egil.RazorComponents.Testing.EventDispatchExtensions;
using MLBlazorRCL.Komponentendateien;
using Microsoft.Extensions.DependencyInjection;
using ITVisions.Blazor;
using Microsoft.JSInterop;
using Microsoft.AspNetCore.Components;
using System.Diagnostics;
using System.Linq;
using System.Globalization;
using Microsoft.AspNetCore.Components.Authorization;
using Web;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Hosting;
using BlazorTests;

namespace MiracleListTests
{
 public class MiracleListLoginTest : ComponentTestFixture
 {
  string UriBefore = "http://myserver/Login";
  string UriAfter = "http://myserver/app";

  public MockJsRuntimeInvokeHandler jsMock { get; set; }
  public MiracleListLoginTest()
  {
   Services.AddSingleton<IWebHostEnvironment>(new MockWebHostEnvironment());
   Services.AddSingleton<NavigationManager>(new MockNavigationManager(UriBefore));
   jsMock = Services.AddMockJsRuntime(JsRuntimeMockMode.Loose); // loose is default
   Services.AddSingleton<BlazorUtil>(new BlazorUtil(jsMock.ToJsRuntime(), new MockNavigationManager(UriBefore), null));
   Services.AddSingleton<AuthenticationStateProvider, MockAuthenticationStateProvider>();
   Services.AddBlazoredLocalStorage(); // ggf. ersetzen durch Mock. Bisher nicht notwendig :-)
  }

  [Fact]
  public void LoginOK()
  {
   string name = "testusers " + DateTime.Now;
   string kennwort = Guid.NewGuid().ToString();

   // Diese Komponente laden
   var cut = RenderComponent<Web.Pages.Login>();

   // Prüfung 1: Richtiges Fenster geladen?
   cut.Find("h2").MarkupMatches(@"<h2>Benutzeranmeldung</h2>");

   // Setze Werte
   cut.Find("#name").Change(name);
   cut.Find("#password").Change(kennwort);
   #region SO NICHT: Das geht nicht, die Werte landen nicht in der Component!
   //cut.Find("#name").SetAttribute("value", name);
   //cut.Find("#password").SetAttribute("value", kennwort);
   // oder  (cut.Find("#password") as AngleSharp.Html.Dom.IHtmlInputElement).Value = "xxx";
   #endregion
   cut.Find("#Anmelden").Click();

   //Nur Diagnose: cut.MarkupMatches((cut.Find("#password") as AngleSharp.Html.Dom.IHtmlInputElement).Value);

   // Prüfung 2: Konsolenausgabe
   Assert.Contains(jsMock.Invocations["console.info"], x => x.Arguments[0].ToString() == "LOG: Login.DoLogin: OK!");
   // Prüfung 3: Navigation
   Assert.Equal(UriAfter, cut.Instance.NavigationManager.Uri);
  }

  [Fact]
  public void LoginError()
  {
   string name = "testusers " + DateTime.Now;
   string kennwort = "";

   var cut = RenderComponent<Web.Pages.Login>();

   cut.Find("h2").MarkupMatches(@"<h2>Benutzeranmeldung</h2>");

   // Setze Werte
   cut.Find("#name").Change(name);
   cut.Find("#password").Change(kennwort);
   cut.Find("#Anmelden").Click();

   Assert.Contains(jsMock.Invocations["console.info"], x => x.Arguments[0].ToString() == "LOG: Login.DoLogin: Login Error!");

   Assert.Equal(UriBefore, cut.Instance.NavigationManager.Uri);
  }
 }
}