﻿using System;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;

public class PlayerBuilder : MonoBehaviour
{
	[SerializeField] BattleManager _battleManager;

	Models[] _allModels;
	List<PlayerData> _newPlayers = new();
	const string _classPrefix = "class";
	const string _pledgePrefix = "pledge";

	void Awake() => _allModels ??= Enum.GetValues(typeof(Models)).Cast<Models>().ToArray();

	void Start()
	{
		var playerEntries = BattleManager.Settings.TestPlayers;
		if (playerEntries)
			playerEntries.RegisterPlayers(this);
	}

	public void ProcessBuildFromText(string playerName, string message)
	{
		var formattedMessage = message.ToLowerInvariant();
		bool selectedModel = TryGetModelToUse(formattedMessage, out var model);
		bool picked = false;
		// if (!selectedModel)
		// {
		// 	Debug.Log($"Player didn't choose a model {playerName}");
		// 	return;
		// }

		
		//
		 // if (selectedModel)
		 // 	playerData.SetModel(model);
		PlayerData playerData = null;
		if (TryGetSpeciesToUseLoose(formattedMessage, out var raceAspect))
		{
			playerData = GetOrAddPlayer(playerName);
			playerData.SetSpecies(raceAspect);
			picked = true;
		}

		if (TryGetProfessionToUseLoose(formattedMessage, out var classAspect))
		{
			playerData = GetOrAddPlayer(playerName);
			playerData.SetClass(classAspect);
			picked = true;
		}

		if (TryGetPledgeToUseLoose(formattedMessage, out Pledge aspect))
		{
			playerData = GetOrAddPlayer(playerName);
			playerData.SetPledgeAspect(aspect);
		}

		if (picked)
		{
			if (selectedModel || classAspect != null)
			{
				ActionLogText.Add(playerName,
					$" is a <color=#{playerData.Profession.DisplayColor.ToHexString()}>{playerData.Profession.DisplayName} {playerData.ModelName}</color>");
				_newPlayers.Add(playerData);
			}
		}
	}

	public PlayerData GetOrAddPlayer(string requestToParse)
	{
		var playerName = requestToParse;
		
		var playerData = Players.Get(playerName);
		_battleManager.AddToContest(playerName);
		PlayerManager.Instance.Get(playerName);

		return playerData;
	}

	void Update()
	{
		if (_newPlayers.Any())
		{
			foreach (var player in _newPlayers)
			{
				if (player.Battler == null)
				{
					return;
					Debug.LogError($"Failed to initialize player {player.PlayerName}");
					continue;
				}
				player.Battler.UpdatePlayerSpecies();
				player.Battler.UpdatePlayerClass();
//				Debug.LogError($"Intialized {player.PlayerName}");
			}
			_newPlayers.Clear();
		}
	}

	bool TryGetPledgeToUseLoose(string lowercaseMessage, out Pledge pledgeAspect)
	{
		pledgeAspect = default;
		foreach (var aspect in Aspects.Pledges)
		{
			if (lowercaseMessage.Contains(aspect.name.ToLowerInvariant()))
			{
				pledgeAspect = aspect;
				return true;
			}
		}

		return false;
	}
	
	private bool TryGetPledgeToUse(string lowercaseMessage, out Pledge apsect)
	{
		apsect = default;

		if (!lowercaseMessage.StartsWith(_pledgePrefix))
			return false;

		var contentsWithoutPrefix = lowercaseMessage.Substring(_pledgePrefix.Length).Trim();
		var allPledges = Aspects.Pledges;

		for (int i = 0; i < allPledges.Length; i++)
		{
			var pledgeToCheck = allPledges[i];
			if (!pledgeToCheck.IsValidForText(contentsWithoutPrefix))
				continue;

			apsect = pledgeToCheck;
			return true;
		}

		return false;
	}

	bool TryGetProfessionToUseLoose(string lowercaseMessage, out Profession classAspect)
	{
		classAspect = default;
		foreach (var aspect in Aspects.Classes)
		{
			if (lowercaseMessage.Contains(aspect.name.ToLowerInvariant()))
			{
				classAspect = aspect;
				return true;
			}
		}

		return false;
	}
	
	bool TryGetSpeciesToUseLoose(string lowercaseMessage, out Species speciesAspect)
	{
		speciesAspect = default;
		foreach (var aspect in Aspects.Species)
		{
			if (lowercaseMessage.Contains(aspect.name.ToLowerInvariant()))
			{
				speciesAspect = aspect;
				return true;
			}
		}

		return false;
	}

	private bool TryGetClassToUse(string lowercaseMessage, out Profession classAspect)
	{
		classAspect = default;
		
		if (!lowercaseMessage.StartsWith(_classPrefix))
			return false;

		var contentsWithoutPrefix = lowercaseMessage.Substring(_classPrefix.Length).Trim();
		var allClasses = Aspects.Classes;
		
		for (int classIndex = 0; classIndex < allClasses.Length; classIndex++)
		{
			var classToCheck = allClasses[classIndex];
			if (!classToCheck.IsValidForText(contentsWithoutPrefix))
				continue;

			classAspect = classToCheck;
			return true;
		}

		return false;
	}
	
	bool TryGetModelToUseLoose(string lowercaseMessage, out Models model)
	{
		model = default;

		foreach (var modelToCheck in _allModels)
		{
			if (lowercaseMessage.Contains(modelToCheck.ToString().ToLowerInvariant()))
			{
				model = modelToCheck;
				return true;
			}
		}
		
		return false;
	}
	
	bool TryGetModelToUse(string lowercaseMessage, out Models model)
	{
		model = default;

		foreach (var modelToCheck in _allModels)
		{
			foreach (var word in lowercaseMessage.Split(' '))
			{
				if (modelToCheck.ToString().ToLowerInvariant() == word)
				{
					model = modelToCheck;
					return true;
				}
			}
		}
		
		return false;
	}

}