using System.Net;
using System.Net.Mime;
using Iceshrimp.Backend.Controllers.Federation.Attributes;
using Iceshrimp.Backend.Controllers.Shared.Attributes;
using Iceshrimp.Backend.Core.Configuration;
using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Extensions;
using Iceshrimp.Backend.Core.Federation.WebFinger;
using Iceshrimp.Backend.Core.Services;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace Iceshrimp.Backend.Controllers.Federation;

[FederationApiController]
[Route("/nodeinfo")]
[EnableCors("well-known")]
[Produces(MediaTypeNames.Application.Json)]
public class NodeInfoController(
	IOptions<Config.InstanceSection> instanceConfig,
	IOptions<Config.StorageSection> storageConfig,
	DatabaseContext db,
	MetaService meta
) : ControllerBase
{
	[HttpGet("2.1")]
	[HttpGet("2.0")]
	[ProducesResults(HttpStatusCode.OK)]
	public async Task<NodeInfoResponse> GetNodeInfo()
	{
		var cutoffMonth    = DateTime.UtcNow - TimeSpan.FromDays(30);
		var cutoffHalfYear = DateTime.UtcNow - TimeSpan.FromDays(180);
		var instance       = instanceConfig.Value;
		var totalUsers =
			await db.Users.LongCountAsync(p => p.IsLocalUser && !Constants.SystemUsers.Contains(p.UsernameLower));
		var activeMonth =
			await db.Users.LongCountAsync(p => p.IsLocalUser &&
			                                   !Constants.SystemUsers.Contains(p.UsernameLower) &&
			                                   p.LastActiveDate > cutoffMonth);
		var activeHalfYear =
			await db.Users.LongCountAsync(p => p.IsLocalUser &&
			                                   !Constants.SystemUsers.Contains(p.UsernameLower) &&
			                                   p.LastActiveDate > cutoffHalfYear);
		var localPosts    = await db.Notes.LongCountAsync(p => p.UserHost == null);
		var maxUploadSize = storageConfig.Value.MaxUploadSizeBytes;

		var (instanceName, instanceDescription, adminContact) =
			await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription,
			                        MetaEntity.AdminContactEmail);
		
		return new NodeInfoResponse
		{
			Version = Request.Path.Value?.EndsWith("2.1") ?? false ? "2.1" : "2.0",
			Software = new NodeInfoResponse.NodeInfoSoftware
			{
				Name     = "Iceshrimp.NET",
				Version  = instance.Version,
				Codename = instance.Codename,
				Edition  = instance.Edition,
				Homepage = new Uri(Constants.ProjectHomepageUrl),
				Repository = Request.Path.Value?.EndsWith("2.1") ?? false
					? new Uri(Constants.RepositoryUrl)
					: null
			},
			Protocols = ["activitypub"],
			Services  = new NodeInfoResponse.NodeInfoServices { Inbound = [], Outbound = ["atom1.0", "rss2.0"] },
			Usage = new NodeInfoResponse.NodeInfoUsage
			{
				//FIXME Implement members
				Users = new NodeInfoResponse.NodeInfoUsers
				{
					Total          = totalUsers,
					ActiveMonth    = activeMonth,
					ActiveHalfYear = activeHalfYear
				},
				LocalComments = 0,
				LocalPosts    = localPosts
			},
			Metadata = new NodeInfoResponse.NodeInfoMetadata
			{
				//FIXME Implement members
				NodeName                   = instanceName,
				NodeDescription            = instanceDescription,
				Maintainer                 = new NodeInfoResponse.Maintainer { Name = "todo", Email = adminContact },
				Languages                  = [],
				TosUrl                     = "todo",
				RepositoryUrl              = new Uri(Constants.RepositoryUrl),
				FeedbackUrl                = new Uri(Constants.IssueTrackerUrl),
				ThemeColor                 = "#000000",
				DisableRegistration        = true,
				DisableLocalTimeline       = false,
				DisableRecommendedTimeline = false,
				DisableGlobalTimeline      = false,
				EmailRequiredForSignup     = false,
				PostEditing                = false,
				PostImports                = false,
				EnableHCaptcha             = false,
				EnableRecaptcha            = false,
				MaxNoteTextLength          = 0,
				MaxCaptionTextLength       = 0,
				EnableGithubIntegration    = false,
				EnableDiscordIntegration   = false,
				EnableEmail                = false,
				PublicTimelineVisibility = new NodeInfoResponse.PleromaPublicTimelineVisibility
				{
					Bubble    = false,
					Federated = false,
					Local     = false
				},
				// @formatter:off
				UploadLimits = new NodeInfoResponse.PleromaUploadLimits
				{
					General    = maxUploadSize,
					Avatar     = maxUploadSize,
					Background = maxUploadSize,
					Banner     = maxUploadSize
				},
				// @formatter:on
				Suggestions = new NodeInfoResponse.PleromaSuggestions { Enabled = false },
				Federation  = new NodeInfoResponse.PleromaFederation { Enabled  = true }
			},
			OpenRegistrations = false
		};
	}

	[HttpGet("2.0.json")]
	public IActionResult GetNodeInfoAkkoma()
	{
		return Redirect("/nodeinfo/2.0");
	}
}