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 PrescriptionViewModel
	{
		private readonly GeneralViewModel _general;

		internal GeneralViewModel General => _general;

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

		/// <summary>
		/// Привязка данных к источникам данных таблицы
		/// </summary>
		/// <param name="dgv"></param>
		internal void SetDefaultDataSource<T>(DataGridView dgv) where T : IUnionId
		{
			switch (typeof(T).Name)
			{
				case "Prescription":
					dgv.DataSource = new SortableBindingList<PrescriptionWrapper>(
							PrescriptionWrapper.ToList(_general.Context.Prescriptions
						.Include(x => x.Patient)
						.ThenInclude(y => y.PatientNavigation)
						.Where(x => x.DoctorId == _general.DoctorId)
						.ToList()));
					break;
				case "DrugTypePrescription":
					dgv.DataSource = new SortableBindingList<DrugTypePrescriptionWrapper>(
						DrugTypePrescriptionWrapper.ToList(_general.Context.DrugTypePrescriptions
						.Include(x => x.DoseUnit)
						.Include(x => x.DrugType)
						.Include(x => x.IntakeMethod)
						.ToList()));
					break;
				case "ExaminationTypePrescription":
					dgv.DataSource = new SortableBindingList<ExaminationTypePrescriptionWrapper>(
						ExaminationTypePrescriptionWrapper.ToList(_general.Context.ExaminationTypePrescriptions
						.Include(x => x.ExaminationType)
						.Include(x => x.Result)
						.ToList()));
					break;
				case "ProcedureTypePrescription":
					dgv.DataSource = new SortableBindingList<ProcedureTypePrescriptionWrapper>(
						ProcedureTypePrescriptionWrapper.ToList(_general.Context.ProcedureTypePrescriptions
						.Include(x => x.ProcedureType)
						.ToList()));
					break;
			}
		}

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

		public List<T> GetPrescription<T>(int? id = null) where T : IUnionId
		{
			List<T> res = [];
			switch (typeof(T).Name)
			{
				case "Prescription":
					res = _general.Context.Prescriptions as List<T> ?? [];
					break;
				case "DrugTypePrescription":
					res = _general.Context.DrugTypePrescriptions as List<T> ?? [];
					break;
				case "ExaminationTypePrescription":
					res = _general.Context.ExaminationTypePrescriptions as List<T> ?? [];
					break;
				case "ProcedureTypePrescription":
					res = _general.Context.ProcedureTypePrescriptions as List<T> ?? [];
					break;
			}

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

		public void Update()
		{
			_general.Context.SaveChanges();
		}

		public int AddPrescription<T>(T type) where T : IUnionId
		{
			try
			{
				switch (typeof(T).Name)
				{
					case "Prescription":
						_general.Context.Prescriptions.Add(type as Prescription);
						_general.Context.SaveChanges();
						return _general.Context.Prescriptions
									.OrderByDescending(x => x.PrescriptionId).First().PrescriptionId;
					case "DrugTypePrescription":
						_general.Context.DrugTypePrescriptions.Add(type as DrugTypePrescription);
						break;
					case "ExaminationTypePrescription":
						_general.Context.ExaminationTypePrescriptions.Add(type as ExaminationTypePrescription);
						break;
					case "ProcedureTypePrescription":
						_general.Context.ProcedureTypePrescriptions.Add(type as ProcedureTypePrescription);
						break;
				}

				_general.Context.SaveChanges();
			}
			catch (DbUpdateException ex)
			{
				DeletePrescription(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 DeletePrescription<T>(T type) where T : IUnionId
		{
			switch (typeof(T).Name)
			{
				case "Prescription":
					_general.Context.Prescriptions.Remove(type as Prescription);
					break;
				case "DrugTypePrescription":
					_general.Context.DrugTypePrescriptions.Remove(type as DrugTypePrescription);
					break;
				case "ExaminationTypePrescription":
					_general.Context.ExaminationTypePrescriptions.Remove(type as ExaminationTypePrescription);
					break;
				case "ProcedureTypePrescription":
					_general.Context.ProcedureTypePrescriptions.Remove(type as ProcedureTypePrescription);
					break;
			}
			_general.Context.SaveChanges();
		}
	}
}
