using XYZ.PrintService.Services;
using XYZ.PrintService.Models;

namespace XYZ.PrintService.Api;

public static class PrinterEndpoints
{
    public static void Map(WebApplication app)
    {
        app.MapGet("/health", () =>
            Results.Ok(new { status = "ok", version = "1.0.0" })
        );

        app.MapGet("/printers", () =>
        {
            try
            {
                var printers = PrinterDiscoveryService.GetPrinters();
                return Results.Ok(new { printers });
            }
            catch (Exception ex)
            {
                return Results.Problem(
                    detail: $"Failed to discover printers: {ex.Message}",
                    statusCode: 500
                );
            }
        });

        app.MapPost("/print", (PrintRequest request) =>
        {
            try
            {
                var result = PrintExecutionService.Print(request);
                return Results.Ok(new { 
                    success = result.Success, 
                    message = result.Message,
                    printerName = result.PrinterName,
                    bytesWritten = result.BytesWritten,
                    submittedAt = result.SubmittedAt
                });
            }
            catch (ArgumentException ex)
            {
                return Results.BadRequest(new { 
                    success = false, 
                    error = ex.Message 
                });
            }
            catch (Exception ex)
            {
                return Results.Problem(
                    detail: ex.Message,
                    statusCode: 500,
                    title: "Print failed"
                );
            }
        });

        // Batch print endpoint - enqueues a print job and returns job metadata
        app.MapPost("/print-batch", (PrintBatchRequest request) =>
        {
            try
            {
                var job = PrintJobQueueService.EnqueueBatch(request.PrinterName, request.Items);
                return Results.Ok(new
                {
                    success = true,
                    jobId = job.JobId,
                    printerName = job.PrinterName,
                    totalItems = job.Items.Count,
                    status = job.Status.ToString(),
                    createdAt = job.CreatedAt
                });
            }
            catch (ArgumentException ex)
            {
                return Results.BadRequest(new
                {
                    success = false,
                    error = ex.Message
                });
            }
            catch (Exception ex)
            {
                return Results.Problem(
                    detail: ex.Message,
                    statusCode: 500,
                    title: "Batch print failed"
                );
            }
        });

        // Print job status endpoint
        app.MapGet("/print-jobs/{jobId:guid}", (Guid jobId) =>
        {
            var job = PrintJobQueueService.GetJob(jobId);
            if (job == null)
            {
                return Results.NotFound(new
                {
                    success = false,
                    error = $"Print job '{jobId}' not found"
                });
            }

            var total = job.Items.Count;
            var successCount = job.Items.Count(i => i.Status == PrintJobItemStatus.Success);
            var failedCount = job.Items.Count(i => i.Status == PrintJobItemStatus.Failed);

            return Results.Ok(new
            {
                success = true,
                jobId = job.JobId,
                printerName = job.PrinterName,
                status = job.Status.ToString(),
                createdAt = job.CreatedAt,
                completedAt = job.CompletedAt,
                totalItems = total,
                successCount,
                failedCount,
                items = job.Items.Select(i => new
                {
                    itemId = i.ItemId,
                    status = i.Status.ToString(),
                    attempts = i.Attempts,
                    lastError = i.LastError
                })
            });
        });
    }
}
