using Core.Entities;
using FuzzySharp;

namespace Core.Parsers;

public class StudentParser : CsvParserBase
{
    public StudentParser(FileSystemInfo csvFile, bool ignoreBlankLines = true) : base(csvFile, ignoreBlankLines)
    {
    }

    public Student[] Parse(ICollection<CompetitiveEvent> events)
    {
        var s = new List<Student>();

        CsvReader.Read();
        CsvReader.ReadHeader();

		while (CsvReader.Read())
		{
			var name = CsvReader.GetField("Student Name");
			if (string.IsNullOrEmpty(name))
				continue;

			var stateID = CsvReader.GetField("State ID").Trim();
			var regionalID = CsvReader.GetField("Regional ID").Trim();
			var nationalID = CsvReader.GetField("National ID").Trim();
			var gr = CsvReader.GetField("Grade");
			var tsaYearsStr = CsvReader.GetField("TSA year");
			var tsaYear = int.Parse(tsaYearsStr?[..1] ?? "1");
			var officer = CsvReader.GetField("Officer");

			var competitiveEvents = new List<CompetitiveEvent>(6);

            for (var i = 1; i <= 6; i++)
            {
	            var eventName = CsvReader.GetField(i.ToString());
	            if (string.IsNullOrEmpty(eventName) || eventName == "") continue;

	            eventName = eventName.Trim();

	            if (eventName == "I&I")
		            eventName = "Inventions & Innovations";
	            if (eventName == "Med Tech")
		            eventName = "Medical Technology";
	            if (eventName.StartsWith("Challenging Tech"))
		            eventName = "Challenging Technology Issues";

                var matches =
	                (from e in events
	                let rat = Fuzz.Ratio(e.Name, eventName)
	                where rat > 90
	                orderby rat descending 
	                select e).ToList();

                if (!matches.Any())
                {
	                matches =
		                (from e in events
			                where e.Name.StartsWith(eventName)
			                select e).ToList();
                }

                var competitiveEvent = matches.FirstOrDefault();
                if (competitiveEvent == null)
                {
					
	                //todo: throw new ArgumentException($"Event named '{eventName}' not found");
	                continue;
                }

                competitiveEvents.Add(competitiveEvent);
            }

            if (!competitiveEvents.Any())
	            continue;

			var student = new Student(
				name.Trim(),
				Convert.ToInt32(gr),
				tsaYear,
				officer?.Trim(),
                competitiveEvents, stateID, regionalID, nationalID);
            s.Add(student);
		}

        return s.ToArray();
    }
}