using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matching;

namespace zero.Routing;

// see https://github.com/umbraco/Umbraco-CMS/blob/5bfab13dc5a268714aad2426a2b68ab5561a6407/src/Umbraco.Web.Website/Routing/NotFoundSelectorPolicy.cs

/// <summary>
/// Used to handle 404 routes that haven't been handled by the end user
/// </summary>
public class NotFoundSelectorPolicy : MatcherPolicy, IEndpointSelectorPolicy
{
  //private readonly Lazy<Endpoint> _notFound;
  private readonly EndpointDataSource _endpointDataSource;

  public NotFoundSelectorPolicy(EndpointDataSource endpointDataSource)
  {
    //_notFound = new Lazy<Endpoint>(GetNotFoundEndpoint);
    _endpointDataSource = endpointDataSource;
  }

  // return the endpoint for the RenderController.Index action.
  //private Endpoint GetNotFoundEndpoint()
  //{
  //  Endpoint e = _endpointDataSource.Endpoints.First(x =>
  //  {
  //    // return the endpoint for the RenderController.Index action.
  //    ControllerActionDescriptor descriptor = x.Metadata?.GetMetadata<ControllerActionDescriptor>();
  //    return descriptor?.ControllerTypeInfo == typeof(RenderController)
  //        && descriptor?.ActionName == nameof(RenderController.Index);
  //  });
  //  return e;
  //}

  public override int Order => 0;

  public bool AppliesToEndpoints(IReadOnlyList<Endpoint> endpoints)
  {
    // Don't apply this filter to any endpoint group that is a controller route
    // i.e. only dynamic routes.
    foreach (Endpoint endpoint in endpoints)
    {
      ControllerAttribute controller = endpoint.Metadata?.GetMetadata<ControllerAttribute>();
      if (controller != null)
      {
        return false;
      }
    }

    // then ensure this is only applied if all endpoints are IDynamicEndpointMetadata
    return endpoints.All(x => x.Metadata?.GetMetadata<IDynamicEndpointMetadata>() != null);
  }

  public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates)
  {
    if (AllInvalid(candidates))
    {
      //UmbracoRouteValues umbracoRouteValues = httpContext.Features.Get<UmbracoRouteValues>();
      //if (umbracoRouteValues?.PublishedRequest != null
      //    && !umbracoRouteValues.PublishedRequest.HasPublishedContent()
      //    && umbracoRouteValues.PublishedRequest.ResponseStatusCode == StatusCodes.Status404NotFound)
      //{
      //  // not found/404
      //  httpContext.SetEndpoint(_notFound.Value);
      //}
    }

    return Task.CompletedTask;
  }

  private static bool AllInvalid(CandidateSet candidates)
  {
    for (int i = 0; i < candidates.Count; i++)
    {
      if (candidates.IsValidCandidate(i))
      {
        return false;
      }
    }
    return true;
  }
}
