using AutoMapper;
using Infrastructure.Interfaces;
using Infrastructure.Models;
using Infrastructure.Services;
using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using TestCasePlanner.Helpers;
using TestCasePlanner.ViewModels;

namespace TestCasePlanner.Controllers
{
    [RoutePrefix("manage/testcases"), Route("{action=index}")]
    public class TestCaseController : AppBaseController
    {
        public TestCaseController() : this(new TestCaseService(), new TestSuiteService())
        {
        }

        public TestCaseController(ITestCaseService testCaseService, ITestSuiteService testSuiteService)
        {
            _testCaseService = testCaseService;
            _testSuiteService = testSuiteService;
        }

        public ITestCaseService _testCaseService { get; private set; }
        public ITestSuiteService _testSuiteService {get; private set; }


        // GET: /manage/testcases
        // Called when page is firstly loaded, e.g. navigated from another panel in menu
        public ActionResult Index()
        {
            var model = Mapper.Map<IEnumerable<TestCase>, IEnumerable<ListTestCasesViewModel>>(_testCaseService.ListTestCases());

            return View(model);
        }


        // GET: /manage/testcases
        // Called when user selects some test case from the list of test cases
        [Route("{externalID}")]
        public ActionResult Index(string externalID)
        {
            TestCase selectedTestCase = null;

            if (!string.IsNullOrEmpty(externalID))
            {
                var internalID = _testCaseService.ConvertFromExternalID(externalID);
                ViewBag.TestCaseID = internalID;
                selectedTestCase = _testCaseService.GetTestCase(internalID);
                ViewBag.SelectedTestSuiteID = selectedTestCase.TestSuiteID;
            }

            var model = Mapper.Map<IEnumerable<TestCase>, IEnumerable<ListTestCasesViewModel>>(_testCaseService.ListTestCases(selectedTestCase.TestSuiteID));

            return View(model);
        }


        // POST: /manage/testcases 
        // Called when user changes the test suite from a dropdown
        [HttpPost, Route("{externalID?}")]
        public ActionResult Index(SelectTestSuiteViewModel testSuite)
        {
            var model = Mapper.Map<IEnumerable<TestCase>, IEnumerable<ListTestCasesViewModel>>(_testCaseService.ListTestCases(testSuite.SelectedTestSuiteID));

            ViewBag.SelectedTestSuiteID = testSuite.SelectedTestSuiteID;

            return View(model);
        }


        // Called from within the Index view, populates the left panel with infromation about test case
        [ChildActionOnly]
        public ActionResult TestCaseDetailsWidget(int? testCaseID)
        {
            DisplayTestCaseViewModel model = null;

            if(testCaseID.HasValue)
            { 
                var id = (int)testCaseID;
                model = Mapper.Map<TestCase, DisplayTestCaseViewModel>(_testCaseService.GetTestCase(id));
            }
            return PartialView("_TestCaseDetailsPartial", model);
        }


        // Called from within the Index view, populates the dropdown with test suites
        [ChildActionOnly]
        public ActionResult ProjectTestSuitesWidget(int? selectedTestSuiteID)
        {
            ViewBag.SelectedTestSuite = selectedTestSuiteID;

            var model = Mapper.Map<IEnumerable<TestSuite>, IEnumerable<SelectTestSuiteViewModel>>(_testSuiteService.ListTestSuites());

            return PartialView("_ProjectsTestSuitesPartial", model);
        }


        // GET: manage/testcases/new
        [HttpGet, Authorize, Route("new")]
        public ActionResult New(int? selectTestSuiteID)
        {
            var testSuites = _testSuiteService.ListTestSuites().Select(r => new SelectListItem { Value = r.ID.ToString(), Text = r.Name });

            var model = new NewTestCaseViewModel { TestSuites = new SelectList(testSuites, "Value", "Text") };
            
            return View(model);
        }


        // POST: manage/testcases/new
        [HttpPost, Authorize, ValidateAntiForgeryToken, Route("new")]
        public async Task<ActionResult> New(NewTestCaseViewModel viewModel)
        {
            if (!ModelState.IsValid) return View(viewModel);
            
            var testCase = Mapper.Map<NewTestCaseViewModel, TestCase>(viewModel);

            await _testCaseService.CreateTestCase(testCase, User.Identity.GetUserId());

            // return RedirectToAction("Index", new { testCase.ExternalID });
            return RedirectToAction("Details", new { testCase.ExternalID });
        }


        // GET: manage/testcases/new
        [HttpGet, Authorize, Route("steps/{externalID}")]
        public ActionResult Details(string externalID)
        {
            var internalID = _testCaseService.ConvertFromExternalID(externalID);
            var selectedTestCase = _testCaseService.GetTestCase(internalID);
            var testCaseToAddStepsTo = Mapper.Map<TestCase, DisplayTestCaseViewModel>(selectedTestCase);

            return View(testCaseToAddStepsTo);
        }


        // Called from within the Details view, displays form to add step and result
        [ChildActionOnly]
        public ActionResult AddStepsWidget()
        {
            return PartialView("_TestCaseStepsPartial");
        }


        // Called from within the Details view, submits form with step and result info
        [HttpPost, Authorize, Route("steps/{externalID}/add")]
        public async Task<ActionResult> AddSteps(AddStepsToTestCaseViewModel model)
        {
            var step = Mapper.Map<AddStepsToTestCaseViewModel, StepResultDefinition>(model);

            await _testCaseService.AddStepToTestCase(step, 1);

            return PartialView("_TestCaseStepsPartial");
        }
	}
}