@using phronCare.UIBlazor.Shared.Services
@using System.Timers
@implements IAsyncDisposable
@inject IJSRuntime JS


<div class="card mt-2">
    <div class="card-header d-flex justify-content-between align-items-center">
        <span><i class="fas fa-map-marker-alt me-2"></i>Mapa de Ubicación</span>
        <div class="d-flex gap-2">
            @if (EnableAddressSearch)
            {
                <input @bind="SearchAddress"
                @bind:event="oninput"
                @onchange="OnAddressChanged"
                class="form-control form-control-sm"
                placeholder="Buscar dirección..."
                style="width: 250px;" />
                <button class="btn btn-sm btn-outline-primary" @onclick="CenterByAddress" title="Buscar" disabled="@IsSearching">
                    <i class="fas @(IsSearching ? "fa-spinner fa-spin" : "fa-search-location")"></i>
                </button>
            }
            <button class="btn btn-sm btn-outline-secondary" @onclick="OpenGoogleMaps" title="Abrir en Google Maps">
                <i class="fab fa-google me-1"></i>Ver en Google Maps
            </button>
        </div>
    </div>
    <div class="card-body p-0" style="height: 400px;">
        <div id="@MapDivId" style="height: 100%; width: 100%;"></div>
    </div>
</div>

@code {
    private string MapDivId = string.Empty;
    public static PhMap? CurrentInstance { get; private set; }

    private double _latitude = -34.6037;
    private double _longitude = -58.3816;
    private bool _isMapInitialized = false;
    private Timer? _searchDebounceTimer;
    private bool IsSearching { get; set; } = false;

    [Parameter]
    public double Latitude
    {
        get => _latitude;
        set => _latitude = value;
    }
    [Parameter]
    public double Longitude
    {
        get => _longitude;
        set => _longitude = value;
    }
    [Parameter] public int Zoom { get; set; } = 13;
    [Parameter] public bool EnableAddressSearch { get; set; } = true;
    [Parameter] public EventCallback<(double lat, double lng)> OnLocationChanged { get; set; }

    private string SearchAddress { get; set; } = string.Empty;

    protected override void OnInitialized()
    {
        MapDivId = $"map_{Guid.NewGuid()}";
        CurrentInstance = this;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender && !_isMapInitialized)
        {
            MapInterop.RegisterInstance(this);
            await JS.InvokeVoidAsync("phMap.initMap", MapDivId, _latitude, _longitude, Zoom);
            _isMapInitialized = true;
        }
    }

    protected override async Task OnParametersSetAsync()
    {
        if (_isMapInitialized && (_latitude != Latitude || _longitude != Longitude))
        {
            _latitude = Latitude;
            _longitude = Longitude;
            await JS.InvokeVoidAsync("phMap.updateLocation", MapDivId, _latitude, _longitude);
        }
    }

    private void OnAddressChanged(ChangeEventArgs e)
    {
        _searchDebounceTimer?.Stop();
        _searchDebounceTimer?.Dispose();

        _searchDebounceTimer = new Timer(500);
        _searchDebounceTimer.Elapsed += async (s, e) =>
        {
            await CenterByAddress();
            _searchDebounceTimer?.Stop();
        };
        _searchDebounceTimer.AutoReset = false;
        _searchDebounceTimer.Start();
    }

    private async Task CenterByAddress()
    {
        if (!string.IsNullOrWhiteSpace(SearchAddress))
        {
            IsSearching = true;
            try
            {
                await JS.InvokeVoidAsync("phMap.searchAddress", MapDivId, SearchAddress);
            }
            finally
            {
                IsSearching = false;
            }
        }
    }

    private async Task OpenGoogleMaps()
    {
        if (!IsValidLocation(_latitude, _longitude))
            return;

        var url = $"https://www.google.com/maps?q={_latitude.ToString(System.Globalization.CultureInfo.InvariantCulture)},{_longitude.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
        await JS.InvokeVoidAsync("window.open", url, "_blank");
    }

    private bool IsValidLocation(double lat, double lng)
    {
        return lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180;
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        _searchDebounceTimer?.Stop();
        _searchDebounceTimer?.Dispose();

        if (_isMapInitialized)
        {
            try
            {
                await JS.InvokeVoidAsync("phMap.destroyMap", MapDivId);
            }
            catch { }
        }

        CurrentInstance = null;
    }
}
