using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using MultipleChoiceTrainer.Data;
using MultipleChoiceTrainer.Models;
using MultipleChoiceTrainer.Models.DataModels;

namespace MultipleChoiceTrainer.Controllers
{
    public class QuestionsController : Controller
    {
        private readonly ApplicationDbContext _context;
        private readonly IWebHostEnvironment _webHostEnvironment;

        public const int CountChoiceFields = 10;

        public QuestionsController(ApplicationDbContext context, IWebHostEnvironment hostEnvironment)
        {
            _context = context;
            _webHostEnvironment = hostEnvironment;
        }

        public IActionResult List(int sectionId)
        {
            return View(_context.Questions.Include(e => e.Choices).Where(e => e.SectionId == sectionId));
        }


        // GET: Questions/Create
        public IActionResult Create(int sectionId)
        {
            ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == sectionId);
            ViewData["CountChoiceFields"] = CountChoiceFields;
            return View();
        }

        // POST: Questions/Create
        // To protect from overposting attacks, enable the specific properties you want to bind to, for 
        // more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(QuestionViewModel question, bool anotherQuestion)
        {
            question.CreationDate = DateTime.Now;
            if (ModelState.IsValid)
            { 
                question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList();
                CopyUploadedFile(question);

                _context.Add(question as Question);
                await _context.SaveChangesAsync();
                
                if(anotherQuestion)
                {
                    return RedirectToAction(nameof(Create), new { sectionId = question.SectionId });
                }
                else
                {
                    var section = _context.Sections.FirstOrDefault(s => s.Id == question.SectionId);
                    return RedirectToAction(nameof(Index), "Home", new { categoryId = section.CategoryId });
                }   
            }
            ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId);
            ViewData["CountChoiceFields"] = CountChoiceFields;
            return View(question);
        }

        // GET: Questions/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var question = _context.Questions.Include(e => e.Choices).FirstOrDefault(e => e.Id == id);
            if (question == null)
            {
                return NotFound();
            }

            ViewData["CountChoiceFields"] = CountChoiceFields;
            ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId);

            var vm = new QuestionViewModel()
            {
                Choices = question.Choices,
                Image = question.Image,
                Id = question.Id,
                SectionId = question.SectionId,
                Text = question.Text
            };
            return View(vm);
        }

        // POST: Questions/Edit/5
        // To protect from overposting attacks, enable the specific properties you want to bind to, for 
        // more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, QuestionViewModel question)
        {
            if (id != question.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                var deletedChoices = question.Choices.Where(e => (string.IsNullOrEmpty(e.Text) || string.IsNullOrWhiteSpace(e.Text)) && e.Id != 0).Select(e => e.Id).ToList();

                question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList();

                CopyUploadedFile(question);
                try
                {
                    _context.Update(question as Question);
                    await _context.SaveChangesAsync();

                    if(deletedChoices.Any())
                    {
                        var q = _context.Questions.Include(e => e.Choices).First(e => e.Id == id);
                        q.Choices.RemoveAll(e => deletedChoices.Contains(e.Id));
                        await _context.SaveChangesAsync();
                    }
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!QuestionExists(question.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(List), new { sectionId = question.SectionId });
            }
            ViewData["CountChoiceFields"] = CountChoiceFields;
            ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId);
            return View(question);
        }

        private bool QuestionExists(int id)
        {
            return _context.Questions.Any(e => e.Id == id);
        }

        private void CopyUploadedFile(QuestionViewModel model)
        {
            if (model.QuestionImage != null)
            {
                string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "uploads", "images", "questions");
                Directory.CreateDirectory(uploadsFolder);

                model.Image = Guid.NewGuid().ToString() + Path.GetExtension(model.QuestionImage.FileName);
                string filePath = Path.Combine(uploadsFolder, model.Image);
                using (var fileStream = new FileStream(filePath, FileMode.Create))
                {
                    model.QuestionImage.CopyTo(fileStream);
                }
            }
        }
    }
}
