namespace NetinaShop.AdminPanel.PWA.Dialogs;

public class ProductActionDialogBoxViewModel : BaseViewModel
{
    private readonly ISnackbar _snackbar;
    private readonly IRestWrapper _restWrapper;
    private readonly IUserUtility _userUtility;
    private readonly IDialogService _dialogService;
    private readonly MudDialogInstance _mudDialog;

    public ProductActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, IDialogService dialogService, MudDialogInstance mudDialog)
    {
        _snackbar = snackbar;
        _restWrapper = restWrapper;
        _userUtility = userUtility;
        _dialogService = dialogService;
        _mudDialog = mudDialog;
    }
    public ProductActionDialogBoxViewModel(ISnackbar snackbar,
        IRestWrapper restWrapper, 
        IUserUtility userUtility, 
        IDialogService dialogService, 
        MudDialogInstance mudDialog,
        ProductSDto product)
    {
        _snackbar = snackbar;
        _restWrapper = restWrapper;
        _userUtility = userUtility;
        _dialogService = dialogService;
        _mudDialog = mudDialog;
        Product = product;
    }

    private ProductSDto? _product = null;
    public ProductSDto? Product
    {
        get => _product;
        set
        {
            _product = value;
            if (_product != null)
            {
                IsEditing = true;
            }
        }
    }

    public void Cancel() => _mudDialog.Cancel();

    public bool IsEditing = false;
    public string ExpertCheck = string.Empty;
    public string Summery = string.Empty;
    public bool BeDisplayed = true;
    public bool HasExpressDelivery = false;
    public string PersianName = string.Empty;
    public string EnglishName = string.Empty;
    public double Cost;
    public double PackingCost;
    public int MaxOrder;
    public string Warranty = string.Empty;
    public string Tags = string.Empty;

    public string SpecificationTitle = string.Empty;
    public string SpecificationValue = string.Empty;
    public readonly ObservableCollection<SpecificationSDto> Specifications = new ObservableCollection<SpecificationSDto>();
    public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();


    public override async Task InitializeAsync()
    {
        if (IsEditing && _product != null)
        {
            try
            {
                IsProcessing = true;
                var productLDto = await _restWrapper.CrudDtoApiRest<Product, ProductLDto, Guid>(Address.ProductController).ReadOne(_product.Id);
                ExpertCheck = productLDto.ExpertCheck;
                Summery = productLDto.Summery;
                BeDisplayed = productLDto.BeDisplayed;
                HasExpressDelivery = productLDto.HasExpressDelivery;
                PersianName = productLDto.PersianName;
                EnglishName = productLDto.EnglishName;
                Cost = productLDto.Cost;
                PackingCost = productLDto.PackingCost;
                MaxOrder = productLDto.MaxOrderCount;
                Warranty = productLDto.Warranty;
                productLDto.Specifications.ForEach(s => Specifications.Add(s));
                productLDto.Files.ForEach(f => Files.Add(f));
                SelectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };
                SelectedBrand = new BrandSDto { Id = productLDto.BrandId, Name = productLDto.BrandName };
            }
            catch (ApiException ex)
            {
                var exe = await ex.GetContentAsAsync<ApiResult>();
                if (exe != null)
                    _snackbar.Add(exe.Message, Severity.Error);
                _snackbar.Add(ex.Content, Severity.Error);
                _mudDialog.Cancel();
            }
            catch (Exception e)
            {
                _snackbar.Add(e.Message, Severity.Error);
                _mudDialog.Cancel();
            }
            finally
            {

                IsProcessing = false;
            }
        };
    }

    public async Task SubmitEditAsync()
    {
        try
        {
            IsProcessing = true;
            if (Product == null || Product.Id == default)
                throw new Exception("محصول اشتباه است");
            if (SelectedCategory == null)
                throw new Exception("لطفا یک دسته بندی انتخاب کنید");
            if (SelectedBrand == null)
                throw new Exception("لطفا یک برند انتخاب کنید");
            var token = await _userUtility.GetBearerTokenAsync();
            var request = new UpdateProductCommand(Product.Id, PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, SelectedBrand?.Id ?? default, SelectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
            await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(request, token);
            _snackbar.Add($"ویرایش محصول {PersianName} با موفقیت انجام شد", Severity.Success);
            _mudDialog.Close();
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (exe != null)
                _snackbar.Add(exe.Message, Severity.Error);
            _snackbar.Add(ex.Content, Severity.Error);
            _mudDialog.Cancel();
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            _mudDialog.Cancel();
        }
        finally
        {

            IsProcessing = false;
        }
    }
    public async Task SubmitCreateAsync()
    {
        try
        {
            IsProcessing = true;
            if (SelectedCategory == null)
                throw new Exception("لطفا یک دسته بندی انتخاب کنید");
            if (SelectedBrand == null)
                throw new Exception("لطفا یک برند انتخاب کنید");
            var token = await _userUtility.GetBearerTokenAsync();
            var request = new CreateProductCommand(PersianName, EnglishName, Summery, ExpertCheck, Tags, Warranty, BeDisplayed, Cost, PackingCost, HasExpressDelivery, MaxOrder, SelectedBrand?.Id ?? default, SelectedCategory?.Id ?? default, Specifications.ToList(), Files.ToList());
            await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);

            _snackbar.Add($"ساخت محصول {PersianName} با موفقیت انجام شد", Severity.Success);
            _mudDialog.Close();
        }
        catch (ApiException ex)
        {
            var exe = await ex.GetContentAsAsync<ApiResult>();
            if (exe != null)
                _snackbar.Add(exe.Message, Severity.Error);
            _snackbar.Add(ex.Content, Severity.Error);
            _mudDialog.Cancel();
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            _mudDialog.Cancel();
        }
        finally
        {

            IsProcessing = false;
        }
    }


    private List<ProductCategorySDto> _productCategories = new List<ProductCategorySDto>();
    public ProductCategorySDto? SelectedCategory;
    public async Task<IEnumerable<ProductCategorySDto>> SearchProductCategory(string category)
    {
        try
        {
            if (category.IsNullOrEmpty())
                _productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(0);
            else
                _productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(category);
            return _productCategories;
        }
        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 _productCategories;
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            return _productCategories;
        }
    }

    private List<BrandSDto> _brands = new List<BrandSDto>();
    public BrandSDto? SelectedBrand;
    public async Task<IEnumerable<BrandSDto>> SearchBrand(string brand)
    {
        try
        {
            if (brand.IsNullOrEmpty())
                _brands = await _restWrapper.BrandRestApi.ReadAll(0);
            else
                _brands = await _restWrapper.BrandRestApi.ReadAll(brand);
            return _brands;
        }
        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 _brands;
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
            return _brands;
        }
    }


    public void AddSpecification()
    {
        try
        {
            if (SpecificationTitle.IsNullOrEmpty())
                throw new AppException("عنوان ویژگی مورد نظر را وارد کنید");
            if (SpecificationValue.IsNullOrEmpty())
                throw new AppException("مقدار ویژگی مورد نظر را وارد کنید");
            Specifications.Add(new SpecificationSDto { Title = SpecificationTitle.ToString(), Value = SpecificationValue.ToString() });

            SpecificationTitle = string.Empty;
            SpecificationValue = string.Empty;
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
        }
    }

    public void RemoveSpecification(SpecificationSDto specification)
    {
        var spec = Specifications.FirstOrDefault(s => s.Value == specification.Value && s.Title == specification.Title);
        if (spec != null)
            Specifications.Remove(spec);
    }

    public async Task SelectFileAsync()
    {
        DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
        var dialog = await _dialogService.ShowAsync<StorageDialogBox>("انتخاب عکس", maxWidth);
        var result = await dialog.Result;
        var file = result.Data;
        if (file is StorageFileSDto storageFile)
            Files.Add(storageFile);
    }

    public void RemoveFile(StorageFileSDto file)
    {
        Files.Remove(file);
    }
}