using System.Globalization;
using System.Text.RegularExpressions;
using CSharpFunctionalExtensions;
using Forwarder.Domain;
using Serilog;
using Serilog.Filters;

namespace Forwarder.Modules.Ademco;

internal partial class Ademco685MessageParser
{
	public record Output(bool IsTest, Message? Message);

	private readonly Regex _messageTemplate = RealMessagePattern();
	private readonly Regex _testTemplate = TestMessagePattern();

	public Result<Output> Parse(string input)
	{
		// [LF]RLsAAAAs18sQXYZsGGsUCCC[CR]
		if (_testTemplate.IsMatch(input))
		{
			return Result.Success(new Output(true, null));
		}

		var matching = _messageTemplate.Match(input);
		if (!matching.Success)
		{
			return Result.Failure<Output>("Not matched");
		}

		return Result.Success(
			new Output(
				false,
				new Message(
					Guid.CreateVersion7(),
					int.Parse(matching.Groups["receiver"].Value),
					int.Parse(matching.Groups["line"].Value),
					ConvertAbonent(matching.Groups["abonent"].Value),
					//$"1{matching.Groups["abonent"].Value:D15}",
					GetMessageType(matching.Groups["type"].Value),
					int.Parse(matching.Groups["code"].Value),
					int.Parse(matching.Groups["area"].Value),
					int.Parse(matching.Groups["zone"].Value),
					DateTime.UtcNow
				)
			)
		);
	}

	private static string ConvertAbonent(string value)
	{
		var hex = int.Parse(value, NumberStyles.HexNumber);
		Log.Information("Abonent: 0x{Hex} ({Decimal})", hex, value);
		return $"{hex:D8}";
	}

	private static MessageType GetMessageType(string s)
	{
		return s switch
		{
			"E" => MessageType.AlarmDisarming,
			"R" => MessageType.RecoveryArming,
			"P" => MessageType.StatePing,
			_ => MessageType.Unknown,
		};
	}

	[GeneratedRegex(
		@"(?<receiver>\d{1})(?<line>\d{1})\s{1}(?<abonent>\d{4})\s{1}18\s{1}(?<type>\w{1})(?<code>\d{3})\s{1}(?<area>\d{2})\s{1}(\w{1})(?<zone>\d{3})"
	)]
	private static partial Regex RealMessagePattern();

	[GeneratedRegex(@"(\d{2})\s{1}OKAY\s{1}@")]
	private static partial Regex TestMessagePattern();
}
