using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NuGet.Versioning;
using isnd.Data;
using isnd.Entities;
using Unleash;
using isnd.Services;
using isnd.ViewModels;
using System.Threading.Tasks;
using isnd.Interfaces;
using isn.Abstract;

namespace isnd.Controllers
{
    [AllowAnonymous]
    public partial class PackagesController : Controller
    {
        const int maxTake = 100;

        const string defaultSemVer = "2.0.0";
        private readonly Resource[] _resources;
        private readonly ILogger<PackagesController> _logger;
        private readonly IDataProtector _protector;

        private readonly IsndSettings _isndSettings;
        readonly ApplicationDbContext _dbContext;
        private readonly IPackageManager _packageManager;
        private readonly IUnleash _unleashĈlient;
        const string _pkgRootPrefix = "~/";

        public PackagesController(
            ILoggerFactory loggerFactory,
            IDataProtectionProvider provider,
            IOptions<IsndSettings> isndOptions,
            IUnleash unleashĈlient,
            ApplicationDbContext dbContext,
            IPackageManager pm)
        {
            _logger = loggerFactory.CreateLogger<PackagesController>();
            _isndSettings = isndOptions.Value;
            _protector = provider.CreateProtector(_isndSettings.ProtectionTitle);
            _dbContext = dbContext;
            _packageManager = pm;
            _unleashĈlient = unleashĈlient;
            _resources = _packageManager.GetResources(_unleashĈlient).ToArray();
        }

        [HttpGet(_pkgRootPrefix + ApiConfig.Base)]
        public IActionResult ApiIndex()
        {
            return Ok(new ApiIndexViewModel{ Version = "3.0.0", Resources = _resources });
        }

        // GET /autocomplete?id=isn.protocol&prerelease=true
        [HttpGet(_pkgRootPrefix + ApiConfig.AutoComplete)]
        public IActionResult AutoComplete(
            string id,
            string semVerLevel,
            bool prerelease = false,
            string packageType = null,
            int skip = 0,
            int take = 25)
        {
            if (take > maxTake)
            {
                ModelState.AddModelError("take", "Maximum exceeded");
                return BadRequest(ModelState);
            }
            if (semVerLevel != defaultSemVer)
            {
                ModelState.AddModelError("semVerLevel", defaultSemVer + " expected");
            }
            
            return Ok(_packageManager.AutoComplete(id,skip,take,prerelease,packageType));
        }
        // TODO GET {@id}/{LOWER_ID}/index.json 
        // LOWER_ID 	URL 	string 	yes 	The package ID, lowercased
        // response : versions 	array of strings 	yes 	The versions available
        [HttpGet(_pkgRootPrefix + ApiConfig.Get + "/{id}/{lower}/index.json")]
        public IActionResult GetVersions(
            string id,
            string lower,
            bool prerelease = false,
            string packageType = null,
            int skip = 0,
            int take = 25)
        {
            if (take > maxTake)
            {
                ModelState.AddModelError("take", "Maximum exceeded");
            }
            // NugetVersion
            if (!NuGetVersion.TryParse(lower, out NuGetVersion parsedVersion))
            {
                ModelState.AddModelError("lower", "invalid version string");
            }
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            return Ok(new
            {
                versions = _packageManager.GetVersions(
                    id, parsedVersion, prerelease, packageType, skip, take)
            });
        }
    }
}