using Coscine.Api.Resources.ParameterObjects;
using Coscine.ResourceTypes.GitLab.Helpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Coscine.Api.Resources.Controllers
{
    /// <summary>
    /// This controller represents the additional actions which can be taken with a GitLab resource .
    /// </summary>
    [Authorize]
    public class GitLabController : Controller
    {
        /// <summary>
        /// ResourceController constructor specifying a ResourceModel.
        /// </summary>
        public GitLabController()
        { }

        /// <summary>
        /// Returns all GitLab projects, that the user is a member of, based on the provided credentials.
        /// </summary>
        /// <param name="gitlabCredentials">GitLab Credentials</param>
        /// <returns>List of GitLab project objects if OK, 204 if empty, 401 if token invalid, 500 if any other problem</returns>
        [HttpGet("[controller]/projects")]
        public async Task<ActionResult<IEnumerable<GitLabApiClient.Models.Projects.Responses.Project>>> GetAllProjectsAsync([FromQuery] GitlabCredentialsObject gitlabCredentials)
        {
            if (!Uri.IsWellFormedUriString(gitlabCredentials.Domain.OriginalString, UriKind.Absolute))
            {
                return BadRequest("Provided GitLab Domain is not absolute. Make sure the URL contains the entire address of the page (https:// or  http://)");
            }
            try
            {
                var projects = await Helper.GetAllProjects(gitlabCredentials.Domain, gitlabCredentials.AccessToken);

                if (projects is null)
                {
                    return NoContent();
                }
                return Ok(projects);
            }
            catch (Exception e)
            {
                if (e.Message.Contains("401"))
                {
                    return Unauthorized("Invalid GitLab token");
                }
                return Problem($"A problem occured during the communicaiton with GitLab", null, 500);
            }
        }

        /// <summary>
        /// Returns a single GitLab project, that the user is a member of, based on the provided credentials.
        /// </summary>
        /// <param name="projectId">GitLab Project Identifier</param>
        /// <param name="gitlabCredentials">GitLab Credentials</param>
        /// <returns>GitLab project object if OK, 204 if empty, 401 if token invalid, 500 if any other problem</returns>
        [HttpGet("[controller]/projects/{projectId}")]
        public async Task<ActionResult<GitLabApiClient.Models.Projects.Responses.Project>> GetProjectAsync(int projectId, [FromQuery] GitlabCredentialsObject gitlabCredentials)
        {
            if (!Uri.IsWellFormedUriString(gitlabCredentials.Domain.OriginalString, UriKind.Absolute))
            {
                return BadRequest("Provided GitLab Domain is not absolute. Make sure the URL contains the entire address of the page (https:// or  http://)");
            }
            try
            {
                var project = await Helper.GetProject(gitlabCredentials.Domain, gitlabCredentials.AccessToken, projectId);

                if (project is not null)
                {
                    return Ok(project);
                }
            }
            catch (Exception e)
            {
                if (e.Message.Contains("401"))
                {
                    return Unauthorized("Invalid GitLab token");
                }
                return Problem($"A problem occured during the communicaiton with GitLab", null, 500);
            }
            return BadRequest("GitLab Project could not be found based on your access rights. Check your domain or consider using a different access token.");
        }

        /// <summary>
        /// Returns all GitLab branches of a project, that the user is a member of, based on the provided credentials.
        /// </summary>
        /// <param name="projectId">GitLab Project Identifier</param>
        /// <param name="gitlabCredentials">GitLab Credentials</param>
        /// <returns>List of GitLab branch objects if OK, 204 if empty, 401 if token invalid, 500 if any other problem</returns>
        [HttpGet("[controller]/branches/{projectId}")]
        public async Task<ActionResult<IEnumerable<GitLabApiClient.Models.Branches.Responses.Branch>>> GetBranchesForProjectAsync(int projectId, [FromQuery] GitlabCredentialsObject gitlabCredentials)
        {
            if (!Uri.IsWellFormedUriString(gitlabCredentials.Domain.OriginalString, UriKind.Absolute))
            {
                return BadRequest("Provided GitLab Domain is not absolute. Make sure the URL contains the entire address of the page (https:// or  http://)");
            }
            try
            {
                var branches = await Helper.GetBranchesForProject(gitlabCredentials.Domain, gitlabCredentials.AccessToken, projectId);

                if (branches is null)
                {
                    return NoContent();
                }
                return Ok(branches);
            }
            catch (Exception e)
            {
                if (e.Message.Contains("401"))
                {
                    return Unauthorized("Invalid GitLab token");
                }
                return Problem($"A problem occured during the communicaiton with GitLab", null, 500);
            }
        }
    }
}