using Force.DeepCloner;

namespace Netina.AdminPanel.PWA.Pages.Personalization;

public class ManageNavMenuPageViewModel : BaseViewModel<NavMenuSetting>
{
    private readonly NavigationManager _navigationManager;
    private readonly ISnackbar _snackbar;
    private readonly IUserUtility _userUtility;
    private readonly IDialogService _dialogService;
    private readonly IRestWrapper _restWrapper;
    public ObservableCollection<NavMenuItem> NavMenuItems { get; set; } = new();
    public NavMenuItem NewNavItem { get; set; } = new NavMenuItem();

    public ManageNavMenuPageViewModel(
        NavigationManager navigationManager,
        ISnackbar snackbar,
        IUserUtility userUtility,
        IRestWrapper restWrapper,
        IDialogService dialogService) : base(userUtility)
    {
        _navigationManager = navigationManager;
        _snackbar = snackbar;
        _userUtility = userUtility;
        _restWrapper = restWrapper;
        _dialogService = dialogService;
    }

    public override async Task InitializeAsync()
    {
        try
        {
            IsProcessing = true;
            var token = await _userUtility.GetBearerTokenAsync();
            if (token == null)
                throw new Exception("Token is null");

            PageDto = await _restWrapper.SettingRestApi.GetSettingAsync<NavMenuSetting>(nameof(NavMenuSetting), token);

            PageDto.NavMenuItems.ForEach(ni =>
            {
                if (ni.ParentId!=default)
                    ni.Parent = PageDto.NavMenuItems.FirstOrDefault(np => np.Id == ni.ParentId);
                NavMenuItems.Add(ni);
            });

        }
        catch (ApiException e)
        {
            var exe = await e.GetContentAsAsync<ApiResult>();
            if (e.StatusCode == HttpStatusCode.Unauthorized)
            {
                await _userUtility.LogoutAsync();
                _navigationManager.NavigateTo("login", true, true);
            }
            _snackbar.Add(exe != null ? exe.Message : e.Content, Severity.Error);
        }
        catch (Exception ex)
        {
            _snackbar.Add(ex.Message, Severity.Error);
        }
        finally
        {
            IsProcessing = false;
        }
        await base.InitializeAsync();
    }

    public void SubmitAddNewNavItem()
    {
        try
        {
            if (NewNavItem.Title.IsNullOrEmpty())
                throw new Exception("عنوان فهرست را وارد کنید");
            if (NewNavItem.Url.IsNullOrEmpty())
                throw new Exception("لینک صفحه فهرست را وارد کنید");
            var item = NewNavItem.DeepClone();
            NavMenuItems.Add(item);

            NewNavItem = new NavMenuItem();
        }
        catch (Exception ex)
        {
            _snackbar.Add(ex.Message, Severity.Error);
        }
    }

    public async Task SubmitNavMenuSettingAsync()
    {
        try
        {


            var token = await _userUtility.GetBearerTokenAsync();
            if (token == null) throw new Exception("Token is null");
            PageDto.NavMenuItems.Clear();
            foreach (var navMenuItem in NavMenuItems)
            {
                navMenuItem.Parent = null;
                navMenuItem.Children = new List<NavMenuItem>();
                PageDto.NavMenuItems.Add(navMenuItem);
            }
            await _restWrapper.SettingRestApi.PostSettingAsync(nameof(NavMenuSetting), PageDto, token);
            _snackbar.Add("تنظیمات فهرست ها با موفقیت به روز شد", Severity.Success);
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (ex.StatusCode == HttpStatusCode.Unauthorized)
            {
                await _userUtility.LogoutAsync();
                _navigationManager.NavigateTo("login", true, true);
            }
            _snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
        }
        finally
        {
            IsProcessing = false;
        }

    }


    public ProductSDto? SelectedProduct = null;
    public async Task<IEnumerable<ProductSDto>> SearchProductAsync(string product)
    {
        try
        {
            var token = await _userUtility.GetBearerTokenAsync();
            if (token == null)
                throw new Exception("Token is null");
            var response = await _restWrapper.ProductRestApi.ReadAll(0,product,null,null,token);
            var categories = response.Products;
            if (product.IsNullOrEmpty())
                return categories;
            return categories.Where(c => c.PersianName.Contains(product));
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (exe != null)
                _snackbar.Add(exe.Message, Severity.Error);
            _snackbar.Add(ex.Content, Severity.Error);
            return new List<ProductSDto>();
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            return new List<ProductSDto>();
        }
    }
    public void AddFromProduct()
    {
        if (SelectedProduct == null)
            return;
        NavMenuItems.Add(new NavMenuItem
        {
            Title = SelectedProduct.PersianName,
            Id = Guid.NewGuid(),
            Url = $"/products/{SelectedProduct.Id}/{SelectedProduct.Slug}"
        });
        SelectedProduct = null;

    }


    public BlogSDto? SelectedBlog = null;
    public async Task<IEnumerable<BlogSDto>> SearchBlogAsync(string blog)
    {
        try
        {
            var response = await _restWrapper.BlogRestApi.ReadAll(0, blog);
            var categories = response.Blogs;
            if (blog.IsNullOrEmpty())
                return categories;
            return categories.Where(c => c.Title.Contains(blog));
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (exe != null)
                _snackbar.Add(exe.Message, Severity.Error);
            _snackbar.Add(ex.Content, Severity.Error);
            return new List<BlogSDto>();
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            return new List<BlogSDto>();
        }
    }
    public void AddFromBlog()
    {
        if (SelectedBlog == null)
            return;
        NavMenuItems.Add(new NavMenuItem
        {
            Title = SelectedBlog.Title,
            Id = Guid.NewGuid(),
            Url = $"/blogs/{SelectedBlog.Id}/{SelectedBlog.Slug}"
        });
        SelectedBlog = null;

    }

    public BlogCategorySDto? SelectedBlogCategory = null;
    public async Task<IEnumerable<BlogCategorySDto>> SearchBlogCategoryAsync(string blogCategory)
    {
        try
        {
            var categories = await _restWrapper.BlogCategoryRestApi.ReadAll(blogCategory);
            if (blogCategory.IsNullOrEmpty())
                return categories;
            return categories.Where(c => c.Name.Contains(blogCategory));
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (exe != null)
                _snackbar.Add(exe.Message, Severity.Error);
            _snackbar.Add(ex.Content, Severity.Error);
            return new List<BlogCategorySDto>();
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            return new List<BlogCategorySDto>();
        }
    }
    public void AddFromBlogCategory()
    {
        if(SelectedBlogCategory==null)
            return;
        NavMenuItems.Add(new NavMenuItem
        {
            Title = SelectedBlogCategory.Name,
            Id = Guid.NewGuid(),
            Url = $"/categories/{SelectedBlogCategory.Id}/{SelectedBlogCategory.Slug}"
        });
        SelectedBlogCategory = null;

    }

    public ProductCategorySDto? SelectedProductCategory = null;
    public async Task<IEnumerable<ProductCategorySDto>> SearchProductCategoryAsync(string productCategory)
    {
        try
        {
            var categories = await _restWrapper.ProductCategoryRestApi.ReadAll(productCategory);
            if (productCategory.IsNullOrEmpty())
                return categories;
            return categories.Where(c => c.Name.Contains(productCategory));
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (exe != null)
                _snackbar.Add(exe.Message, Severity.Error);
            _snackbar.Add(ex.Content, Severity.Error);
            return new List<ProductCategorySDto>();
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            return new List<ProductCategorySDto>();
        }
    }
    public void AddFromProductCategory()
    {
        if (SelectedProductCategory == null)
            return;
        NavMenuItems.Add(new NavMenuItem
        {
            Title = SelectedProductCategory.Name,
            Id = Guid.NewGuid(),
            Url = $"/products/{SelectedProductCategory.Id}/{SelectedProductCategory.Slug}"
        });
        SelectedBlogCategory = null;

    }


    public async Task<IEnumerable<NavMenuItem>> SearchNavMenuItem(string navTitle)
    {
        if (navTitle.IsNullOrEmpty())
            return NavMenuItems;
        return NavMenuItems.Where(c => c.Title.Trim().ToUpper().Contains(navTitle.Trim().ToUpper()));
    }

    public NavMenuItem? SelectedParent = null;
    public void AddNavMenuItemParent(Guid childId)
    {
        var child = NavMenuItems.FirstOrDefault(c => c.Id == childId);
        if(child == null)
            return;
        if (child.ParentId != default)
        {
            var oldParent = NavMenuItems.FirstOrDefault(c => c.Id == child.ParentId);
            if (oldParent != null)
                oldParent.Children.Remove(child);
        }

        if (child.Parent == null)
            return;
        var parentId = child.Parent.Id;
        var parent = NavMenuItems.FirstOrDefault(c => c.Id == parentId);
        if(parent == null)
            return;
        child.ParentId = parentId;
        parent.Children.Add(child);
        SelectedParent = null;
        return;
    }

    public void RemoveNavItem(Guid navItemId)
    {
        var navItem = NavMenuItems.FirstOrDefault(ni => ni.Id == navItemId);
        if (navItem != null)
            NavMenuItems.Remove(navItem);
    }
}