using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// Simple standalone team placement script that randomly places the team on a settlement
/// and creates a visible marker in front of the map.
/// </summary>
public class SimpleTeamPlacement : MonoBehaviour
{
    [Header("Team Marker Settings")]
    public GameObject teamMarkerPrefab;
    public Material teamMarkerMaterial;
    [Range(0.5f, 3f)]
    public float markerSize = 1.5f;
    [Range(-5f, 5f)]
    public float markerHeight = 0.5f; // Y coordinate height above map tiles
    public Color markerColor = Color.green;

    [Header("Animation Settings")]
    public bool enableBlinking = true;
    [Range(0.1f, 2f)]
    public float blinkSpeed = 0.5f;

    // Private variables
    private GameObject teamMarkerInstance;
    private Vector2Int currentTeamPosition;
    private bool isTeamPositionSet = false;
    private bool isBlinking = false;
    private MapMaker2 mapMaker;

    public static SimpleTeamPlacement Instance { get; private set; }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        else
        {
            Debug.LogWarning("Multiple SimpleTeamPlacement instances found. Destroying this one.");
            Destroy(gameObject);
            return;
        }
    }

    void Start()
    {
        // Find MapMaker2
        mapMaker = FindFirstObjectByType<MapMaker2>();

        if (mapMaker == null)
        {
            return;
        }

        // Wait a bit for map generation, then place team
        StartCoroutine(WaitAndPlaceTeam());
    }

    void Update()
    {
        // Debug keys
        if (Input.GetKeyDown(KeyCode.R))
        {
            RandomlyPlaceTeam();
        }

        if (Input.GetKeyDown(KeyCode.M))
        {
            ShowMarkerInfo();
        }

        // Debug key to check saved positions
        if (Input.GetKeyDown(KeyCode.P))
        {
            DebugSavedPositions();
        }

        // Travel system integration - allow clicking on map to plan travel
        if (Input.GetKeyDown(KeyCode.T))
        {
            ShowTravelInfo();
        }
    }

    private IEnumerator WaitAndPlaceTeam()
    {
        // Wait for map generation
        yield return new WaitForSeconds(1.5f);

        // Check if this is a new game that should force random placement
        // First ensure GameStateManager exists, create it if needed
        if (GameStateManager.Instance == null)
        {
            GameObject gameStateObj = new GameObject("GameStateManager");
            gameStateObj.AddComponent<GameStateManager>();
            // Wait a frame for the GameStateManager to initialize
            yield return null;
        }

        bool isNewGame = GameStateManager.Instance?.IsNewGameForceRandom() ?? false;

        // ALWAYS show new game detection debug logs (even if showDebugLogs is false)

        if (isNewGame)
        {
            RandomlyPlaceTeam();

            // Clear the new game flag after placement
            GameStateManager.Instance?.ClearNewGameFlag();
            yield break;
        }

        // Try multiple times to load saved position (in case MapMaker2 isn't ready yet)
        int attempts = 0;
        const int maxAttempts = 5;

        while (attempts < maxAttempts)
        {
            attempts++;

            // Try to load saved position first
            if (TryLoadSavedPosition())
            {
                yield break; // Exit successfully
            }

            // If failed and MapMaker seed is still 0, wait a bit more
            if (mapMaker?.seed == 0 && attempts < maxAttempts)
            {
                yield return new WaitForSeconds(0.5f);
            }
            else
            {
                break; // Either loaded successfully or MapMaker is ready but no saved position
            }
        }

        // No saved position or invalid, place randomly
        RandomlyPlaceTeam();
    }

    private bool TryLoadSavedPosition()
    {
        // Get the current map seed to make position specific to this map
        int currentSeed = mapMaker?.seed ?? 0;
        string positionKey = $"TeamPosition_{currentSeed}";


        if (currentSeed == 0)
        {
            return false;
        }

        if (!PlayerPrefs.HasKey($"{positionKey}_X") || !PlayerPrefs.HasKey($"{positionKey}_Y"))
        {
            return false;
        }

        Vector2Int savedPosition = new Vector2Int(
            PlayerPrefs.GetInt($"{positionKey}_X"),
            PlayerPrefs.GetInt($"{positionKey}_Y")
        );


        // Verify position is still valid (any valid map position, not just settlements)
        if (IsValidMapPosition(savedPosition))
        {
            PlaceTeamAt(savedPosition);
            return true;
        }

        return false;
    }

    public void RandomlyPlaceTeam()
    {
        if (mapMaker?.GetMapData() == null)
        {
            return;
        }

        // For new games, ensure we're using the current random state for truly random placement
        bool isNewGame = GameStateManager.Instance?.IsNewGameForceRandom() ?? false;

        var mapData = mapMaker.GetMapData();
        var allSettlements = new List<Settlement>();

        // Combine towns and villages into one list for random selection
        allSettlements.AddRange(mapData.GetTowns());
        allSettlements.AddRange(mapData.GetVillages());

        if (allSettlements.Count == 0)
        {
            return;
        }

        // Randomly select a settlement
        int randomIndex = Random.Range(0, allSettlements.Count);
        Settlement selectedSettlement = allSettlements[randomIndex];

        PlaceTeamAt(selectedSettlement.position);
    }

    public void PlaceTeamAt(Vector2Int position)
    {
        currentTeamPosition = position;
        isTeamPositionSet = true;

        // Save position with map seed for persistence
        int currentSeed = mapMaker?.seed ?? 0;
        string positionKey = $"TeamPosition_{currentSeed}";
        bool isNewGame = GameStateManager.Instance?.IsNewGameForceRandom() ?? false;


        PlayerPrefs.SetInt($"{positionKey}_X", position.x);
        PlayerPrefs.SetInt($"{positionKey}_Y", position.y);
        PlayerPrefs.Save();

        // Create/update visual marker
        CreateTeamMarker();

        // Notify MapMaker2 of position change for event-driven exploration
        if (mapMaker != null)
        {
            mapMaker.OnTeamPositionChanged(position);
        }

    }

    /// <summary>
    /// Cleans up position data for old map seeds (optional maintenance)
    /// </summary>
    public void CleanupOldPositionData()
    {
        int currentSeed = mapMaker?.seed ?? 0;
        int cleanedCount = 0;

        // This is a simple cleanup - in a real game you might want more sophisticated management
        for (int i = 0; i < 10; i++) // Check last 10 potential seeds for cleanup
        {
            int testSeed = currentSeed - i;
            if (testSeed != currentSeed && testSeed > 0)
            {
                string positionKey = $"TeamPosition_{testSeed}";
                if (PlayerPrefs.HasKey($"{positionKey}_X"))
                {
                    PlayerPrefs.DeleteKey($"{positionKey}_X");
                    PlayerPrefs.DeleteKey($"{positionKey}_Y");
                    cleanedCount++;
                }
            }
        }
    }

    /// <summary>
    /// Debug method to check what positions are saved in PlayerPrefs
    /// </summary>
    private void DebugSavedPositions()
    {
        int currentSeed = mapMaker?.seed ?? 0;




        // Check current seed position
        string currentKey = $"TeamPosition_{currentSeed}";
        bool hasCurrentPosition = PlayerPrefs.HasKey($"{currentKey}_X") && PlayerPrefs.HasKey($"{currentKey}_Y");

        if (hasCurrentPosition)
        {
            Vector2Int currentPos = new Vector2Int(
                PlayerPrefs.GetInt($"{currentKey}_X"),
                PlayerPrefs.GetInt($"{currentKey}_Y")
            );

        }
        else
        {

        }

        // Check for other potential seeds (common ones)
        int[] testSeeds = { 0, 12345, 1000, 5000, 9999 };
        foreach (int testSeed in testSeeds)
        {
            if (testSeed == currentSeed) continue; // Already checked

            string testKey = $"TeamPosition_{testSeed}";
            if (PlayerPrefs.HasKey($"{testKey}_X") && PlayerPrefs.HasKey($"{testKey}_Y"))
            {
                Vector2Int testPos = new Vector2Int(
                    PlayerPrefs.GetInt($"{testKey}_X"),
                    PlayerPrefs.GetInt($"{testKey}_Y")
                );

            }
        }




    }

    private void CreateTeamMarker()
    {
        // Stop any existing blinking first
        if (isBlinking)
        {
            StopAllCoroutines(); // This will stop the BlinkMarker coroutine
            isBlinking = false;
        }

        // Remove existing marker
        if (teamMarkerInstance != null)
        {
            DestroyImmediate(teamMarkerInstance);
        }

        // Create new marker
        if (teamMarkerPrefab != null)
        {
            teamMarkerInstance = Instantiate(teamMarkerPrefab);
        }
        else
        {
            // Create simple sphere marker
            teamMarkerInstance = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            teamMarkerInstance.transform.localScale = Vector3.one * markerSize;
            teamMarkerInstance.tag = "Player";
        }

        // Position marker
        PositionMarker();

        // Apply material/color
        ApplyMarkerMaterial();

        // Set name
        teamMarkerInstance.name = "TeamMarker";

        // Start blinking if enabled
        if (enableBlinking)
        {
            StartBlinking();
        }

    }

    /// <summary>
    /// Get current team position
    /// </summary>
    public Vector2Int GetCurrentTeamPosition()
    {
        return currentTeamPosition;
    }

    /// <summary>
    /// Update team marker position when map coordinates change (called by exploration system)
    /// </summary>
    public void UpdateMarkerAfterMapChange(Vector2Int newVisiblePosition)
    {
        if (!isTeamPositionSet || teamMarkerInstance == null)
        {
            return;
        }

        // Store the world position before updating coordinates
        Vector3 currentWorldPos = teamMarkerInstance.transform.position;

        // Update the current team position to the new visible coordinates
        Vector2Int oldPosition = currentTeamPosition;
        currentTeamPosition = newVisiblePosition;

        // Reposition the marker to maintain world position consistency
        PositionMarker();

    }

    private void PositionMarker()
    {
        // Get tile size from MapVisualizer
        float tileSize = 1f;
        if (mapMaker?.mapVisualizer != null)
        {
            tileSize = mapMaker.mapVisualizer.tileSize;
        }

        // Calculate world position: 
        // In exploration mode, we need to convert exploration coordinates to full map coordinates for world positioning
        Vector2Int worldCoordinates = currentTeamPosition;

        // Check if we're using exploration system
        if (mapMaker != null && mapMaker.useExplorationSystem)
        {
            var explorationManager = mapMaker.GetExplorationManager();
            if (explorationManager != null)
            {
                // Use exploration manager to convert coordinates properly
                Vector3 correctWorldPos = explorationManager.ConvertExplorationToWorldCoordinates(currentTeamPosition);
                teamMarkerInstance.transform.position = new Vector3(
                    correctWorldPos.x,
                    markerHeight, // Y coordinate height above map tiles
                    correctWorldPos.z  // Use Z coordinate for map Y position
                );

                return;
            }
        }

        // Fallback for non-exploration mode: use direct coordinate mapping
        Vector3 worldPosition = new Vector3(
            worldCoordinates.x * tileSize,
            markerHeight, // Y coordinate height above map tiles
            worldCoordinates.y * tileSize // Map Y becomes world Z for top-down view
        );

        teamMarkerInstance.transform.position = worldPosition;

    }

    private void ApplyMarkerMaterial()
    {
        Renderer renderer = teamMarkerInstance.GetComponent<Renderer>();
        if (renderer == null) return;

        if (teamMarkerMaterial != null)
        {
            renderer.material = teamMarkerMaterial;
        }
        else
        {
            // Create simple colored material using URP shaders first
            Shader shader = null;

            // Try URP shaders first
            shader = Shader.Find("Universal Render Pipeline/Lit");
            if (shader == null)
                shader = Shader.Find("Universal Render Pipeline/Simple Lit");
            if (shader == null)
                shader = Shader.Find("Universal Render Pipeline/Unlit");

            // Fallback to built-in shaders
            if (shader == null)
                shader = Shader.Find("Standard");
            if (shader == null)
                shader = Shader.Find("Legacy Shaders/Diffuse");
            if (shader == null)
                shader = Shader.Find("Unlit/Color");

            // Last resort fallback
            if (shader == null)
            {
                return;
            }

            Material material = new Material(shader);

            // Set base color (works for both URP and built-in)
            if (material.HasProperty("_BaseColor"))
            {
                material.SetColor("_BaseColor", markerColor); // URP property
            }
            else if (material.HasProperty("_Color"))
            {
                material.SetColor("_Color", markerColor); // Built-in property
            }

            material.color = markerColor; // Fallback

            // Add emission for better visibility
            if (material.HasProperty("_EmissionColor"))
            {
                material.EnableKeyword("_EMISSION");
                material.SetColor("_EmissionColor", markerColor * 0.3f);
            }

            renderer.material = material;
        }
    }

    private void StartBlinking()
    {
        if (!isBlinking)
        {
            StartCoroutine(BlinkMarker());
        }
        else
        {
            // Force restart blinking as a fallback
            StopAllCoroutines();
            isBlinking = false;
            StartCoroutine(BlinkMarker());
        }
    }

    private IEnumerator BlinkMarker()
    {
        isBlinking = true;
        Renderer markerRenderer = teamMarkerInstance?.GetComponent<Renderer>();

        if (markerRenderer == null)
        {
            isBlinking = false;
            yield break;
        }

        // Capture the enableBlinking state at start to avoid timing issues
        bool shouldBlink = enableBlinking;

        int blinkCount = 0;
        while (teamMarkerInstance != null && markerRenderer != null && shouldBlink)
        {
            // Hide marker
            markerRenderer.enabled = false;
            yield return new WaitForSeconds(blinkSpeed);

            // Show marker
            if (markerRenderer != null && teamMarkerInstance != null)
            {
                markerRenderer.enabled = true;
                yield return new WaitForSeconds(blinkSpeed);
                blinkCount++;
            }
            else
            {
                break;
            }

            // Re-check enableBlinking periodically (every 10 blinks) in case user changes it
            if (blinkCount % 10 == 0)
            {
                shouldBlink = enableBlinking;
            }
        }

        isBlinking = false;
    }

    private bool IsValidSettlementPosition(Vector2Int position)
    {
        if (mapMaker?.GetMapData() == null) return false;

        var mapData = mapMaker.GetMapData();
        if (!mapData.IsValidPosition(position.x, position.y)) return false;

        // Check if position has a settlement
        foreach (var town in mapData.GetTowns())
        {
            if (town.position == position) return true;
        }

        foreach (var village in mapData.GetVillages())
        {
            if (village.position == position) return true;
        }

        return false;
    }

    /// <summary>
    /// Checks if a position is valid for team placement (any valid map position)
    /// Used for persistent positioning - team can be anywhere on the map
    /// </summary>
    private bool IsValidMapPosition(Vector2Int position)
    {
        if (mapMaker?.GetMapData() == null)
        {
            return false;
        }

        var mapData = mapMaker.GetMapData();
        return mapData.IsValidPosition(position.x, position.y);
    }

    private void ShowMarkerInfo()
    {
        if (teamMarkerInstance == null)
        {

            return;
        }









    }

    private void ShowTravelInfo()
    {




        var travelSystem = TeamTravelSystem.Instance;
        if (travelSystem != null)
        {




        }
        else
        {

        }








    }

    // Public methods for external control
    public Vector2Int GetTeamPosition() => currentTeamPosition;
    public bool IsTeamPlaced() => isTeamPositionSet;
    public GameObject GetTeamMarker() => teamMarkerInstance;

    [ContextMenu("Randomly Place Team")]
    public void ContextRandomlyPlaceTeam()
    {
        RandomlyPlaceTeam();
    }

    [ContextMenu("Show Marker Info")]
    public void ContextShowMarkerInfo()
    {
        ShowMarkerInfo();
    }

    [ContextMenu("Force New Game Random Placement")]
    public void ContextForceNewGamePlacement()
    {
        // Temporarily set new game flag for testing
        if (GameStateManager.Instance != null)
        {
            GameStateManager.Instance.isNewGame = true;
        }

        RandomlyPlaceTeam();

        // Clear the flag after testing
        GameStateManager.Instance?.ClearNewGameFlag();
    }
}
