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;
using System.Windows.Forms;

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

		internal GeneralViewModel General => _general;

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

		/// <summary>
		/// Привязка данных к источникам данных таблицы
		/// </summary>
		/// <param name="dgv"></param>
		internal void SetDefaultDataSource<T>(DataGridView dgv) where T : IUnionId
		{
			switch (typeof(T).Name)
			{
				case "HospitalAdmission":
					dgv.DataSource = new SortableBindingList<HospitalAdmissionWrapper>(
						HospitalAdmissionWrapper.ToList(GetHospitalAdmission()));
					break;
				case "HospitalDischarge":
					dgv.DataSource = new SortableBindingList<HospitalDischargeWrapper>(
						HospitalDischargeWrapper.ToList(GetHospitalDischarge()));
					break;
			}
		}

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

		public List<HospitalAdmission> GetHospitalAdmission(int? id = null)
		{
			List<HospitalAdmission> res = _general.Context.HospitalAdmissions
						.Include(x => x.PreliminaryDisease)
						.Include(x => x.Patient)
							.ThenInclude(x => x.PatientNavigation)
						.ToList();

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

		public List<HospitalDischarge> GetHospitalDischarge(int? id = null)
		{
			List<HospitalDischarge> res = _general.Context.HospitalDischarges
						.Include(x => x.FinalDisease)
						.Include(x => x.HospitalAdmission)
							.ThenInclude(x => x.Patient)
								.ThenInclude(x => x.PatientNavigation)
						.Include(x => x.HospitalAdmission)
							.ThenInclude(x => x.PreliminaryDisease)
						.ToList();

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

		public int AddHospital<T>(T type) where T : IUnionId
		{
			try
			{
				switch (typeof(T).Name)
				{
					case "HospitalAdmission":
						_general.Context.HospitalAdmissions.Add(type as HospitalAdmission);
						break;
					case "HospitalDischarge":
						_general.Context.HospitalDischarges.Add(type as HospitalDischarge);
						break;
				}

				_general.Context.SaveChanges();
			}
			catch (DbUpdateException ex)
			{
				DeleteHospital(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);
				return -1;
			}

			return 0;
		}

		public void DeleteHospital<T>(T type) where T : IUnionId
		{
			switch (typeof(T).Name)
			{
				case "HospitalAdmission":
					_general.Context.HospitalAdmissions.Remove(type as HospitalAdmission);
					break;
				case "HospitalDischarge":
					_general.Context.HospitalDischarges.Remove(type as HospitalDischarge);
					break;
			}
			_general.Context.SaveChanges();
		}

		public void Update()
		{
			try
			{
				_general.Context.SaveChanges();
			}
			catch (DbUpdateException ex)
			{
				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);
			}
		}
	}
}
