using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Meezi.API.Models.Printing;
using Meezi.API.Services.Printing;
using Meezi.Core.Interfaces;
using Meezi.Shared;

namespace Meezi.API.Controllers;

[Route("api/cafes/{cafeId}/print")]
public class PrintController : CafeApiControllerBase
{
    private readonly IPrinterService _printer;

    public PrintController(IPrinterService printer) => _printer = printer;

    [HttpPost("receipt/{orderId}")]
    public async Task<IActionResult> PrintReceipt(
        string cafeId,
        string orderId,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var result = await _printer.PrintReceiptAsync(cafeId, orderId, ct);
        return ToActionResult(result);
    }

    [HttpPost("kitchen/{orderId}")]
    public async Task<IActionResult> PrintKitchen(
        string cafeId,
        string orderId,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var result = await _printer.PrintKitchenTicketAsync(cafeId, orderId, ct);
        return ToActionResult(result);
    }

    [HttpPost("test")]
    [Authorize(Roles = "Manager,Owner")]
    public async Task<IActionResult> TestPrint(
        string cafeId,
        [FromBody] TestPrintRequest request,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var result = await _printer.TestPrintAsync(request.PrinterIp, request.Port, ct);
        return ToActionResult(result);
    }

    private IActionResult ToActionResult(PrintResult result)
    {
        if (result.Success)
            return Ok(new ApiResponse<PrintJobResultDto>(true,
                new PrintJobResultDto(true, null, null)));

        var status = result.ErrorCode switch
        {
            "PRINTER_NOT_CONFIGURED" or "KITCHEN_PRINTER_NOT_CONFIGURED" => StatusCodes.Status400BadRequest,
            "ORDER_NOT_FOUND" => StatusCodes.Status404NotFound,
            _ => StatusCodes.Status502BadGateway
        };

        return StatusCode(status, new ApiResponse<PrintJobResultDto>(false, null,
            new ApiError(result.ErrorCode!, MessageForCode(result.ErrorCode), null)));
    }

    private static string MessageForCode(string? code) => code switch
    {
        "PRINTER_NOT_CONFIGURED" => "Receipt printer IP is not configured for this branch.",
        "KITCHEN_PRINTER_NOT_CONFIGURED" => "Kitchen printer IP is not configured for this branch.",
        "PRINTER_CONNECTION_FAILED" => "Could not connect to the printer.",
        "ORDER_NOT_FOUND" => "Order not found.",
        _ => "Print failed."
    };
}
