using ComputersShopDataModels.Models;
using ComputersShopContracts.BusinessLogicContracts;
using ComputersShopContracts.SearchModels;
using ComputersShopContracts.BindingModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ComputersShopView
{
	public partial class FormComputer : Form
	{
		private readonly ILogger _logger;
		private readonly IComputerLogic _logic;
		private int? _id;
		private Dictionary<int, (IComponentModel, int)> _computerComponents;
		public int Id { set { _id = value; } }

		public FormComputer(ILogger<FormComputer> logger, IComputerLogic logic)
		{
			InitializeComponent();
			_logger = logger;
			_logic = logic;
			_computerComponents = new Dictionary<int, (IComponentModel, int)>();
		}

		private void FormComputer_Load(object sender, EventArgs e)
		{
			if (_id.HasValue)
			{
				_logger.LogInformation("Загрузка компьютера");
				try
				{
					var view = _logic.ReadElement(new ComputerSearchModel
					{
						Id = _id.Value
					});
					if (view != null)
					{
						textBoxName.Text = view.ComputerName;
						textBoxPrice.Text = view.Price.ToString();
						_computerComponents = view.ComputerComponents ?? new Dictionary<int, (IComponentModel, int)>();
						LoadData();
					}
				}
				catch (Exception ex)
				{
					_logger.LogError(ex, "Ошибка загрузки компьютера");
					MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
					MessageBoxIcon.Error);
				}
			}
		}
		private void LoadData()
		{
			_logger.LogInformation("Загрузка компонента компьютера");
			try
			{
				if (_computerComponents != null)
				{
					dataGridView.Rows.Clear();
					foreach (var pc in _computerComponents)
					{
						dataGridView.Rows.Add(new object[] { pc.Key, pc.Value.Item1.ComponentName, pc.Value.Item2 });
					}
					textBoxPrice.Text = CalcPrice().ToString();
				}
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка загрузки компонента компьютера");
				MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void ButtonAdd_Click(object sender, EventArgs e)
		{
			var service = Program.ServiceProvider?.GetService(typeof(FormComputerComponent));
			if (service is FormComputerComponent form)
			{
				if (form.ShowDialog() == DialogResult.OK)
				{
					if (form.ComponentModel == null)
					{
						return;
					}
					_logger.LogInformation("Добавление нового компонента: { ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count);
					if (_computerComponents.ContainsKey(form.Id))
					{
						_computerComponents[form.Id] = (form.ComponentModel,
					   form.Count);
					}
					else
					{
						_computerComponents.Add(form.Id, (form.ComponentModel,
					   form.Count));
					}
					LoadData();
				}
			}
		}
		private void ButtonUpd_Click(object sender, EventArgs e)
		{
			if (dataGridView.SelectedRows.Count == 1)
			{
				var service = Program.ServiceProvider?.GetService(typeof(FormComputerComponent));
				if (service is FormComputerComponent form)
				{
					int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value);
					form.Id = id;
					form.Count = _computerComponents[id].Item2;
					if (form.ShowDialog() == DialogResult.OK)
					{
						if (form.ComponentModel == null)
						{
							return;
						}
						_logger.LogInformation("Изменение компонента: { ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count);
						_computerComponents[form.Id] = (form.ComponentModel, form.Count);
						LoadData();
					}
				}
			}
		}

		private void ButtonDel_Click(object sender, EventArgs e)
		{
			if (dataGridView.SelectedRows.Count == 1)
			{
				if (MessageBox.Show("Удалить запись?", "Вопрос",
			   MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
				{
					try
					{
						_logger.LogInformation("Удаление компонента: { ComponentName} - { Count}", dataGridView.SelectedRows[0].Cells[1].Value);
						_computerComponents?.Remove(Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value));
					}
					catch (Exception ex)
					{
						MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
					LoadData();
				}
			}
		}

		private void ButtonRef_Click(object sender, EventArgs e)
		{
			LoadData();
		}

		private void ButtonSave_Click(object sender, EventArgs e)
		{
			if (string.IsNullOrEmpty(textBoxName.Text))
			{
				MessageBox.Show("Заполните название", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			if (string.IsNullOrEmpty(textBoxPrice.Text))
			{
				MessageBox.Show("Заполните цену", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			if (_computerComponents == null || _computerComponents.Count == 0)
			{
				MessageBox.Show("Заполните компоненты", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			_logger.LogInformation("Сохранение компьютера");
			try
			{
				var model = new ComputerBindingModel
				{
					Id = _id ?? 0,
					ComputerName = textBoxName.Text,
					Price = Convert.ToDouble(textBoxPrice.Text),
					ComputerComponents = _computerComponents
				};
				var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);
				if (!operationResult)
				{
					throw new Exception("Ошибка при сохранении. Дополнительная информация в логах.");
			    }
				MessageBox.Show("Сохранение прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
				DialogResult = DialogResult.OK;
				Close();
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка сохранения компьютера");
				MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void ButtonCancel_Click(object sender, EventArgs e)
		{
			DialogResult = DialogResult.Cancel;
			Close();
		}

		private double CalcPrice()
		{
			double price = 0;
			foreach (var elem in _computerComponents)
			{
				price += ((elem.Value.Item1?.Cost ?? 0) * elem.Value.Item2);
			}
			return Math.Round(price * 1.1, 2);
		}

	}
}