using System;
using System.Collections.Generic;
using System.Linq;

namespace AxCopilot.Services;

public static class DiffService
{
	public enum DiffType
	{
		Equal,
		Added,
		Removed
	}

	public record DiffLine(DiffType Type, int? OldLineNo, int? NewLineNo, string Content);

	public static List<DiffLine> ComputeDiff(string oldText, string newText)
	{
		string[] array = (oldText ?? "").Split('\n');
		string[] array2 = (newText ?? "").Split('\n');
		List<DiffLine> list = new List<DiffLine>();
		List<string> list2 = ComputeLcs(array, array2);
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		while (num < array.Length || num2 < array2.Length)
		{
			if (num3 < list2.Count && num < array.Length && num2 < array2.Length && array[num].TrimEnd('\r') == list2[num3] && array2[num2].TrimEnd('\r') == list2[num3])
			{
				list.Add(new DiffLine(DiffType.Equal, num + 1, num2 + 1, array[num].TrimEnd('\r')));
				num++;
				num2++;
				num3++;
				continue;
			}
			if (num3 < list2.Count && num < array.Length && array[num].TrimEnd('\r') != list2[num3])
			{
				list.Add(new DiffLine(DiffType.Removed, num + 1, null, array[num].TrimEnd('\r')));
				num++;
				continue;
			}
			if (num2 < array2.Length && (num3 >= list2.Count || array2[num2].TrimEnd('\r') != list2[num3]))
			{
				list.Add(new DiffLine(DiffType.Added, null, num2 + 1, array2[num2].TrimEnd('\r')));
				num2++;
				continue;
			}
			if (num < array.Length)
			{
				list.Add(new DiffLine(DiffType.Removed, num + 1, null, array[num].TrimEnd('\r')));
				num++;
			}
			if (num2 < array2.Length)
			{
				list.Add(new DiffLine(DiffType.Added, null, num2 + 1, array2[num2].TrimEnd('\r')));
				num2++;
			}
		}
		return list;
	}

	private static List<string> ComputeLcs(string[] a, string[] b)
	{
		int num = a.Length;
		int num2 = b.Length;
		int[,] array = new int[num + 1, num2 + 1];
		for (int i = 1; i <= num; i++)
		{
			for (int j = 1; j <= num2; j++)
			{
				array[i, j] = ((a[i - 1].TrimEnd('\r') == b[j - 1].TrimEnd('\r')) ? (array[i - 1, j - 1] + 1) : Math.Max(array[i - 1, j], array[i, j - 1]));
			}
		}
		List<string> list = new List<string>();
		int num3 = num;
		int num4 = num2;
		while (num3 > 0 && num4 > 0)
		{
			if (a[num3 - 1].TrimEnd('\r') == b[num4 - 1].TrimEnd('\r'))
			{
				list.Add(a[num3 - 1].TrimEnd('\r'));
				num3--;
				num4--;
			}
			else if (array[num3 - 1, num4] > array[num3, num4 - 1])
			{
				num3--;
			}
			else
			{
				num4--;
			}
		}
		list.Reverse();
		return list;
	}

	public static string GetSummary(List<DiffLine> diff)
	{
		int value = diff.Count((DiffLine d) => d.Type == DiffType.Added);
		int value2 = diff.Count((DiffLine d) => d.Type == DiffType.Removed);
		return $"+{value} -{value2} 라인 변경";
	}
}
