using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;

/// <summary>
/// MinimapExpandController — Tap the minimap to expand it to a full-screen map view.
/// Tap again or press the close button to return to mini view.
/// Attach to the minimap RawImage UI element.
/// 
/// In expanded mode:
///   - Camera zooms out to show entire play area
///   - Map stops rotating (north-up for readability)
///   - Semi-transparent overlay dims the game behind
///   - Close button appears in the corner
/// </summary>
[RequireComponent(typeof(RawImage))]
public class MinimapExpandController : MonoBehaviour, IPointerClickHandler
{
    [Header("Expand Settings")]
    [SerializeField] private float expandedZoom = 200f;          // Camera ortho size when expanded
    [SerializeField] private float expandDuration = 0.25f;       // Animation duration
    [SerializeField] private float overlayAlpha = 0.6f;          // Background dim overlay

    [Header("Expanded Size (screen fraction)")]
    [SerializeField] private float expandedScreenFraction = 0.85f; // 85% of screen
    
    [Header("Close Button")]
    [SerializeField] private Sprite closeButtonSprite;            // Optional: custom close icon
    [SerializeField] private float closeButtonSize = 50f;
    
    // ─── Runtime ─────────────────────────────────────────────
    private RectTransform _rectTransform;
    private MinimapManager _minimapManager;
    private Camera _minimapCam;
    
    // Saved mini-view state
    private Vector2 _miniAnchorMin;
    private Vector2 _miniAnchorMax;
    private Vector2 _miniOffsetMin;
    private Vector2 _miniOffsetMax;
    private Vector2 _miniPivot;
    private Vector2 _miniSizeDelta;
    private Vector3 _miniAnchoredPos;
    private float _miniZoom;
    private bool _miniRotateWithPlayer;
    private Vector3 _miniCameraOffset;
    
    // Expanded state
    private bool _isExpanded = false;
    private bool _isAnimating = false;
    private GameObject _overlay;
    private GameObject _closeButton;
    private Canvas _parentCanvas;
    
    // ─── Lifecycle ───────────────────────────────────────────

    private void Start()
    {
        _rectTransform = GetComponent<RectTransform>();
        _parentCanvas = GetComponentInParent<Canvas>();
        
        // Find MinimapManager
        _minimapManager = FindObjectOfType<MinimapManager>();
        if (_minimapManager != null)
            _minimapCam = _minimapManager.GetComponent<Camera>();
        
        // Save initial mini-view layout
        SaveMiniState();
        
        // Create overlay (hidden by default)
        CreateOverlay();
        CreateCloseButton();
    }

    // ─── Click Handler ───────────────────────────────────────

    public void OnPointerClick(PointerEventData eventData)
    {
        if (_isAnimating) return;
        
        if (_isExpanded)
            Collapse();
        else
            Expand();
    }

    // ─── Expand / Collapse ───────────────────────────────────

    public void Expand()
    {
        if (_isExpanded || _isAnimating) return;
        _isExpanded = true;
        
        SaveMiniState();
        
        // Show overlay
        if (_overlay != null) _overlay.SetActive(true);
        if (_closeButton != null) _closeButton.SetActive(true);
        
        // Bring minimap on top
        _rectTransform.SetAsLastSibling();
        if (_closeButton != null) _closeButton.transform.SetAsLastSibling();
        
        // Switch camera to full-map mode
        if (_minimapManager != null)
        {
            _minimapManager.rotateWithPlayer = false;
            _minimapManager.SetZoom(expandedZoom);
        }
        
        // Animate the RectTransform to fill screen
        StartCoroutine(AnimateExpand());
    }

    public void Collapse()
    {
        if (!_isExpanded || _isAnimating) return;
        _isExpanded = false;
        
        // Hide overlay
        if (_overlay != null) _overlay.SetActive(false);
        if (_closeButton != null) _closeButton.SetActive(false);
        
        // Restore camera
        if (_minimapManager != null)
        {
            _minimapManager.rotateWithPlayer = _miniRotateWithPlayer;
            _minimapManager.SetZoom(_miniZoom);
        }
        
        // Animate back to mini
        StartCoroutine(AnimateCollapse());
    }

    // ─── State Save/Restore ──────────────────────────────────

    private void SaveMiniState()
    {
        _miniAnchorMin = _rectTransform.anchorMin;
        _miniAnchorMax = _rectTransform.anchorMax;
        _miniOffsetMin = _rectTransform.offsetMin;
        _miniOffsetMax = _rectTransform.offsetMax;
        _miniPivot = _rectTransform.pivot;
        _miniSizeDelta = _rectTransform.sizeDelta;
        _miniAnchoredPos = _rectTransform.anchoredPosition;
        
        if (_minimapManager != null)
        {
            _miniRotateWithPlayer = _minimapManager.rotateWithPlayer;
            _miniCameraOffset = _minimapManager.offset;
        }
        
        if (_minimapCam != null)
            _miniZoom = _minimapCam.orthographicSize;
    }

    private void RestoreMiniState()
    {
        _rectTransform.anchorMin = _miniAnchorMin;
        _rectTransform.anchorMax = _miniAnchorMax;
        _rectTransform.offsetMin = _miniOffsetMin;
        _rectTransform.offsetMax = _miniOffsetMax;
        _rectTransform.pivot = _miniPivot;
        _rectTransform.sizeDelta = _miniSizeDelta;
        _rectTransform.anchoredPosition = _miniAnchoredPos;
    }

    // ─── Animations ──────────────────────────────────────────

    private IEnumerator AnimateExpand()
    {
        _isAnimating = true;
        
        // Capture start state
        Vector2 startAnchorMin = _rectTransform.anchorMin;
        Vector2 startAnchorMax = _rectTransform.anchorMax;
        Vector2 startOffsetMin = _rectTransform.offsetMin;
        Vector2 startOffsetMax = _rectTransform.offsetMax;
        Vector2 startPivot = _rectTransform.pivot;
        
        // Target: centered, filling expandedScreenFraction of screen
        float margin = (1f - expandedScreenFraction) / 2f;
        Vector2 targetAnchorMin = new Vector2(margin, margin);
        Vector2 targetAnchorMax = new Vector2(1f - margin, 1f - margin);
        Vector2 targetOffsetMin = Vector2.zero;
        Vector2 targetOffsetMax = Vector2.zero;
        Vector2 targetPivot = new Vector2(0.5f, 0.5f);
        
        float elapsed = 0f;
        while (elapsed < expandDuration)
        {
            elapsed += Time.unscaledDeltaTime;
            float t = Mathf.SmoothStep(0f, 1f, elapsed / expandDuration);
            
            _rectTransform.anchorMin = Vector2.Lerp(startAnchorMin, targetAnchorMin, t);
            _rectTransform.anchorMax = Vector2.Lerp(startAnchorMax, targetAnchorMax, t);
            _rectTransform.offsetMin = Vector2.Lerp(startOffsetMin, targetOffsetMin, t);
            _rectTransform.offsetMax = Vector2.Lerp(startOffsetMax, targetOffsetMax, t);
            _rectTransform.pivot = Vector2.Lerp(startPivot, targetPivot, t);
            
            yield return null;
        }
        
        // Ensure final values are exact
        _rectTransform.anchorMin = targetAnchorMin;
        _rectTransform.anchorMax = targetAnchorMax;
        _rectTransform.offsetMin = targetOffsetMin;
        _rectTransform.offsetMax = targetOffsetMax;
        _rectTransform.pivot = targetPivot;
        
        _isAnimating = false;
    }

    private IEnumerator AnimateCollapse()
    {
        _isAnimating = true;
        
        // Capture current (expanded) state
        Vector2 startAnchorMin = _rectTransform.anchorMin;
        Vector2 startAnchorMax = _rectTransform.anchorMax;
        Vector2 startOffsetMin = _rectTransform.offsetMin;
        Vector2 startOffsetMax = _rectTransform.offsetMax;
        Vector2 startPivot = _rectTransform.pivot;
        
        float elapsed = 0f;
        while (elapsed < expandDuration)
        {
            elapsed += Time.unscaledDeltaTime;
            float t = Mathf.SmoothStep(0f, 1f, elapsed / expandDuration);
            
            _rectTransform.anchorMin = Vector2.Lerp(startAnchorMin, _miniAnchorMin, t);
            _rectTransform.anchorMax = Vector2.Lerp(startAnchorMax, _miniAnchorMax, t);
            _rectTransform.offsetMin = Vector2.Lerp(startOffsetMin, _miniOffsetMin, t);
            _rectTransform.offsetMax = Vector2.Lerp(startOffsetMax, _miniOffsetMax, t);
            _rectTransform.pivot = Vector2.Lerp(startPivot, _miniPivot, t);
            
            yield return null;
        }
        
        // Ensure exact mini state restored
        RestoreMiniState();
        
        _isAnimating = false;
    }

    // ─── UI Creation ─────────────────────────────────────────

    private void CreateOverlay()
    {
        if (_parentCanvas == null) return;
        
        _overlay = new GameObject("MinimapExpandOverlay");
        _overlay.transform.SetParent(_parentCanvas.transform, false);
        
        RectTransform overlayRect = _overlay.AddComponent<RectTransform>();
        overlayRect.anchorMin = Vector2.zero;
        overlayRect.anchorMax = Vector2.one;
        overlayRect.offsetMin = Vector2.zero;
        overlayRect.offsetMax = Vector2.zero;
        
        Image overlayImage = _overlay.AddComponent<Image>();
        overlayImage.color = new Color(0f, 0f, 0f, overlayAlpha);
        overlayImage.raycastTarget = true;
        
        // Clicking the overlay also closes the expanded map
        Button overlayButton = _overlay.AddComponent<Button>();
        overlayButton.transition = Selectable.Transition.None;
        overlayButton.onClick.AddListener(Collapse);
        
        _overlay.SetActive(false);
    }

    private void CreateCloseButton()
    {
        if (_parentCanvas == null) return;
        
        _closeButton = new GameObject("MinimapCloseButton");
        _closeButton.transform.SetParent(_parentCanvas.transform, false);
        
        RectTransform btnRect = _closeButton.AddComponent<RectTransform>();
        btnRect.anchorMin = new Vector2(1f, 1f);
        btnRect.anchorMax = new Vector2(1f, 1f);
        btnRect.pivot = new Vector2(1f, 1f);
        btnRect.sizeDelta = new Vector2(closeButtonSize, closeButtonSize);
        btnRect.anchoredPosition = new Vector2(-20f, -20f);
        
        Image btnImage = _closeButton.AddComponent<Image>();
        
        if (closeButtonSprite != null)
        {
            btnImage.sprite = closeButtonSprite;
        }
        else
        {
            // Create a simple "X" close icon procedurally
            btnImage.color = new Color(1f, 1f, 1f, 0.9f);
            btnImage.sprite = CreateCloseIcon();
        }
        
        Button btn = _closeButton.AddComponent<Button>();
        btn.targetGraphic = btnImage;
        btn.onClick.AddListener(Collapse);
        
        // Add "X" text as fallback
        GameObject textObj = new GameObject("CloseText");
        textObj.transform.SetParent(_closeButton.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;
        
        Text closeText = textObj.AddComponent<Text>();
        closeText.text = "✕";
        closeText.fontSize = (int)(closeButtonSize * 0.6f);
        closeText.alignment = TextAnchor.MiddleCenter;
        closeText.color = Color.white;
        closeText.font = Font.CreateDynamicFontFromOSFont("Arial", 24);
        
        _closeButton.SetActive(false);
    }

    private Sprite CreateCloseIcon()
    {
        int size = 64;
        Texture2D tex = new Texture2D(size, size);
        tex.filterMode = FilterMode.Bilinear;
        Color[] colors = new Color[size * size];
        
        // Semi-transparent dark circle
        Vector2 center = new Vector2(size / 2f, size / 2f);
        float radius = size / 2f;
        
        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                float dist = Vector2.Distance(new Vector2(x, y), center);
                if (dist <= radius)
                {
                    float edgeFade = Mathf.Clamp01((radius - dist) * 2f / radius);
                    colors[y * size + x] = new Color(0.2f, 0.2f, 0.2f, 0.8f * edgeFade);
                }
                else
                {
                    colors[y * size + x] = Color.clear;
                }
            }
        }
        
        tex.SetPixels(colors);
        tex.Apply();
        
        return Sprite.Create(tex, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f));
    }

    // ─── Public API ──────────────────────────────────────────

    /// <summary>Is the minimap currently expanded?</summary>
    public bool IsExpanded => _isExpanded;

    /// <summary>Toggle between expanded and mini views.</summary>
    public void Toggle()
    {
        if (_isExpanded) Collapse();
        else Expand();
    }

    private void OnDestroy()
    {
        if (_overlay != null) Destroy(_overlay);
        if (_closeButton != null) Destroy(_closeButton);
    }
}
