﻿using System.Collections.Generic;
using System.Linq;
using Facility.Definition.Swagger;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Shouldly;

namespace Facility.Definition.UnitTests.Swagger
{
	[TestFixture]
	public class ComplexSwaggerTests
	{
		[Test]
		public void GenerateComplexService()
		{
			var generator = new SwaggerGenerator { GeneratorName = "tests" };
			var output = generator.GenerateOutput(TestUtility.ParseTestApi(s_fsdText));
			var namedText = output.NamedTexts.Single();
			namedText.Name.ShouldBe("swagger.json");
			var jToken = JToken.Parse(namedText.Text);
			var jTokenExpected = JToken.FromObject(s_swaggerService, JsonSerializer.Create(SwaggerUtility.JsonSerializerSettings));
			JToken.DeepEquals(jToken, jTokenExpected).ShouldBe(true);
		}

		readonly string s_fsdText = @"
/// test service
[info(version: 1.2.3), http(url: ""https://example.com/v3"")]
service TestApi
{
	/// do!
	[http(method: POST, path: ""/do/{id}"", code: 201)]
	method do
	{
		/// path!
		id: int64;

		/// query!
		[http(from: query, name: q)] query: string;

		/// field!
		field: boolean;
	}:
	{
		/// id!
		id: string;

		/// job!
		[http(from: body, code: 202)]
		job: Job;

		/// no ID!
		[http(from: body, code: 204)]
		noId: boolean;
	}

	method kill
	{
		/// job!
		[http(from: body)] job: Job;
	}:
	{
	}

	/// job data
	data Job
	{
		jobId: string;
	}
}

# TestApi

These are the service remarks.

They are multi-line.
";

		readonly SwaggerService s_swaggerService = new SwaggerService
		{
			Swagger = "2.0",
			Info = new SwaggerInfo
			{
				Title = "test service",
				Description = "These are the service remarks.\n\nThey are multi-line.",
				Version = "1.2.3",
				Identifier = "TestApi",
				CodeGen = "DO NOT EDIT: generated by tests",
			},
			Host = "example.com",
			BasePath = "/v3",
			Schemes = new[] { "https" },
			Paths = new Dictionary<string, SwaggerOperations>
			{
				["/do/{id}"] = new SwaggerOperations
				{
					Post = new SwaggerOperation
					{
						Summary = "do!",
						OperationId = "do",
						Consumes = new[] { "application/json" },
						Produces = new[] { "application/json" },
						Parameters = new[]
						{
							new SwaggerParameter
							{
								In = SwaggerParameterKind.Path,
								Name = "id",
								Description = "path!",
								Required = true,
								Type = SwaggerSchemaType.Integer,
								Format = SwaggerSchemaTypeFormat.Int64,
							},
							new SwaggerParameter
							{
								In = SwaggerParameterKind.Query,
								Name = "q",
								Description = "query!",
								Required = false,
								Type = SwaggerSchemaType.String,
								Identifier = "query",
							},
							new SwaggerParameter
							{
								In = SwaggerParameterKind.Body,
								Name = "request",
								Required = true,
								Schema = new SwaggerSchema
								{
									Ref = "#/definitions/DoRequest",
								}
							},
						},
						Responses = new Dictionary<string, SwaggerResponse>
						{
							["201"] = new SwaggerResponse
							{
								Schema = new SwaggerSchema
								{
									Ref = "#/definitions/DoResponse",
								}
							},
							["202"] = new SwaggerResponse
							{
								Description = "job!",
								Schema = new SwaggerSchema
								{
									Ref = "#/definitions/Job",
								},
								Identifier = "job",
							},
							["204"] = new SwaggerResponse
							{
								Description = "no ID!",
								Identifier = "noId",
							},
						},
					}
				},
				["/kill"] = new SwaggerOperations
				{
					Post = new SwaggerOperation
					{
						OperationId = "kill",
						Consumes = new[] { "application/json" },
						Parameters = new[]
						{
							new SwaggerParameter
							{
								In = SwaggerParameterKind.Body,
								Name = "request",
								Description = "job!",
								Required = true,
								Schema = new SwaggerSchema
								{
									Ref = "#/definitions/Job",
								}
							},
						},
						Responses = new Dictionary<string, SwaggerResponse>
						{
							["204"] = new SwaggerResponse(),
						},
					}
				},
			},
			Definitions = new Dictionary<string, SwaggerSchema>
			{
				["Job"] = new SwaggerSchema
				{
					Type = SwaggerSchemaType.Object,
					Description = "job data",
					Properties = new Dictionary<string, SwaggerSchema>
					{
						["jobId"] = new SwaggerSchema
						{
							Type = SwaggerSchemaType.String,
						},
					}
				},
				["DoRequest"] = new SwaggerSchema
				{
					Type = SwaggerSchemaType.Object,
					Description = "The request body for do.",
					Properties = new Dictionary<string, SwaggerSchema>
					{
						["field"] = new SwaggerSchema
						{
							Description = "field!",
							Type = SwaggerSchemaType.Boolean,
						}
					},
				},
				["DoResponse"] = new SwaggerSchema
				{
					Type = SwaggerSchemaType.Object,
					Description = "The response body for do.",
					Properties = new Dictionary<string, SwaggerSchema>
					{
						["id"] = new SwaggerSchema
						{
							Description = "id!",
							Type = SwaggerSchemaType.String,
						}
					},
				},
			},
		};
	}
}
