using Newtonsoft.Json;
using PCUT.Entities;
using PCUT.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Popups;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Controls;
using Windows.Storage.Streams;
using PCUT.Extensions;
using PCUT.Pages;
using Http.Core;
using Http.Core.Extensions;
using static Http.Core.Constants.HttpConstants;
using PCUT.Entities.ApiResponse;
using Http.Core.Exceptions;

namespace PCUT.ViewModels
{
    public class FileAddViewModel : NotificationBase
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { SetProperty(ref _name, value); }
        }
        
        private string _area;
        public string Area
        {
            get { return _area; }
            set { SetProperty(ref _area, value); }
        }

        private string _remarks;
        public string Remarks
        {
            get { return _remarks; }
            set { SetProperty(ref _remarks, value); }
        }

        private ImageSource _previewSource;
        public ImageSource PreviewSource
        {
            get { return _previewSource; }
            set { SetProperty(ref _previewSource, value); }
        }

        public SelectableCollection<Category> Categories { get; }
        public MetadataViewModel MetadataModel { get; }

        public FileAddViewModel()
        {
            Categories = new SelectableCollection<Category>();
            MetadataModel = new MetadataViewModel();

            MetadataModel.SetFilterChangedHandle();
        }

        public async Task GetCategoriesAsync()
        {
            using (var client = HttpClientFactory.CreateClient(ClientNames.ApiClient))
            {
                var categories = await client.GetCategoriesAsync(filterByRole: true);
                Categories.Load(categories);
            }
        }

        public async Task<bool> AddFileAsync(StorageFile file, Image image)
        {
            if (file == null)
            {
                var noFileSelectedDialog = new MessageDialog("Please select a file to upload!");
                await noFileSelectedDialog.ShowAsync();
                return false;
            }
            string fileId;
            using (var stream = await file.OpenReadAsync())
            {
                fileId = await UpLoadFileAsync(file.Name, stream.AsStreamForRead());
            }

            if (string.IsNullOrEmpty(fileId))
            {
                var uploadAgainDialog = new MessageDialog("Please select a file to upload!");
                await uploadAgainDialog.ShowAsync();
                return false;
            }

            string thumbnailId;
            using (var stream = await image.CreateThumbnailAsync())
            {
                thumbnailId = await UpLoadFileAsync(Path.GetFileNameWithoutExtension(file.Name) + ".png", stream.AsStreamForRead());
            }
            if (string.IsNullOrEmpty(thumbnailId))
            {
                var uploadAgainDialog = new MessageDialog("Please select a file to upload!");
                await uploadAgainDialog.ShowAsync();
                return false;
            }
            
            try
            {
                var fileInfo = new UpsertFile
                {
                    FileId = fileId,
                    Name = this.Name,
                    Thumbnail = thumbnailId,
                    Category = Categories.SelectedItem?.Id,
                    Type = MetadataModel.Types.SelectedItem?.Id,
                    Brand = MetadataModel.Brands.SelectedItem?.Id,
                    Series = MetadataModel.Series.SelectedItem?.Id,
                    Model = MetadataModel.Models.SelectedItem?.Id,
                    SubType = MetadataModel.SubTypes.SelectedItem?.Id,
                    Year = MetadataModel.Years.SelectedItem?.Id,
                    Area = this.Area,
                    Remarks = this.Remarks
                };
                using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient))
                {
                    var response = await client.PostAsJsonAsync(Api.CdrFiles, fileInfo);
                    if (!response.IsSuccessStatusCode)
                    {
                        var failDialog = new MessageDialog("An error occurred while adding the file!");
                        await failDialog.ShowAsync();
                        return false;
                    }
                }
            }
            catch (Exception ex) when (!(ex is AppOutdatedException))
            {
                var errorDialog = new MessageDialog($"Error: {ex.Message}");
                await errorDialog.ShowAsync();
                return false;
            }
            var successDialog = new MessageDialog("File added successfully!");
            await successDialog.ShowAsync();
            return true;
        }

        private async Task<string> UpLoadFileAsync(string name, Stream stream)
        {
            try
            {
                using (HttpClient client = HttpClientFactory.CreateClient(ClientNames.ApiClient))
                {
                    var content = new MultipartFormDataContent();
                    var streamContent = new StreamContent(stream);
                    streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                    {
                        Name = "file",
                        FileName = name
                    };
                    content.Add(streamContent);

                    var response = await client.PostAsync(Api.Upload, content);
                    if (response.IsSuccessStatusCode)
                    {
                        var uploadResponse = await response.DeserializeObjectAsync<DataResponse<FileData>>();
                        return uploadResponse.Data.Id;
                    }
                    else
                    {
                        var errorDialog = new MessageDialog("Error uploading file!");
                        await errorDialog.ShowAsync();
                    }
                }
            }
            catch (Exception ex) when (!(ex is AppOutdatedException))
            {
                var exceptionDialog = new MessageDialog($"Error: {ex.Message}");
                await exceptionDialog.ShowAsync();
            }
            return null;
        }
    }
}
