using qtc_net_client_2.ClientModel;
using qtc_net_client_2.Properties;
using qtc_net_client_2.Services;
using QtCNETAPI.Dtos.User;
using QtCNETAPI.Models;
using QtCNETAPI.Schema;
using QtCNETAPI.Services.ApiService;
using QtCNETAPI.Services.GatewayService;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace qtc_net_client_2.Forms
{
    public partial class Profile : Form
    {
        private UserInformationDto _userInformationDto;
        private ImageFactory _imgFactory = new();
        private IApiService _apiService;
        private IGatewayService _gatewayService;

        private ServiceResponse<byte[]>? pfpRes;
        byte[]? cosmeticRes;

        private List<Contact> contactsList;
        public Profile(UserInformationDto userInfo, ServiceResponse<byte[]>? pfp, List<Contact> contacts, IApiService apiService, IGatewayService gatewayService, byte[]? cosmetic = null)
        {
            _userInformationDto = userInfo;
            _apiService = apiService;
            _gatewayService = gatewayService;
            pfpRes = pfp;
            cosmeticRes = cosmetic;
            contactsList = contacts;

            InitializeComponent();
        }

        private async void frmProfile_Load(object sender, EventArgs e)
        {
            lblUsername.Text = _userInformationDto.Username;
            lblCurrencyAmount.Text = _userInformationDto.CurrencyAmount.ToString("N0");
            rtxtBio.Text = _userInformationDto.Bio;

            Bitmap? pfp = null;
            if (pfpRes != null && pfpRes.Success && pfpRes.Data != null)
            {
                using (var ms = new MemoryStream(pfpRes.Data))
                {
                    pfp = new Bitmap(ms);
                }
            }

            var userStatus = (UserStatus)_userInformationDto.Status;
            Bitmap precenseImage = Resources.OnlineIcon;
            switch (userStatus)
            {
                case UserStatus.Online:
                    precenseImage = Resources.OnlineIcon;
                    break;
                case UserStatus.Away:
                    precenseImage = Resources.AwayIcon;
                    break;
                case UserStatus.DoNotDisturb:
                    precenseImage = Resources.DNDIcon;
                    break;
                case UserStatus.Offline:
                    precenseImage = Resources.OfflineIcon;
                    break;
            }

            Bitmap? cosmetic = null;
            if(cosmeticRes != null)
            {
                using var ms = new MemoryStream(cosmeticRes);
                cosmetic = new Bitmap(ms);
            }

            pbUserPfp.Image = _imgFactory.CreateProfileImage(precenseImage, pfp, cosmetic);
            precenseImage.Dispose();
            pfp?.Dispose();
            cosmetic?.Dispose();

            if (_userInformationDto.Id == _apiService.CurrentUser!.Id)
            {
                btnAddContact.Visible = false;
                btnMessage.Visible = false;
                return; // do not run contact getting code
            }
            else btnAddContact.Visible = true;

            if (contactsList != null)
            {
                var contact = contactsList.FirstOrDefault(e => e.UserId == _userInformationDto.Id || e.OwnerId == _userInformationDto.Id);
                if (contact != null)
                {
                    if (contact.OwnerId == _apiService.CurrentUser.Id)
                    {
                        // the user requesting this profile initiated a contact relationship with this user
                        switch (contact.OwnerStatus)
                        {
                            case Contact.ContactStatus.AwaitingApprovalFromOther:
                                btnAddContact.Enabled = false;

                                using (var ms = new MemoryStream(Resources.RequestSentIcon)) { btnAddContact.Image = Image.FromStream(ms); ms.Dispose(); }
                                btnCancelRequest.Visible = true;
                                break;
                            case Contact.ContactStatus.Accepted:
                                btnAddContact.Visible = true;
                                btnAddContact.Enabled = true;
                                btnAddContact.Image = Resources.RemoveContactIcon;
                                btnAddContact.Click += btnAddContact_Click_Remove;
                                if (_userInformationDto.Status >= 1) btnMessage.Visible = true;
                                break;
                        }
                    }
                    else if (contact.UserId == _apiService.CurrentUser.Id)
                    {
                        // the user requesting this profile did not initiate a contact relationship with the user
                        switch (contact.UserStatus)
                        {
                            case Contact.ContactStatus.AwaitingApprovalFromSelf:
                                btnAddContact.Visible = false;

                                btnAccept.Visible = true;
                                btnDecline.Visible = true;
                                btnCancelRequest.Visible = false;
                                break;
                            case Contact.ContactStatus.Accepted:
                                btnAccept.Visible = false;
                                btnDecline.Visible = false;
                                btnCancelRequest.Visible = false;

                                btnAddContact.Visible = true;
                                btnAddContact.Enabled = true;
                                btnAddContact.Image = Resources.RemoveContactIcon;
                                btnAddContact.Click += btnAddContact_Click_Remove;
                                if (_userInformationDto.Status >= 1) btnMessage.Visible = true;
                                break;
                        }
                    }
                }
                else
                {
                    btnAddContact.Visible = true;
                    btnAddContact.Click += btnAddContact_Click_Add;
                }
            }
            else
            {
                btnAddContact.Visible = true;
                btnAddContact.Click += btnAddContact_Click_Add;
            }
        }

        private void Profile_FormClosed(object sender, FormClosedEventArgs e)
        {
            _userInformationDto = null!; // ignoring warning since this is just disposing the form
            pfpRes = null;
        }

        private async void btnAddContact_Click_Add(object sender, EventArgs e)
        {
            var result = await _apiService.AddContactToCurrentUser(_userInformationDto.Id);
            if (result.Success)
            {
                btnAddContact.Enabled = false;
                using (var ms = new MemoryStream(Resources.RequestSentIcon)) { btnAddContact.Image = Image.FromStream(ms); ms.Dispose(); }
                btnCancelRequest.Visible = true;
            }
        }

        private async void btnAddContact_Click_Remove(object sender, EventArgs e)
        {
            var msgBoxResult = MessageBox.Show("Are You Sure You Want To Remove This User From Your Contacts?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (msgBoxResult == DialogResult.No) return;

            var result = await _apiService.RemoveContactFromCurrentUser(_userInformationDto.Id);
            if (result.Success)
            {
                btnAddContact.Image = Resources.AddContactIcon;
                btnAddContact.Click += btnAddContact_Click_Add;
                btnMessage.Visible = false;
            }
        }

        private async void btnAccept_Click(object sender, EventArgs e)
        {
            var result = await _apiService.AcceptContactRequest(_userInformationDto.Id);
            if (result.Success)
            {
                btnAccept.Visible = false;
                btnDecline.Visible = false;

                btnAddContact.Visible = true;
                btnAddContact.Image = Resources.RemoveContactIcon;
                btnAddContact.Click += btnAddContact_Click_Remove;
                if (_userInformationDto.Status >= 1) btnMessage.Visible = true;
            }
        }

        private async void btnDecline_Click(object sender, EventArgs e)
        {
            var msgBoxResult = MessageBox.Show("Are You Sure You Want To Decline This Request?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (msgBoxResult == DialogResult.No) return;

            var result = await _apiService.RemoveContactFromCurrentUser(_userInformationDto.Id);
            if (result.Success)
            {
                btnAccept.Visible = false;
                btnDecline.Visible = false;

                btnAddContact.Visible = true;
                btnAddContact.Image = Resources.AddContactIcon;
                btnAddContact.Click += btnAddContact_Click_Add;
            }
        }

        private async void btnCancelRequest_Click(object sender, EventArgs e)
        {
            var msgBoxResult = MessageBox.Show("Are You Sure You Want To Cancel This Request?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (msgBoxResult == DialogResult.No) return;

            var result = await _apiService.RemoveContactFromCurrentUser(_userInformationDto.Id);
            if (result.Success)
            {
                btnAddContact.Enabled = true;
                btnAddContact.Image = Resources.AddContactIcon;
                btnAddContact.Click += btnAddContact_Click_Add;

                btnCancelRequest.Visible = false;
            }
        }

        private void btnMessage_Click(object sender, EventArgs e)
        {
            DirectMessage frmDirectMessage = new DirectMessage(_gatewayService, _apiService, _userInformationDto);
            Close();
            frmDirectMessage.Show();
        }
    }
}
