@page "/deliverynotes/create"
@using System.ComponentModel.DataAnnotations
@using System.Text.Json
@using Blazored.Typeahead
@using Domain.Constants
@using Domain.Dtos
@using Domain.Dtos.Sales
@using phronCare.UIBlazor.Services.Lookups
@using phronCare.UIBlazor.Services.Sales.DeliveryNotes
@using phronCare.UIBlazor.Services.Sales.Quotes
@using phronCare.UIBlazor.Shared.Modals

@inject NavigationManager Navigation
@inject IDeliveryNoteService DeliveryNoteService
@inject ISalesLookupService SalesLookupService
@inject IQuoteService QuoteService
@inject IToastService toastService
@inject IModalService Modal

<EditForm Model="Model" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="container mt-4" style="zoom:.8;">
        <div class="card shadow-sm mb-3">
            <div class="card-header d-flex justify-content-center align-items-center">
                <h3 class="mb-0">Emisión de Remito</h3>
            </div>
            <div class="card-body">
                <div class="row mb-3">
                    <div class="col-md-2">
                        <label for="deliveryNoteNumber" class="form-label">Número de remito</label>
                        <InputText id="deliveryNoteNumber" class="form-control" @bind-Value="Model.DeliveryNoteNumber" />
                        <ValidationMessage For="@(() => Model.DeliveryNoteNumber)" />
                    </div>
                    <div class="col-md-2">
                        <label for="issueDate" class="form-label">Fecha de emisión</label>
                        <InputDate id="issueDate" class="form-control" @bind-Value="Model.IssueDate" />
                        <ValidationMessage For="@(() => Model.IssueDate)" />
                    </div>
                    <div class="col-md-4">
                        <label for="quoteLookup" class="form-label">Presupuesto aprobado (opcional)</label>
                        <BlazoredTypeahead id="quoteLookup" TItem="ELookUpItem" TValue="ELookUpItem"
                                           SearchMethod="SalesLookupService.SearchApprovedQuotesAsync"
                                           Value="SelectedQuote"
                                           ValueChanged="OnQuoteSelected"
                                           ValueExpression="@(() => SelectedQuote)"
                                           MaximumSuggestions="10"
                                           Placeholder="Buscar presupuesto aprobado..."
                                           TextProperty="Nombre">
                            <ResultTemplate Context="item">@item.Nombre</ResultTemplate>
                            <SelectedTemplate Context="item">@item.Nombre</SelectedTemplate>
                        </BlazoredTypeahead>
                    </div>
                    <div class="col-md-4">
                        <label for="customerLookup" class="form-label">Cliente</label>
                        <BlazoredTypeahead id="customerLookup" TItem="ELookUpItem" TValue="ELookUpItem"
                                           SearchMethod="SalesLookupService.SearchCustomersAsync"
                                           Value="SelectedCustomer"
                                           ValueChanged="OnCustomerSelected"
                                           ValueExpression="@(() => SelectedCustomer)"
                                           MaximumSuggestions="10"
                                           Placeholder="Buscar cliente..."
                                           TextProperty="Nombre">
                            <ResultTemplate Context="item">@item.Nombre</ResultTemplate>
                            <SelectedTemplate Context="item">@item.Nombre</SelectedTemplate>
                        </BlazoredTypeahead>
                        <ValidationMessage For="@(() => Model.CustomerId)" />
                    </div>
                </div>

                <div class="row mb-3">
                    <div class="col-md-6">
                        <label for="observations" class="form-label">Observaciones</label>
                        <InputTextArea id="observations" class="form-control" rows="3" @bind-Value="Model.Observations" />
                    </div>
                    <div class="col-md-6">
                        @if (SelectedQuote is not null)
                        {
                            <label for="observations" class="form-label">Vinculado</label>
                            <div class="alert alert-dark border mb-3">
                                <strong rows="3">Presupuesto vinculado:</strong> @SelectedQuote.Nombre
                            </div>
                        }
                    </div>
                </div>

                @if (SelectedQuote is not null)
                {
                    <div class="card border-1 bg-light-subtle">
                        <div class="card-body py-3">
                            <div class="row g-3">
                                <div class="col-md-6">
                                    <label class="form-label fw-semibold mb-1">Profesional</label>
                                    <div class="form-control bg-white">@(string.IsNullOrWhiteSpace(ExtraInfo.Professional) ? "No informado" : ExtraInfo.Professional)</div>
                                </div>
                                <div class="col-md-6">
                                    <label class="form-label fw-semibold mb-1">Institución</label>
                                    <div class="form-control bg-white">@(string.IsNullOrWhiteSpace(ExtraInfo.Institution) ? "No informada" : ExtraInfo.Institution)</div>
                                </div>
                                <div class="col-md-6">
                                    <label class="form-label fw-semibold mb-1">Paciente</label>
                                    <div class="form-control bg-white">@(string.IsNullOrWhiteSpace(ExtraInfo.Patient) ? "No informado" : ExtraInfo.Patient)</div>
                                </div>
                                <div class="col-md-6">
                                    <label class="form-label fw-semibold mb-1">Fecha estimada de cirugía</label>
                                    <div class="form-control bg-white">@(ExtraInfo.SurgeryDate.HasValue ? ExtraInfo.SurgeryDate.Value.ToString("dd/MM/yyyy") : "No informada")</div>
                                </div>
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>

        <div class="card shadow-sm mb-3">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Ítems del remito</h5>
                <button type="button" class="btn btn-outline-success btn-sm rounded-pill" @onclick="AddItem">
                    <i class="fas fa-plus me-1"></i> Agregar ítem
                </button>
            </div>
            <div class="card-body p-2">
                @if (Items.Any())
                {
                    <div class="table-responsive">
                        <table class="table table-sm table-bordered mb-0 deliverynote-items-table">
                            <thead class="table-light">
                                <tr>
                                    <th style="width: 60px;" class="text-center">#</th>
                                    <th>Descripción</th>
                                    <th style="width: 120px;" class="text-center">Cantidad</th>
                                    <th style="width: 160px;" class="text-center">Origen</th>
                                    <th>Notas</th>
                                    <th style="width: 60px;"></th>
                                </tr>
                            </thead>
                            <tbody>
                                @foreach (var item in Items)
                                {
                                    <tr>
                                        <td class="text-center line-number-cell">@item.LineNumber</td>
                                        <td>
                                            <InputTextArea class="form-control form-control-sm item-description" rows="3" @bind-Value="item.Description" />
                                        </td>
                                        <td>
                                            <InputNumber class="form-control form-control-sm text-end" @bind-Value="item.Quantity" />
                                        </td>
                                        <td>
                                            <InputSelect class="form-select form-select-sm" @bind-Value="item.OriginType">
                                                <option value="@((byte)DeliveryNoteItemOriginType.Manual)">Manual</option>
                                                <option value="@((byte)DeliveryNoteItemOriginType.QuoteDetail)">Presupuesto</option>
                                                <option value="@((byte)DeliveryNoteItemOriginType.SalesProduct)">Producto venta</option>
                                                <option value="@((byte)DeliveryNoteItemOriginType.StockProduct)">Producto stock</option>
                                            </InputSelect>
                                        </td>
                                        <td>
                                            <InputTextArea class="form-control form-control-sm item-notes" rows="3" @bind-Value="item.Notes" />
                                        </td>
                                        <td class="text-center actions-cell">
                                            <button type="button" class="btn btn-link p-0 text-danger" title="Eliminar" @onclick="() => RemoveItem(item)">
                                                <i class="fas fa-trash"></i>
                                            </button>
                                        </td>
                                    </tr>
                                }
                            </tbody>
                        </table>
                    </div>
                }
                else
                {
                    <div class="text-center text-muted py-4">
                        No hay ítems cargados.
                    </div>
                }
            </div>
        </div>

        <div class="d-flex justify-content-end gap-2">
            <button type="button" class="btn btn-secondary rounded-pill" @onclick="BackToList" disabled="@IsSaving">
                <i class="fas fa-arrow-left me-1"></i> Volver
            </button>
            <button type="submit" class="btn btn-primary rounded-pill" disabled="@IsSaving">
                @if (IsSaving)
                {
                    <span class="spinner-border spinner-border-sm me-2"></span>
                }
                <i class="fas fa-save me-1"></i> Emitir remito
            </button>
        </div>
    </div>
</EditForm>

@code {
    private DeliveryNoteCreatePageModel Model = new()
    {
        IssueDate = DateTime.Today
    };

    private ELookUpItem? SelectedCustomer;
    private ELookUpItem? SelectedQuote;
    private DeliveryNoteExtraInfoModel ExtraInfo = new();
    private List<DeliveryNoteItemRow> Items = new();

    private bool IsSaving;

    private void AddItem()
    {
        Items.Add(new DeliveryNoteItemRow
        {
            LineNumber = Items.Count + 1,
            OriginType = (byte)DeliveryNoteItemOriginType.Manual,
            Quantity = 1
        });
    }

    private void RemoveItem(DeliveryNoteItemRow item)
    {
        if (Items.Remove(item))
        {
            ReindexItems();
        }
    }

    private void ReindexItems()
    {
        for (var i = 0; i < Items.Count; i++)
        {
            Items[i].LineNumber = i + 1;
        }
    }

    private Task OnCustomerSelected(ELookUpItem? customer)
    {
        SelectedCustomer = customer;
        Model.CustomerId = customer?.Id;
        return Task.CompletedTask;
    }

    private async Task OnQuoteSelected(ELookUpItem? quote)
    {
        SelectedQuote = quote;
        Model.QuoteId = quote?.Id;

        if (quote is null)
        {
            ExtraInfo = new();
            Model.ExtraInfoJson = null;
            return;
        }

        var quoteDto = await QuoteService.GetDtoByIdAsync(quote.Id);
        if (quoteDto is null)
        {
            ExtraInfo = new();
            Model.ExtraInfoJson = null;
            toastService.ShowError("No se pudo cargar el presupuesto seleccionado.");
            return;
        }

        ExtraInfo = BuildExtraInfoModel(quoteDto);

        var mappedItems = BuildItemsFromApprovedQuote(quoteDto);
        if (mappedItems.Count == 0)
        {
            Model.ExtraInfoJson = JsonSerializer.Serialize(ExtraInfo);
            toastService.ShowWarning("El presupuesto seleccionado no tiene ítems aprobados para precargar.");
            return;
        }

        if (Items.Any())
        {
            var parameters = new ModalParameters();
            parameters.Add(nameof(ConfirmModal.Title), "Reemplazar ítems");
            parameters.Add(nameof(ConfirmModal.Message), "Ya hay ítems cargados. ¿Desea reemplazarlos por los ítems aprobados del presupuesto?");

            var modal = Modal.Show<ConfirmModal>("Confirmación", parameters);
            var result = await modal.Result;
            if (result.Cancelled)
                return;
        }

        Items = mappedItems;
        Model.ExtraInfoJson = JsonSerializer.Serialize(ExtraInfo);
        ReindexItems();
        StateHasChanged();
    }

    private static DeliveryNoteExtraInfoModel BuildExtraInfoModel(QuoteDto quote)
    {
        return new DeliveryNoteExtraInfoModel
        {
            Professional = quote.ProfessionalName,
            Institution = quote.InstitutionName,
            Patient = quote.PatientName,
            SurgeryDate = quote.EstimatedDate
        };
    }

    private List<DeliveryNoteItemRow> BuildItemsFromApprovedQuote(QuoteDto quote)
    {
        return quote.Items
            .Where(item => item.Approved)
            .Select(item => new
            {
                Item = item,
                Quantity = item.ApprovedQuantity.HasValue && item.ApprovedQuantity.Value > 0
                    ? item.ApprovedQuantity.Value
                    : item.Quantity
            })
            .Where(x => x.Quantity > 0)
            .Select((x, index) => new DeliveryNoteItemRow
            {
                LineNumber = index + 1,
                OriginType = (byte)DeliveryNoteItemOriginType.QuoteDetail,
                QuoteDetailId = x.Item.Id,
                Description = x.Item.Description,
                Quantity = x.Quantity
            })
            .ToList();
    }

    private string? ValidateBeforeSave()
    {
        if (Items.Count == 0)
            return "Debe incluir al menos un ítem.";

        if (Items.Any(x => string.IsNullOrWhiteSpace(x.Description)))
            return "Todos los ítems deben tener descripción.";

        if (Items.Any(x => x.Quantity <= 0))
            return "Todos los ítems deben tener cantidad mayor a cero.";

        return null;
    }

    private async Task HandleValidSubmit()
    {
        var validationError = ValidateBeforeSave();
        if (!string.IsNullOrWhiteSpace(validationError))
        {
            toastService.ShowError(validationError);
            return;
        }

        try
        {
            IsSaving = true;

            var request = new DeliveryNoteCreateRequest
            {
                DeliveryNoteNumber = Model.DeliveryNoteNumber.Trim(),
                IssueDate = Model.IssueDate!.Value,
                CustomerId = Model.CustomerId!.Value,
                QuoteId = Model.QuoteId,
                Observations = Model.Observations,
                ExtraInfoJson = Model.ExtraInfoJson,
                Items = Items.Select(x => new DeliveryNoteCreateItemRequest
                {
                    OriginType = x.OriginType,
                    OriginId = x.OriginId,
                    QuoteDetailId = x.QuoteDetailId,
                    Description = x.Description.Trim(),
                    Quantity = x.Quantity,
                    Notes = string.IsNullOrWhiteSpace(x.Notes) ? null : x.Notes.Trim()
                }).ToList()
            };

            var response = await DeliveryNoteService.CreateAndIssueAsync(request);
            toastService.ShowSuccess($"Remito {response.DeliveryNoteNumber} emitido correctamente.");
            await DeliveryNoteService.ExportPdfAsync(response.Id, response.DeliveryNoteNumber);
            Navigation.NavigateTo("/deliverynotes");
        }
        catch (Exception ex)
        {
            toastService.ShowError(ex.Message);
        }
        finally
        {
            IsSaving = false;
        }
    }

    private void BackToList()
    {
        Navigation.NavigateTo("/deliverynotes");
    }

    private sealed class DeliveryNoteCreatePageModel
    {
        [Required(ErrorMessage = "El número de remito es obligatorio.")]
        public string DeliveryNoteNumber { get; set; } = string.Empty;

        [Required(ErrorMessage = "La fecha de emisión es obligatoria.")]
        public DateTime? IssueDate { get; set; }

        [Required(ErrorMessage = "El cliente es obligatorio.")]
        public int? CustomerId { get; set; }

        public int? QuoteId { get; set; }
        public string? Observations { get; set; }
        public string? ExtraInfoJson { get; set; }
    }

    private sealed class DeliveryNoteExtraInfoModel
    {
        public string? Professional { get; set; }
        public string? Institution { get; set; }
        public string? Patient { get; set; }
        public DateTime? SurgeryDate { get; set; }
    }

    private sealed class DeliveryNoteItemRow
    {
        public int LineNumber { get; set; }
        public byte OriginType { get; set; }
        public int? OriginId { get; set; }
        public int? QuoteDetailId { get; set; }
        public string Description { get; set; } = string.Empty;
        public decimal Quantity { get; set; }
        public string? Notes { get; set; }
    }
}
