using ESuite.UI.E2E.Helpers;
using ESuite.UI.E2E.Models;
using ESuite.UI.E2E.Pages;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;

namespace ESuite.UI.E2E.StepDefinitions
{
    [Binding]
    public class DomainCreationStepDefinitions
    {
        private readonly IWebDriver driver;
        private readonly BasicPage basicPage;
        private readonly DomainEditPage domainEditPage;
        private readonly ScenarioContext _scenarioContext;
        private readonly AutomationTestManagerHelper automationTestManagerHelper;
        private readonly APIHelper apiHelper;
        private readonly ConfigHelper configHelper;

        public DomainCreationStepDefinitions(ScenarioContext scenarioContext)
        {
            driver = WebDriverHelper.GetWebDriver();
            basicPage = new(driver);
            domainEditPage = new(driver);
            _scenarioContext = scenarioContext;
            automationTestManagerHelper = new(_scenarioContext);
            apiHelper = new(_scenarioContext);
            configHelper = new();
        }

        [AfterScenario("deletedomain", Order = 10)]
        [When(@"I delete existing Domain")]
        public void DeleteDomain()
        {
            automationTestManagerHelper.DeleteDomain();
        }

        [AfterScenario("deletedomainapi", Order = 10)]
        [When(@"I delete existing Domain via API")]
        public async Task DeleteDomainViaAPI()
        {
            await automationTestManagerHelper.DeleteDomainAPI();
        }

        [BeforeScenario("createdomain", Order = 15)]
        public async Task CreateDomain()
        {
            await automationTestManagerHelper.CreateDomain("");
            var domains = await apiHelper.GetDomains(configHelper.APIUrl);
            var data = domains["data"]!.ElementAt(0);
            int domainId = (int)data["id"]!;
            string domainName = (string)data["name"]!;
            Guid domainGuid = Guid.Parse((string)data["guid"]!);
            Assert.AreEqual(domainName, _scenarioContext["DomainName"].ToString()!);
            _scenarioContext["DomainId"] = domainId;
            _scenarioContext["DomainGUID"] = domainGuid;
        }

        [Given(@"I create a new domain via API")]
        public async Task CreateDomain(Table dataTable)
        {
            var domains = dataTable.CreateSet<DomainsData>();
            List<string> domainList = [];
            foreach (var domain in domains)
            {
                var domainName = domain.Name + _scenarioContext["GUID"];

                await automationTestManagerHelper.CreateDomain(domainName);
                domainList.Add(domainName);
            }
            _scenarioContext["DomainList"] = domainList;
        }

        [Given(@"I create a new domain")]
        public void GivenICreateANewDomain(Table dataTable)
        {
            BasicPage.ClickOnDropdownMenuItem("Client Domains");

            var domains = dataTable.CreateSet<DomainsData>();

            foreach (var domain in domains)
            {
                _scenarioContext["DomainName"] = domain.Name + _scenarioContext["GUIDPostfix"];

                I.Click(BasicPage.AddButton);
                I.FillField(BasicPage.NameField, _scenarioContext["DomainName"].ToString()!);
                if (!string.IsNullOrWhiteSpace(domain.SSOProvider))
                {
                    I.SelectOption(BasicPage.SSOProvider, _scenarioContext["SSOProviderName"].ToString()!);
                }
                I.Click(BasicPage.SaveAndCloseButton);
                AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
                I.WaitTillInvisible(BasicPage.SaveAndCloseButton);
                BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainName"].ToString()!);
            }
        }

        [When(@"I edit domains details")]
        public void WhenIEditDomainsDetails(Table dataTable)
        {
            var domains = dataTable.CreateSet<DomainsData>();

            foreach (var domain in domains)
            {
                _scenarioContext["DomainName"] = domain.Name + _scenarioContext["GUIDPostfix"];

                I.FillField(BasicPage.NameField, _scenarioContext["DomainName"].ToString()!);
                if (!string.IsNullOrWhiteSpace(domain.SSOProvider))
                {
                    I.SelectOption(BasicPage.SSOProvider, _scenarioContext["SSOProviderName"].ToString()!);
                }
                I.Click(BasicPage.SaveAndCloseButton);
                AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
                I.WaitTillInvisible(BasicPage.SaveAndCloseButton);
                BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainName"].ToString()!);
            }
            _scenarioContext["DomainEdited"] = $"{_scenarioContext["DomainName"]}, {_scenarioContext["SSOProviderName"]}";
        }

        [Given(@"I edit created domain")]
        [When(@"I edit created domain")]
        public void WhenIEditCreatedDomain()
        {
            BasicPage.ClickOnDropdownMenuItem("Client Domains");
            BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainName"].ToString()!);
            I.Click(domainEditPage.EditButton(_scenarioContext["DomainName"].ToString()));
            I.WaitForVisible(domainEditPage.EditPageTitle);
        }

        [Then(@"I add a new Security Role")]
        public void ThenIAddANewSecurityRole(Table dataTable)
        {
            var roles = dataTable.CreateSet<DomainsData>();
            foreach (var role in roles)
            {
                _scenarioContext["DomainRoleName"] = role.RoleName + _scenarioContext["GUIDPostfix"];

                BasicPage.SelectTab("Security Roles");

                I.Click(BasicPage.AddButton);
                I.FillField(BasicPage.NameField, _scenarioContext["DomainRoleName"].ToString()!);
                I.Click(BasicPage.SaveAndCloseButton);
                AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
                BasicPage.SelectTab("Security Roles");
                BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainRoleName"].ToString()!);
            }
        }

        [Then(@"I change Mail Template")]
        public void ThenIChangeMailTemplate(Table dataTable)
        {
            var templates = dataTable.CreateSet<DomainsData>();
            foreach (var template in templates)
            {
                _scenarioContext["DomainMailTemplateName"] = template.TemplateName;
                _scenarioContext["DomainMailTemplateSubject"] = template.Subject + _scenarioContext["GUIDPostfix"];
                _scenarioContext["DomainMailTemplateDefinition"] = template.Definition + _scenarioContext["GUIDPostfix"];
                _scenarioContext["DomainMailTemplateCreated"] = $"{"false"}, {_scenarioContext["DomainName"]}, {_scenarioContext["DomainMailTemplateName"]}, " +
                   $"{_scenarioContext["DomainMailTemplateSubject"]}";
                _scenarioContext["DomainMailTemplateUpdated"] = $"{_scenarioContext["DomainMailTemplateSubject"]}, {_scenarioContext["DomainMailTemplateDefinition"]}";
                BasicPage.SelectTab("Mail Templates");
                I.WaitForPageToLoad();
                domainEditPage.ChooseMailTemplate(_scenarioContext["DomainMailTemplateName"].ToString());
                I.WaitForElementVisibleAndClickable(DomainEditPage.SubjectInput);
                I.FillField(DomainEditPage.SubjectInput, _scenarioContext["DomainMailTemplateSubject"].ToString()!);
                if (I.GetValueAttribute(DomainEditPage.SubjectInput) != _scenarioContext["DomainMailTemplateSubject"].ToString())
                {
                    I.FillField(DomainEditPage.SubjectInput, _scenarioContext["DomainMailTemplateSubject"].ToString()!);
                }
                I.FillField(BasicPage.CKEditorTextBox, _scenarioContext["DomainMailTemplateDefinition"].ToString()!);

                _scenarioContext["CKEditorTextBoxContent"] = I.GetTextFromElement(BasicPage.CKEditorTextBox);

                I.Click(BasicPage.SaveAndCloseButton);
                AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
                I.WaitTillInvisible(BasicPage.SaveAndCloseButton);
            }
        }

        [When(@"I check Mail Template changes")]
        public void ThenICheckMailTemplateChanges()
        {
            RetryHelper.Retry(() =>
            {
                BasicPage.SelectTab("Mail Templates");
                domainEditPage.ChooseMailTemplate(_scenarioContext["DomainMailTemplateName"].ToString());
                I.WaitForVisible(domainEditPage.SubjectNameInField(_scenarioContext["DomainMailTemplateSubject"].ToString()!));
                Assert.AreEqual(
                    I.GetValueAttribute(DomainEditPage.SubjectInput),
                    _scenarioContext["DomainMailTemplateSubject"]
                    );
                Assert.AreEqual(
                    _scenarioContext["CKEditorTextBoxContent"],
                    I.GetTextFromElement(BasicPage.CKEditorTextBox)
                    );
            });
        }

        [Then(@"I check new Security Role created")]
        public void ThenICheckNewSecurityRoleCreated()
        {
            RetryHelper.Retry(() =>
            {
                BasicPage.SelectTab("Security Roles");
                I.WaitForPageToLoad();
                BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainRoleName"].ToString()!);
            });
        }

        [When(@"I click on newly created Security Role")]
        public void WhenIClickOnNewlyCreatedSecurityRole()
        {
            I.Click(BasicPage.ObjectNameInTable(_scenarioContext["DomainRoleName"].ToString()));
            I.WaitForPageToLoad();
        }

        [Then(@"I choose Role Access permission options")]
        public void ThenIChooseRoleAccessPermissionOptions(Table dataTable)
        {
            var permissions = dataTable.CreateSet<PermissionsData>();
            foreach (var permission in permissions)
            {
                if (!string.IsNullOrEmpty(permission.Name))
                {
                    I.Click(domainEditPage.RoleAccessCheckbox(
                            permission.Name.Replace(" ", "")
                            )
                        );
                }
            }
            I.Click(DomainEditPage.RoleSaveButton);
            AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
        }

        [When(@"I enter into Users tab")]
        public void WhenIEnterIntoUsersTab()
        {
            BasicPage.SelectTab("Users");
        }

        [Then(@"I add User to Security Role")]
        public void ThenIAddUserToSecurityRole(Table dataTable)
        {
            By UserSelector = BasicPage.SelectorByLabel("User");
            var users = dataTable.CreateSet<UsersData>();

            foreach (var user in users)
            {
                if (!user.UserName!.Equals("UserName"))
                {
                    _scenarioContext["UserName"] = user.UserName;
                }

                I.Click(DomainEditPage.AddUserToRoleButton);
                I.WaitForVisible(UserSelector);
                I.SelectOption(UserSelector, _scenarioContext["UserName"]!);
                I.Click(BasicPage.SaveAndCloseButton);
                AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
            }
            _scenarioContext["RoleUserCreated"] = $"{"false"}, {_scenarioContext["DomainRoleName"]}, {_scenarioContext["UserName"]}";
        }

        [Then(@"I check if user is added to Security Role")]
        public void ThenICheckIfUserIsAddedToSecurityRole()
        {
            RetryHelper.Retry(() =>
            {
                I.FillField(BasicPage.SearchUsersInput, _scenarioContext["UserName"].ToString()!);
                I.WaitForVisible(BasicPage.ObjectNameInTable(_scenarioContext["UserName"].ToString()));
            });
        }

        [Given(@"I add a new Security Role via API")]
        public void GivenCreateRole()
        {
            automationTestManagerHelper.CreateRole();
        }

        [Then(@"I delete added Security Role")]
        [When(@"I delete added Security Role")]
        public void ThenIDeleteAddedSecurityRole()
        {
            BasicPage.ClickOnDropdownMenuItem("Client Domains");
            BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainName"].ToString()!);
            I.Click(domainEditPage.EditButton(_scenarioContext["DomainName"].ToString()));
            BasicPage.SelectTab("Security Roles");
            I.Click(BasicPage.DeleteObjectButton(_scenarioContext["DomainRoleName"].ToString()!));
            I.Click(BasicPage.ConfirmDeletionButton);
            AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
        }

        [When(@"I delete added User from Security Role")]
        public void ThenIDeleteUserFromSecurityRole()
        {
            BasicPage.ClickOnDropdownMenuItem("Client Domains");
            BasicPage.SearchObjectNameInTableViaSearchInputField(_scenarioContext["DomainName"].ToString()!);
            I.Click(domainEditPage.EditButton(_scenarioContext["DomainName"].ToString()));
            BasicPage.SelectTab("Security Roles");
            I.Click(BasicPage.ObjectNameInTable(_scenarioContext["DomainRoleName"].ToString()));
            BasicPage.SelectTab("Users");
            I.FillField(BasicPage.SearchUsersInput, _scenarioContext["UserName"].ToString()!);
            I.Click(BasicPage.DeleteObjectButton(_scenarioContext["UserName"].ToString()!));
            I.Click(BasicPage.ConfirmDeletionButton);
            AutomationTestManagerHelper.SaveTimingForAction(_scenarioContext);
        }
    }
}
