@page "/expeditions"
@using Domain.Dtos
@using Domain.Dtos.Stock
@using Domain.Generics
@using System.Text.Json
@using phronCare.UIBlazor.Shared.Modals
@using phronCare.UIBlazor.Services.Stock.Expeditions
@inject IExpeditionService expeditionService

@inject NavigationManager Nav
@inject IToastService Toast
@inject IModalService Modal

<div class="card shadow-sm mb-3" style="zoom: 0.8;">
  <div class="card-header py-2">
    <div class="d-flex justify-content-center align-items-center">
        <h3 class="card-title m-0">Consulta de Expediciones</h3>
    </div>
  </div>

  <div class="card-body">
    <EditForm Model="@filters" OnValidSubmit="@Search">
      <div class="row g-2 align-items-end">
        <!-- En monitores grandes queda todo en una fila (col-xxl-2 = 6 columnas por fila) -->
        <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xxl-2">
          <label for="number"  class="form-label mb-1">Número</label>
          <InputText id="number" class="form-control form-control-sm" @bind-Value="filters.Number" />
        </div>

        <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xxl-2">
          <label for="status" class="form-label mb-1">Estado</label>
            <InputSelect id="status" class="form-select form-select-sm" @bind-Value="filters.Status">
            <option value="">(Todos)</option>
            <option value="Emitida">Emitida</option>
            <option value="EnTransito">En tránsito</option>
            <option value="EnDestino">En destino</option>
            <option value="Retorno">Retorno</option>
            <option value="Cerrada">Cerrada</option>
            <option value="Anulada">Anulada</option>
          </InputSelect>
        </div>

        <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xxl-2">
          <label for="from" class="form-label mb-1">Fecha desde</label>
          <InputDate id="from" class="form-control form-control-sm" @bind-Value="filters.From" />
        </div>

        <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xxl-2">
          <label for="to" class="form-label mb-1">Fecha hasta</label>
          <InputDate id="to" class="form-control form-control-sm" @bind-Value="filters.To" />
        </div>

        <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xxl-2">
          <label for="location" class="form-label mb-1">Ubicación</label>
          <InputNumber id="location" class="form-control form-control-sm" @bind-Value="filters.LocationId" />
          @* TODO: reemplazar por BlazoredTypeahead cuando conectes lookup de ubicaciones *@
        </div>

        <div class="col-12 col-sm-6 col-md-4 col-lg-3 col-xxl-2">
          <label for="pageg" class="form-label mb-1">Tam. página</label>
          <InputSelect id="pageg"class="form-select form-select-sm" @bind-Value="pageSize" @onchange="@(e => ChangePageSize(e.Value?.ToString()))">
            <option value="10">10</option>
            <option value="20">20</option>
            <option value="50">50</option>
          </InputSelect>
        </div>
      </div>

      <div class="d-flex justify-content-end gap-2 mt-3">
        <button class="btn btn-primary rounded-pill">
          <i class="fas fa-search me-1"></i> Buscar
        </button>
        <button class="btn btn-success rounded-pill" @onclick="Create">
            <i class="fas fa-plus me-1"></i> Nuevo
        </button>
        <button class="btn btn-secondary rounded-pill" @onclick="Clear">
            <i class="fas fa-eraser me-1"></i> Limpiar
        </button>
        <button class="btn btn-success rounded-pill" @onclick="ExportarExcel">
            <i class="fas fa-file-excel me-1"></i> Excel
        </button>
    </div>
    </EditForm>
  </div>
</div>

<div class="card shadow-sm" style="zoom:0.8;">
  <div class="table-responsive">
    <table class="table table-sm align-middle mb-0">
      <thead class="table-light">
        <tr>
          <th style="width:160px">Nº</th>
          <th style="width:120px">Fecha</th>
          <th style="width:140px">Estado</th>
          <th style="width:200px">Referencia Ext.</th>
            <th style="width:220px">Paciente</th>
            <th style="width:220px">Médico</th>
            <th style="width:220px">Hospital</th>
          <th>Observaciones</th>
          <th style="width:180px" class="text-end">Acciones</th>
        </tr>
      </thead>
      <tbody>
        @if (result?.Items?.Any() == true)
        {
          @foreach (var e in result!.Items!)
          {
            <tr>
                <td class="fw-semibold">@e.Expeditionnumber</td>
                <td>@e.Issuedate.ToString("yyyy-MM-dd")</td>
                <td>@e.Status</td>
                <td>@e.ExternalReference</td>
                <td class="text-truncate" style="max-width: 220px">@GetPatient(e.ExtrainfoJson)</td>
                <td class="text-truncate" style="max-width: 220px">@GetProfessional(e.ExtrainfoJson)</td>
                <td class="text-truncate" style="max-width: 220px">@GetInstitution(e.ExtrainfoJson)</td>
              <td class="text-truncate" style="max-width: 420px">@e.Observations</td>
              <td class="text-end">
                <div class="btn-group btn-group-sm">
                    <button class="btn btn-outline-primary rounded-pill" title="PDF" @onclick="() => ViewPdf(e.Id, e.Expeditionnumber)">
                        <i class="fas fa-file-pdf"></i>
                    </button>
                    <button class="btn btn-outline-secondary rounded-pill" title="Ver" @onclick="() => OpenDetailAsync(e)">
                        <i class="fas fa-eye"></i>
                    </button>

                    @if (CanMarkInTransit(e))
                    {
                        <button class="btn btn-outline-warning rounded-pill"
                                title="Pasar a En tránsito"
                                @onclick="() => ConfirmMarkInTransitAsync(e)">
                            <i class="fas fa-truck"></i>
                        </button>
                    }
                </div>
              </td>
            </tr>
          }
        }
        else if (IsLoading)
        {
            <tr><td colspan="9" class="text-center text-muted py-4">Cargando...</td></tr>
        }
        else
        {
            <tr><td colspan="9" class="text-center text-muted py-4">Sin resultados</td></tr>
        }
      </tbody>
    </table>
  </div>

  <!-- Paginación debajo -->
  <div class="d-flex justify-content-between align-items-center px-3 py-2 border-top">
    <div class="small text-muted">
      @if (result is not null && result.TotalItems > 0)
      {
        var from = ((page - 1) * pageSize) + 1;
        var to = Math.Min(page * pageSize, result.TotalItems);
        <text>Mostrando @from–@to de @result.TotalItems</text>
      }
    </div>
    <div class="btn-group">
      <button class="btn btn-outline-secondary btn-sm rounded-pill"
              disabled="@(page<=1)" @onclick="PrevPage">
        <i class="fas fa-chevron-left me-1"></i> Anterior
      </button>
      <button class="btn btn-outline-secondary btn-sm rounded-pill"
              disabled="@(result is null || page>=TotalPages)" @onclick="NextPage">
        Siguiente <i class="fas fa-chevron-right ms-1"></i>
      </button>
    </div>
  </div>
</div>

<!-- Drawer de detalle -->
<ExpeditionDetailDrawer Expedition="@selected"
                        Visible="@drawerOpen"
                        VisibleChanged="@(v => drawerOpen = v)"
                        ExportPdfRequested="OnExportPdfRequested"
                        Loading="@loadingDetail" />

@code {
    private LSProductSearchParams SearchParams = new() { Page = 1, PageSize = 10 };

    private Filters filters = new();
    private PagedResult<ExpeditionDto>? result;
    private bool IsLoading;

    private int page = 1;
    private int pageSize = 10;
    private int TotalPages => result is null ? 1 : (int)Math.Ceiling((double)result.TotalItems / result.PageSize);

    private ExpeditionDto? selected;
    private bool drawerOpen;
    private bool loadingDetail;

    private async Task OpenDetailAsync(ExpeditionDto dto)
    {
        // Abro el drawer con lo que ya tengo (encabezado)
        loadingDetail = true;
        drawerOpen = true;
        selected = dto;
        StateHasChanged();

        // Traigo el DTO completo (incluye Items)
        var full = await expeditionService.GetDtoByIdAsync(dto.Id);
        if (full is not null)
        {
            selected = full;          // ahora sí con Items
        }
        else
        {
            Toast.ShowError("No se pudo cargar el detalle de la expedición.");
        }

        // opcional: si querés mostrar un spinner en el drawer mientras carga
        loadingDetail = false;
        StateHasChanged();
    }

  private async Task Search()
  {
        try
        {
            IsLoading = true;
            result = await expeditionService.SearchAsync(
            expeditionNumber: filters.Number,
            status: filters.Status,
            issueDateFrom: filters.From,
            issueDateTo: filters.To,
            locationId: filters.LocationId,
            page: page,
            pageSize: pageSize);
            StateHasChanged();
        }
        catch (Exception ex)
        {
            Toast.ShowError(ex.Message);
        }
        finally
        {
            IsLoading = false;
        }
    }

  private void Clear()
  {
    filters = new();
    page = 1;
    result = null;
  }

  private void Create()
  {
    Nav.NavigateTo("/expeditions/create");
  }

    private async Task ExportarExcel()
    {
        SearchParams.Page = 1;
        SearchParams.PageSize = int.MaxValue; // Exportar todos los resultados
        try
        {
            await expeditionService.ExportFilteredAsync(SearchParams);
            Toast.ShowSuccess("Exportación completada.");
        }
        catch (Exception ex)
        {
            Toast.ShowError($"Error: {ex.Message}");
        }
    }

  // private async Task ExportCurrent()
  // {
  //   // Opcional: /api/lsm/expeditions/export?{filtros}
  //   Toast.ShowInfo("Export en preparación.");
  // }

  private async Task ViewPdf(int id, string number)
  {
    await expeditionService.ExportPdfAsync(id, number);
  }

  private void OpenDetail(ExpeditionDto dto)
  {
    selected = dto;
    drawerOpen = true;
  }

  private async Task OnExportPdfRequested((int Id, string Number) payload)
  {
    await expeditionService.ExportPdfAsync(payload.Id, payload.Number);
  }

  private async Task PrevPage()
  {
    if (page <= 1) return;
    page--;
    await Search();
  }

  private async Task NextPage()
  {
    if (result is null || page >= TotalPages) return;
    page++;
    await Search();
  }

  private void ChangePageSize(string? value)
  {
    if (int.TryParse(value, out var newSize) && newSize > 0)
    {
      pageSize = newSize;
      page = 1;
      _ = Search();
    }
  }

  public class Filters
  {
    public string? Number { get; set; }
    public string? Status { get; set; }
    public DateTime? From { get; set; }
    public DateTime? To { get; set; }
    public int? LocationId { get; set; }
  }
    private static string? GetProfessional(string? json) => TryGetString(json, "Professional");
    private static string? GetInstitution(string? json) => TryGetString(json, "Institution");
    private static string? GetPatient(string? json) => TryGetString(json, "Patient");
    private static string? GetSurgeryDateShort(string? json)
        => TryGetDate(json, "SurgeryDate")?.ToString("dd/MM/yyyy");

    private static string? TryGetString(string? json, string propName)
    {
        if (string.IsNullOrWhiteSpace(json)) return null;
        try
        {
            using var doc = JsonDocument.Parse(json);
            var root = doc.RootElement;
            if (root.ValueKind != JsonValueKind.Object) return null;

            foreach (var p in root.EnumerateObject())
                if (string.Equals(p.Name, propName, StringComparison.OrdinalIgnoreCase)
                    && p.Value.ValueKind == JsonValueKind.String)
                    return p.Value.GetString();

            return null;
        }
        catch { return null; }
    }

    private static DateTime? TryGetDate(string? json, string propName)
    {
        var s = TryGetString(json, propName);
        if (string.IsNullOrWhiteSpace(s)) return null;
        if (DateTime.TryParse(s, out var dt)) return dt;
        return null;
    }
    // private bool CanMarkInTransit(ExpeditionDto expedition)
    // {
    //     if (expedition == null)
    //         return false;

    //     if (!string.IsNullOrWhiteSpace(expedition.StatusLabel))
    //         return string.Equals(expedition.StatusLabel, "Emitida", StringComparison.OrdinalIgnoreCase);

    //     return expedition.Status == 1;
    // }
    private bool CanMarkInTransit(ExpeditionDto expedition)
    {
        return expedition is not null && expedition.Status == 1;
    }
    private async Task ConfirmMarkInTransitAsync(ExpeditionDto expedition)
    {
        var parameters = new ModalParameters();
        parameters.Add(nameof(ConfirmModal.Title), "Confirmar cambio de estado");
        parameters.Add(nameof(ConfirmModal.Message),
            $"La expedición '{expedition.Expeditionnumber}' pasará a estado 'En tránsito'. ¿Desea continuar?");

        var modal = Modal.Show<ConfirmModal>("Confirmar", parameters);
        var resultModal = await modal.Result;

        if (resultModal.Cancelled)
            return;

        try
        {
            await expeditionService.MarkInTransitAsync(expedition.Id);

            Toast.ShowSuccess($"La expedición '{expedition.Expeditionnumber}' pasó a 'En tránsito' correctamente.");

            await Search();

            if (selected is not null && selected.Id == expedition.Id)
            {
                selected = await expeditionService.GetDtoByIdAsync(expedition.Id);
                StateHasChanged();
            }
        }
        catch (Exception ex)
        {
            Toast.ShowError(string.IsNullOrWhiteSpace(ex.Message)
                ? "No se pudo pasar la expedición a 'En tránsito'."
                : ex.Message);
        }
    }
}
