context: using ChummerHub.API;
  using ChummerHub.Data;
  using ChummerHub.Models.V1;
  using Microsoft.ApplicationInsights;
  using Microsoft.ApplicationInsights.DataContracts;
  using Microsoft.AspNetCore.Authorization;
  using Microsoft.AspNetCore.Cors;
  using Microsoft.AspNetCore.Http;
  using Microsoft.AspNetCore.Identity;
  using Microsoft.AspNetCore.Mvc;
  using Microsoft.Data.SqlClient;
  using Microsoft.EntityFrameworkCore;
  using Microsoft.Extensions.Logging;
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Linq;
  using System.Net;
  using System.Security.Authentication;
  using System.Threading.Tasks;
  using System.Transactions;
  
  namespace ChummerHub.Controllers
  {
      [Route("api/v{api-version:apiVersion}/[controller]/[action]")]
      [ApiController]
      [EnableCors("AllowOrigin")]
      [ApiVersion("1.0")]
      [Authorize]
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController'
      public class AccountController : Controller
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController'
      {
  
          private readonly UserManager<ApplicationUser> _userManager;
          private readonly SignInManager<ApplicationUser> _signInManager;
          private readonly ApplicationDbContext _context;
          private readonly RoleManager<ApplicationRole> _roleManager;
          private readonly ILogger _logger;
          private readonly TelemetryClient tc;
  
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.AccountController(ApplicationDbContext, ILogger<AccountController>, UserManager<ApplicationUser>, SignInManager<ApplicationUser>, RoleManager<ApplicationRole>, TelemetryClient)'
          public AccountController(ApplicationDbContext context,
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.AccountController(ApplicationDbContext, ILogger<AccountController>, UserManager<ApplicationUser>, SignInManager<ApplicationUser>, RoleManager<ApplicationRole>, TelemetryClient)'
              ILogger<AccountController> logger,
              UserManager<ApplicationUser> userManager,
              SignInManager<ApplicationUser> signInManager,
              RoleManager<ApplicationRole> roleManager,
              TelemetryClient telemetry)
          {
              _context = context;
              _logger = logger;
              _userManager = userManager;
              _signInManager = signInManager;
              _roleManager = roleManager;
              tc = telemetry;
          }
  
          [HttpGet]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Unauthorized)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Forbidden)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.BadRequest)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("AccountGetPossibleRoles")]
          [Authorize]
  
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetPossibleRoles()'
          public async Task<ActionResult<ResultAccountGetPossibleRoles>> GetPossibleRoles()
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetPossibleRoles()'
          {
              ResultAccountGetPossibleRoles res;
              try
              {
                  var list = await _context.Roles.Select(a => a.Name).ToListAsync();
                  res = new ResultAccountGetPossibleRoles(list);
                  return Ok(res);
              }
              catch (Exception e)
              {
                  res = new ResultAccountGetPossibleRoles(e);
                  return BadRequest(res);
              }
          }
  
          [HttpGet]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Unauthorized)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Forbidden)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.BadRequest)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("AccountGetRoles")]
          [Authorize]
  
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetRoles()'
          public async Task<ActionResult<ResultAccountGetRoles>> GetRoles()
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetRoles()'
          {
              ResultAccountGetRoles res;
              try
              {
                  //var user = _userManager.FindByEmailAsync(email).Result;
                  var user = await _signInManager.UserManager.GetUserAsync(User);
                  if (user.EmailConfirmed)
                  {
                      await SeedData.EnsureRole(Program.MyHost.Services, user.Id, Authorizarion.Constants.UserRoleConfirmed, _roleManager, _userManager);
                  }
                  var roles = await _userManager.GetRolesAsync(user);
                  var list = await _context.Roles.Select(a => a.Name).ToListAsync();
                  res = new ResultAccountGetRoles(roles, list);
  
                  return Ok(res);
              }
              catch (Exception e)
              {
                  res = new ResultAccountGetRoles(e);
                  return BadRequest(res);
              }
          }
  
          [HttpGet]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Unauthorized)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.BadRequest)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("AccountGetUserByEmail")]
          [Authorize]
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetUserByEmail(string)'
          public async Task<ActionResult<ResultAccountGetUserByEmail>> GetUserByEmail(string email)
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetUserByEmail(string)'
          {
              ResultAccountGetUserByEmail res;
              try
              {
                  var user = await _userManager.FindByEmailAsync(email);
                  res = new ResultAccountGetUserByEmail(user);
                  if (user == null)
                      return NotFound(res);
                  user.PasswordHash = string.Empty;
                  user.SecurityStamp = string.Empty;
                  return Ok(res);
              }
              catch (Exception e)
              {
                  res = new ResultAccountGetUserByEmail(e);
                  return BadRequest(res);
              }
          }
  
          [HttpGet]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Conflict)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.BadRequest)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("GetAddSqlDbUser")]
          [Authorize(Roles = "Administrator")]
  
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetAddSqlDbUser(string, string, string, string)'
          public async Task<ActionResult<string>> GetAddSqlDbUser(string username, string password, string start_ip_address, string end_ip_address)
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetAddSqlDbUser(string, string, string, string)'
          {
              string result = string.Empty;
              try
              {
                  if (string.IsNullOrEmpty(username))
                      throw new ArgumentNullException(nameof(username));
                  if (string.IsNullOrEmpty(password))
                      throw new ArgumentNullException(nameof(password));
  
                  IPAddress startaddress = null;
                  if (!string.IsNullOrEmpty(start_ip_address))
                  {
                      startaddress = IPAddress.Parse(start_ip_address);
                  }
                  IPAddress endaddress = null;
                  if (!string.IsNullOrEmpty(end_ip_address))
                  {
                      endaddress = IPAddress.Parse(end_ip_address);
                  }
                  if (string.IsNullOrEmpty(Startup.ConnectionStringToMasterSqlDb))
                  {
                      throw new ArgumentNullException(nameof(Startup.ConnectionStringToMasterSqlDb));
                  }
  
  
                  try
                  {
                      string cmd = "CREATE LOGIN " + username + " WITH password = '" + password + "';";
                      using (SqlConnection masterConnection = new SqlConnection(Startup.ConnectionStringToMasterSqlDb))
                      {
                          await masterConnection.OpenAsync();
                          using (SqlCommand dbcmd = new SqlCommand(cmd, masterConnection))
                          {
                              dbcmd.ExecuteNonQuery();
                          }
                      }
                  }
                  catch (SqlException e)
                  {
                      result += e.Message + Environment.NewLine + Environment.NewLine;
                  }
                  //create the user in the master DB
                  try
                  {
                      string cmd = "CREATE USER " + username + " FROM LOGIN " + username + ";";
                      using (SqlConnection masterConnection = new SqlConnection(Startup.ConnectionStringToMasterSqlDb))
                      {
                          await masterConnection.OpenAsync();
                          using (SqlCommand dbcmd = new SqlCommand(cmd, masterConnection))
                          {
                              dbcmd.ExecuteNonQuery();
                          }
                      }
                  }
                  catch (SqlException e)
                  {
                      result += e.Message + Environment.NewLine + Environment.NewLine;
                  }
                  //create the user in the sinner_db as well!
                  try
                  {
                      string cmd = "CREATE USER " + username + " FROM LOGIN " + username + ";";
                      using (SqlConnection masterConnection = new SqlConnection(Startup.ConnectionStringSinnersDb))
                      {
                          await masterConnection.OpenAsync();
                          using (SqlCommand dbcmd = new SqlCommand(cmd, masterConnection))
                          {
                              dbcmd.ExecuteNonQuery();
                          }
                      }
                  }
                  catch (Exception e)
                  {
                      result += e.Message + Environment.NewLine + Environment.NewLine;
                  }
                  try
                  {
                      string cmd = "ALTER ROLE dbmanager ADD MEMBER " + username + ";";
                      using (SqlConnection masterConnection = new SqlConnection(Startup.ConnectionStringSinnersDb))
                      {
                          await masterConnection.OpenAsync();
                          using (SqlCommand dbcmd = new SqlCommand(cmd, masterConnection))
                          {
                              dbcmd.ExecuteNonQuery();
                          }
                      }
                  }
                  catch (Exception e)
                  {
                      bool worked = false;
                      try
                      {
                          string cmd = "EXEC sp_addrolemember 'db_owner', '" + username + "';";
                          using (SqlConnection masterConnection = new SqlConnection(Startup.ConnectionStringSinnersDb))
                          {
                              await masterConnection.OpenAsync();
                              using (SqlCommand dbcmd = new SqlCommand(cmd, masterConnection))
                              {
                                  dbcmd.ExecuteNonQuery();
                              }
                          }
                          worked = true;
                      }
                      catch (Exception e1)
                      {
                          result += e1 + Environment.NewLine + Environment.NewLine;
                      }
                      if (worked)
                      {
                          result += "User added!" + Environment.NewLine + Environment.NewLine;
                      }
                      else
                      {
                          result += e.Message + Environment.NewLine + Environment.NewLine;
                      }
                  }
                  try
                  {
                      string cmd = "EXEC sp_set_database_firewall_rule N'Allow " +
                                   username + "', '" + startaddress + "', '" + endaddress + "';";
                      using (SqlConnection masterConnection = new SqlConnection(Startup.ConnectionStringSinnersDb))
                      {
                          await masterConnection.OpenAsync();
                          using (SqlCommand dbcmd = new SqlCommand(cmd, masterConnection))
                          {
                              dbcmd.ExecuteNonQuery();
                          }
  
                          result += "Firewallrule added: " + startaddress + " - " + endaddress + Environment.NewLine +
                                    Environment.NewLine;
                      }
                  }
                  catch (Exception e)
                  {
                      result += e.Message + Environment.NewLine + Environment.NewLine;
                  }
                  return Ok(result);
              }
              catch (Exception e)
              {
                  try
                  {
                      var user = await _signInManager.UserManager.GetUserAsync(User);
                      //var tc = new Microsoft.ApplicationInsights.TelemetryClient();
                      ExceptionTelemetry et = new ExceptionTelemetry(e);
                      et.Properties.Add("user", User.Identity.Name);
                      tc.TrackException(et);
                  }
                  catch (Exception ex)
                  {
                      _logger?.LogError(ex.ToString());
                  }
                  result += Environment.NewLine + e;
                  if (e is HubException)
                      return BadRequest(e);
                  HubException hue = new HubException(result, e);
                  return BadRequest(hue);
              }
          }
  
          [HttpPost]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Unauthorized)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.BadRequest)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("PostSetUserRole")]
          [Authorize(Roles = "Administrator")]
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.PostSetUserRole(string, string)'
          public async Task<ActionResult<ApplicationUser>> PostSetUserRole(string email, string userrole)
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.PostSetUserRole(string, string)'
          {
              try
              {
                  var user = await _userManager.FindByEmailAsync(email);
                  if (user == null)
                      return NotFound();
                  await SeedData.EnsureRole(Program.MyHost.Services, user.Id, userrole, _roleManager, _userManager);
                  user.PasswordHash = string.Empty;
                  user.SecurityStamp = string.Empty;
                  return Ok(user);
              }
              catch (Exception e)
              {
                  try
                  {
                      var user = await _signInManager.UserManager.GetUserAsync(User);
                      //var tc = new Microsoft.ApplicationInsights.TelemetryClient();
                      ExceptionTelemetry et = new ExceptionTelemetry(e);
                      et.Properties.Add("user", User.Identity?.Name ?? string.Empty);
                      tc.TrackException(et);
                  }
                  catch (Exception ex)
                  {
                      _logger?.LogError(ex.ToString());
                  }
                  if (e is HubException)
                      return BadRequest(e);
                  HubException hue = new HubException(e.Message, e);
                  return BadRequest(hue);
              }
          }
  
          [HttpGet]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK, "LogonUser", typeof(ResultAccountGetUserByAuthorization))]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.NotFound, "LogonUser", typeof(ResultAccountGetUserByAuthorization))]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.BadRequest, "LogonUser", typeof(ResultAccountGetUserByAuthorization))]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("AccountGetUserByAuthorization")]
          [Authorize]
          public async Task<ActionResult<ResultAccountGetUserByAuthorization>> GetUserByAuthorization()
          {
              ResultAccountGetUserByAuthorization res;
              try
              {
                  var user = await _signInManager.UserManager.GetUserAsync(User);
                  res = new ResultAccountGetUserByAuthorization(user);
                  if (user == null)
                      return NotFound(res);
  
                  res.MyApplicationUser.PasswordHash = string.Empty;
                  res.MyApplicationUser.SecurityStamp = string.Empty;
                  return res;
              }
              catch (Exception e)
              {
                  try
                  {
                      var user = await _signInManager.UserManager.GetUserAsync(User);
                      //var tc = new Microsoft.ApplicationInsights.TelemetryClient();
                      ExceptionTelemetry et = new ExceptionTelemetry(e);
                      et.Properties.Add("user", User.Identity?.Name);
                      tc.TrackException(et);
                  }
                  catch (Exception ex)
                  {
                      _logger?.LogError(ex.ToString());
                  }
                  res = new ResultAccountGetUserByAuthorization(e);
                  return BadRequest(res);
              }
          }
  
          [HttpGet]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.OK)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerResponse((int)HttpStatusCode.Unauthorized)]
          [Swashbuckle.AspNetCore.Annotations.SwaggerOperation("ResetDb")]
          [Authorize(Roles = "Administrator")]
  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetDeleteAllSINnersDb()'
          public async Task<ActionResult<string>> GetDeleteAllSINnersDb()
  #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member 'AccountController.GetDeleteAllSINnersDb()'
          {
              try
              {
  
gt:                 var user = await _signInManager.UserManager.GetUserAsync(User);