using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EventsAppQuest.Web.Producer.Core;
using EventsAppQuest.Web.Producer.Domain;

namespace EventsAppQuest.Web.Producer.Application
{
    /// <summary>
    /// Conclusão operacional do pedido: gerar relatório final, marcar como concluído, consolidar resumo (mock).
    /// </summary>
    public static class ProducerExecutionFinalReportController
    {
        /// <summary>Gera o relatório final a partir do estado de execução, updates, checklist, readiness e pedido. Substitui relatório anterior se existir.</summary>
        public static ProducerExecutionFinalReport GenerateReport(string orderId, string preparedByRole = "Producer")
        {
            if (string.IsNullOrEmpty(orderId)) return null;
            var execState = ProducerExecutionTrackingController.GetState(orderId);
            var updates = ProducerExecutionTrackingController.GetUpdates(orderId, 50);
            var checklistState = ProducerPreparationChecklistController.GetChecklistState(orderId);
            var readiness = ProducerExecutionReadinessController.Evaluate(orderId);
            var order = HandoffStore.GetOrderById(orderId);

            var report = new ProducerExecutionFinalReport
            {
                ReportId = "rpt-" + Guid.NewGuid().ToString("N").Substring(0, 8),
                ProducerOrderId = orderId,
                ExecutionStatusAtClose = execState.ExecutionStatus,
                StartedAt = execState.StartedAt,
                CompletedAt = execState.IsCompleted ? execState.LastUpdatedAt : (DateTime?)null,
                FinalProgressPercent = execState.ProgressPercent,
                FinalSummary = execState.CurrentExecutionSummary ?? execState.CompletionSummary ?? "—",
                DeliveredScopeSummary = BuildDeliveredScopeSummary(order, execState),
                AdjustmentsMade = BuildAdjustmentsSummary(updates),
                BlockingIssuesEncountered = BuildBlockingIssuesSummary(execState, updates),
                CompletionNotes = execState.CompletionSummary ?? "—",
                PreparedByRole = preparedByRole ?? "Producer",
                GeneratedAt = DateTime.UtcNow,
                ClosedByProducerAt = null,
                HotelAcknowledgedAt = null,
                Items = BuildReportItems(orderId, order, execState, updates)
            };

            FinalReportStore.SetReport(report);
            return report;
        }

        /// <summary>Marca o pedido como concluído operacionalmente (relatório deve existir).</summary>
        public static bool MarkOperationallyClosed(string orderId)
        {
            if (string.IsNullOrEmpty(orderId)) return false;
            var report = FinalReportStore.GetReport(orderId);
            if (report == null) return false;
            report.ClosedByProducerAt = DateTime.UtcNow;
            FinalReportStore.SetReport(report);
            return true;
        }

        /// <summary>Gera relatório e marca como concluído operacionalmente numa única acção.</summary>
        public static ProducerExecutionFinalReport GenerateAndClose(string orderId, string preparedByRole = "Producer")
        {
            var report = GenerateReport(orderId, preparedByRole);
            if (report != null)
                MarkOperationallyClosed(orderId);
            return report;
        }

        public static ProducerExecutionFinalReport GetReport(string orderId) => FinalReportStore.GetReport(orderId);
        public static bool HasReport(string orderId) => FinalReportStore.HasReport(orderId);
        public static bool IsOperationallyClosed(string orderId) => FinalReportStore.IsOperationallyClosed(orderId);

        /// <summary>Hotel reconhece o fechamento (mock).</summary>
        public static void SetHotelAcknowledged(string orderId) => FinalReportStore.SetHotelAcknowledged(orderId);

        private static string BuildDeliveredScopeSummary(ProducerOrder order, ProducerExecutionStatusState execState)
        {
            if (order == null) return execState.CompletionSummary ?? "—";
            var sb = new StringBuilder();
            if (!string.IsNullOrEmpty(order.EventCategory)) sb.Append("Categoria: ").Append(order.EventCategory).Append(". ");
            if (!string.IsNullOrEmpty(order.ThemeLabel)) sb.Append("Tema: ").Append(order.ThemeLabel).Append(". ");
            if (!string.IsNullOrEmpty(order.OrderSummary)) sb.Append(order.OrderSummary);
            if (sb.Length == 0) return execState.CompletionSummary ?? "—";
            return sb.ToString().Trim();
        }

        private static string BuildAdjustmentsSummary(IReadOnlyList<ProducerExecutionUpdate> updates)
        {
            var adjustmentUpdates = updates.Where(u => u.UpdateType == ProducerExecutionUpdateType.ProgressUpdate && !u.IsIssue && !u.IsBlocking).Take(10).ToList();
            if (adjustmentUpdates.Count == 0) return "Nenhum ajuste registado.";
            return string.Join(" | ", adjustmentUpdates.Select(u => u.Title + ": " + u.Summary));
        }

        private static string BuildBlockingIssuesSummary(ProducerExecutionStatusState execState, IReadOnlyList<ProducerExecutionUpdate> updates)
        {
            if (!execState.HasIssues && execState.ExecutionStatus != ProducerExecutionStatus.Blocked)
                return "Nenhum bloqueio ou issue reportado.";
            var issueUpdates = updates.Where(u => u.IsIssue || u.IsBlocking).Take(15).ToList();
            if (issueUpdates.Count == 0) return execState.HasIssues ? "Issues reportadas (sem detalhe)." : "—";
            return string.Join(" | ", issueUpdates.Select(u => (u.IsBlocking ? "[Bloqueio] " : "[Issue] ") + u.Title + ": " + u.Summary));
        }

        private static List<ProducerExecutionFinalReportItem> BuildReportItems(string orderId, ProducerOrder order, ProducerExecutionStatusState execState, IReadOnlyList<ProducerExecutionUpdate> updates)
        {
            var items = new List<ProducerExecutionFinalReportItem>();
            var id = 0;

            if (order != null && (!string.IsNullOrEmpty(order.OrderSummary) || !string.IsNullOrEmpty(order.EventCategory)))
            {
                items.Add(new ProducerExecutionFinalReportItem
                {
                    ItemId = "ri-" + (++id),
                    Category = ProducerExecutionReportItemCategory.ScopeDelivered,
                    Title = "Escopo entregue",
                    Summary = order.OrderSummary ?? order.EventCategory ?? "—",
                    IsIssue = false,
                    IsResolved = true,
                    Notes = null
                });
            }

            foreach (var u in updates.Where(u => u.IsIssue || u.IsBlocking).Take(20))
            {
                items.Add(new ProducerExecutionFinalReportItem
                {
                    ItemId = "ri-" + (++id),
                    Category = u.IsBlocking ? ProducerExecutionReportItemCategory.Blocker : ProducerExecutionReportItemCategory.Issue,
                    Title = u.Title,
                    Summary = u.Summary,
                    IsIssue = u.IsIssue,
                    IsResolved = false,
                    Notes = u.CreatedAt.ToString("yyyy-MM-dd HH:mm")
                });
            }

            foreach (var u in updates.Where(u => u.UpdateType == ProducerExecutionUpdateType.ProgressUpdate && !u.IsIssue && !u.IsBlocking && !string.IsNullOrWhiteSpace(u.Summary)).Take(10))
            {
                items.Add(new ProducerExecutionFinalReportItem
                {
                    ItemId = "ri-" + (++id),
                    Category = ProducerExecutionReportItemCategory.Adjustment,
                    Title = u.Title,
                    Summary = u.Summary,
                    IsIssue = false,
                    IsResolved = true,
                    Notes = null
                });
            }

            return items;
        }
    }
}
