using Mapster;

namespace NetinaShop.AdminPanel.PWA.Dialogs;

public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
{
    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;
    private bool _isSpecialOffer;

    public bool IsSpecialOffer
    {
        get => _isSpecialOffer;
        set
        {
            _isSpecialOffer = value;
            PageDto.IsSpecialOffer = value;
            if(!value)
            {
                IsAmountType = value;
                IsPercentType = value;
            }
        }
    }

    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 response = await _restWrapper.ProductRestApi.ReadOne(_product.Id);
                var productLDto = response.Product;
                PageDto.ExpertCheck = productLDto.ExpertCheck;
                PageDto.Summery = productLDto.Summery;
                PageDto.BeDisplayed = productLDto.BeDisplayed;
                PageDto.HasExpressDelivery = productLDto.HasExpressDelivery;
                PageDto.PersianName = productLDto.PersianName;
                PageDto.EnglishName = productLDto.EnglishName;
                PageDto.Cost = productLDto.Cost;
                PageDto.PackingCost = productLDto.PackingCost;
                PageDto.MaxOrderCount = productLDto.MaxOrderCount;
                PageDto.Warranty = productLDto.Warranty;
                PageDto.Stock = productLDto.Stock;
                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, PersianName = productLDto.BrandName };
                PageDto.IsSpecialOffer = productLDto.IsSpecialOffer;
                IsSpecialOffer = PageDto.IsSpecialOffer;
                if (productLDto.SpecialOffer != null)
                {
                    Discount = productLDto.SpecialOffer;
                    switch (Discount.AmountType)
                    {
                        case DiscountAmountType.Amount:
                            IsAmountType = true;
                            IsPercentType = false;
                            break;
                        case DiscountAmountType.Percent:
                            IsAmountType = false;
                            IsPercentType = true;
                            break;
                    }

                    ExpireDate = Discount.ExpireDate;
                    StartDate = Discount.StartDate;
                }
            }
            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();
            if (token == null)
                throw new Exception("Token is null");
            PageDto.Specifications = Specifications.ToList();
            PageDto.Files = Files.ToList();
            PageDto.Id = Product.Id;
            PageDto.CategoryId = SelectedCategory?.Id ?? default;
            PageDto.BrandId = SelectedBrand?.Id ?? default;
            if (PageDto.IsSpecialOffer)
            {
                if (ExpireDate != null)
                    Discount.ExpireDate = ExpireDate.Value;
                if (StartDate != null)
                    Discount.StartDate = StartDate.Value;
                PageDto.SpecialOffer = Discount;
            }
            var request = PageDto.Adapt<UpdateProductCommand>();
            await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(request, token);
            _snackbar.Add($"ویرایش محصول {PageDto.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);
        }
        catch (Exception e)
        {
            _snackbar.Add(e.Message, Severity.Error);
        }
        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();
            if (token == null)
                throw new Exception("Token is null");
            PageDto.Specifications = Specifications.ToList();
            PageDto.Files = Files.ToList();
            PageDto.CategoryId = SelectedCategory?.Id ?? default;
            PageDto.BrandId = SelectedBrand?.Id ?? default;
            if (PageDto.IsSpecialOffer)
            {
                if (ExpireDate != null)
                    Discount.ExpireDate = ExpireDate.Value;
                if (StartDate != null)
                    Discount.StartDate = StartDate.Value;
                PageDto.SpecialOffer = Discount;
            }
            var request = PageDto.Adapt<CreateProductCommand>();
            await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);

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

            IsProcessing = false;
        }
    }

    public bool IsPercentType { get; set; } = true;
    public bool IsAmountType { get; set; }
    public DateTime? ExpireDate { get; set; }
    public DateTime? StartDate { get; set; }
    public DiscountSDto Discount { get; set; } = new DiscountSDto();
    public void AmountTypeChanged(DiscountAmountType type)
    {
        switch (type)
        {
            case DiscountAmountType.Amount:
                IsAmountType = true;
                IsPercentType = false;
                break;
            case DiscountAmountType.Percent:
                IsAmountType = false;
                IsPercentType = true;
                break;
        }
    }

    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);
    }
}