using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Npgsql;
using Register_office.BaseClasses;
using Register_office.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Register_office.ViewModel
{
	internal class TypeViewModel
	{
		private readonly GeneralViewModel _general;

		internal GeneralViewModel General => _general;

		public TypeViewModel()
		{
			_general = GeneralViewModel.Instance;
		}



		/// <summary>
		/// Привязка данных к источникам данных таблицы
		/// </summary>
		/// <param name="dgv"></param>
		internal void SetDefaultDataSource<T>(DataGridView dgv) where T : IUnionId
		{
			switch (typeof(T).Name)
			{
				case "Disease":
					dgv.DataSource = new SortableBindingList<Disease>(_general.Context.Diseases.ToList());
					break;
				case "DrugIntakeMethod":
					dgv.DataSource = new SortableBindingList<DrugIntakeMethod>(_general.Context.DrugIntakeMethods.ToList());
					break;
				case "DrugType":
					dgv.DataSource = new SortableBindingList<DrugType>(_general.Context.DrugTypes.ToList());
					break;
				case "DiseaseSyndrome":
					dgv.DataSource = new SortableBindingList<DiseaseSyndromeWrapper>(
						DiseaseSyndromeWrapper.ToList(_general.Context.DiseaseSyndromes
						.Include(x => x.Disease)
						.Include(x => x.Syndrome)
						.ToList()));
					break;
				case "ExaminationType":
					dgv.DataSource = new SortableBindingList<ExaminationType>(_general.Context.ExaminationTypes.ToList());
					break;
				case "ProcedureType":
					dgv.DataSource = new SortableBindingList<ProcedureType>(_general.Context.ProcedureTypes.ToList());
					break;
				case "ReferenceValue":
					dgv.DataSource = new SortableBindingList<ReferenceValueWrapper>(
						ReferenceValueWrapper.ToList(_general.Context.ReferenceValues
						.Include(x => x.ExaminationType).ToList()));
					break;
				case "SyndromeExaminationType":
					dgv.DataSource = new SortableBindingList<SyndromeExaminationTypeWrapper>(
						SyndromeExaminationTypeWrapper.ToList(_general.Context.SyndromeExaminationTypes
						.Include(x => x.ExaminationType)
						.Include(x => x.Syndrome)
						.ToList()));
					break;
				case "SyndromeType":
					dgv.DataSource = new SortableBindingList<SyndromeType>(_general.Context.SyndromeTypes.ToList());
					break;
				case "Unit":
					dgv.DataSource = new SortableBindingList<Unit>(_general.Context.Units.ToList());
					break;
			}
		}

		/// <summary>
		/// Настраивает таблицу под вывод данных
		/// </summary>
		/// <param name="dgv"></param>
		internal void ConfigureSettingsDGV<T>(DataGridView dgv)
		{
			_general.SetDefaultSettingsToDGV(dgv);
			_general.ConfigureGrid<T>(dgv);
		}

		public List<T> GetType<T>(int? id = null) where T : IUnionId
		{
			List<T> res = [];
			switch (typeof(T).Name)
			{
				case "Disease":
					res = _general.Context.Diseases as List<T> ?? [];
					break;
				case "DrugIntakeMethod":
					res = _general.Context.DrugIntakeMethods as List<T> ?? [];
					break;
				case "DrugType":
					res = _general.Context.DrugTypes as List<T> ?? [];
					break;
				case "DiseaseSyndrome":
					res = _general.Context.DiseaseSyndromes as List<T> ?? [];
					break;
				case "ExaminationType":
					res = _general.Context.ExaminationTypes as List<T> ?? [];
					break;
				case "ProcedureType":
					res = _general.Context.ProcedureTypes as List<T> ?? [];
					break;
				case "ReferenceNumericValue":
					res = _general.Context.ReferenceNumericValues as List<T> ?? [];
					break;
				case "ReferenceQualitativeValue":
					res = _general.Context.ReferenceQualitativeValues as List<T> ?? [];
					break;
				case "ReferenceValue":
					res = _general.Context.ReferenceValues as List<T> ?? [];
					break;
				case "SyndromeExaminationType":
					res = _general.Context.SyndromeExaminationTypes as List<T> ?? [];
					break;
				case "SyndromeType":
					res = _general.Context.SyndromeTypes as List<T> ?? [];
					break;
				case "Unit":
					res = _general.Context.Units as List<T> ?? [];
					break;
			}

			if (id == null)
				return res;
			else
				return res
				.Where(item => item.GetId().Equals(id))
				.ToList();
		}

		public void AddType<T>(T type) where T : IUnionId
		{
			try
			{
				switch (typeof(T).Name)
				{
					case "Disease":
						_general.Context.Diseases.Add(type as Disease);
						break;
					case "DrugIntakeMethod":
						_general.Context.DrugIntakeMethods.Add(type as DrugIntakeMethod);
						break;
					case "DrugType":
						_general.Context.DrugTypes.Add(type as DrugType);
						break;
					case "DiseaseSyndrome":
						_general.Context.DiseaseSyndromes.Add(type as DiseaseSyndrome);
						break;
					case "ExaminationType":
						_general.Context.ExaminationTypes.Add(type as ExaminationType);
						break;
					case "ProcedureType":
						_general.Context.ProcedureTypes.Add(type as ProcedureType);
						break;
					case "ReferenceNumericValue":
						_general.Context.ReferenceNumericValues.Add(type as ReferenceNumericValue);
						break;
					case "ReferenceQualitativeValue":
						_general.Context.ReferenceQualitativeValues.Add(type as ReferenceQualitativeValue);
						break;
					case "ReferenceValue":
						_general.Context.ReferenceValues.Add(type as ReferenceValue);
						break;
					case "SyndromeExaminationType":
						_general.Context.SyndromeExaminationTypes.Add(type as SyndromeExaminationType);
						break;
					case "SyndromeType":
						_general.Context.SyndromeTypes.Add(type as SyndromeType);
						break;
					case "Unit":
						_general.Context.Units.Add(type as Unit);
						break;
				}

				_general.Context.SaveChanges();
			}
			catch (DbUpdateException ex)
			{
				DeleteType(type);
				string message = "";
				if (ex.GetBaseException() is PostgresException pgException)
				{
					if (pgException.ConstraintName != null)
					{
						message = "Нарушено ограничение " + pgException.ConstraintName;
					}
					else
					{
						message = pgException.Message;
					}
				}

				MessageBox.Show(message, "Ошибка добавления",
						MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

		}

		public void DeleteType<T>(T type) where T : IUnionId
		{
			switch (typeof(T).Name)
			{
				case "Disease":
					_general.Context.Diseases.Remove(type as Disease);
					break;
				case "DrugIntakeMethod":
					_general.Context.DrugIntakeMethods.Remove(type as DrugIntakeMethod);
					break;
				case "DrugType":
					_general.Context.DrugTypes.Remove(type as DrugType);
					break;
				case "DiseaseSyndrome":
					_general.Context.DiseaseSyndromes.Remove(type as DiseaseSyndrome);
					break;
				case "ExaminationType":
					_general.Context.ExaminationTypes.Remove(type as ExaminationType);
					break;
				case "ProcedureType":
					_general.Context.ProcedureTypes.Remove(type as ProcedureType);
					break;
				case "ReferenceNumericValue":
					_general.Context.ReferenceNumericValues.Remove(type as ReferenceNumericValue);
					break;
				case "ReferenceQualitativeValue":
					_general.Context.ReferenceQualitativeValues.Remove(type as ReferenceQualitativeValue);
					break;
				case "ReferenceValue":
					_general.Context.ReferenceValues.Remove(type as ReferenceValue);
					break;
				case "SyndromeExaminationType":
					_general.Context.SyndromeExaminationTypes.Remove(type as SyndromeExaminationType);
					break;
				case "SyndromeType":
					_general.Context.SyndromeTypes.Remove(type as SyndromeType);
					break;
				case "Unit":
					_general.Context.Units.Remove(type as Unit);
					break;
			}
			_general.Context.SaveChanges();
		}
	}
}
