using FluentValidation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Meezi.API.Models.Printing;
using Meezi.Core.Entities;
using Meezi.Core.Interfaces;
using Meezi.Infrastructure.Data;
using Meezi.Shared;
using Microsoft.EntityFrameworkCore;

namespace Meezi.API.Controllers;

[Route("api/cafes/{cafeId}/branches/{branchId}/print-settings")]
[Authorize(Roles = "Manager,Owner")]
public class BranchPrintSettingsController : CafeApiControllerBase
{
    private readonly AppDbContext _db;
    private readonly IValidator<PatchBranchPrintSettingsRequest> _validator;

    public BranchPrintSettingsController(
        AppDbContext db,
        IValidator<PatchBranchPrintSettingsRequest> validator)
    {
        _db = db;
        _validator = validator;
    }

    [HttpGet]
    public async Task<IActionResult> Get(
        string cafeId,
        string branchId,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var branch = await _db.Branches
            .AsNoTracking()
            .FirstOrDefaultAsync(b => b.Id == branchId && b.CafeId == cafeId, ct);

        if (branch is null)
            return NotFound(new ApiResponse<object>(false, null,
                new ApiError("BRANCH_NOT_FOUND", "Branch not found.")));

        return Ok(new ApiResponse<BranchPrintSettingsDto>(true, ToDto(branch)));
    }

    [HttpPatch]
    public async Task<IActionResult> Patch(
        string cafeId,
        string branchId,
        [FromBody] PatchBranchPrintSettingsRequest request,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var validation = await _validator.ValidateAsync(request, ct);
        if (!validation.IsValid) return BadRequest(ValidationError(validation));

        var branch = await _db.Branches.FirstOrDefaultAsync(b => b.Id == branchId && b.CafeId == cafeId, ct);
        if (branch is null)
            return NotFound(new ApiResponse<object>(false, null,
                new ApiError("BRANCH_NOT_FOUND", "Branch not found.")));

        if (request.ReceiptPrinterIp is not null)
            branch.ReceiptPrinterIp = string.IsNullOrWhiteSpace(request.ReceiptPrinterIp)
                ? null
                : request.ReceiptPrinterIp.Trim();
        if (request.ReceiptPrinterPort.HasValue)
            branch.ReceiptPrinterPort = request.ReceiptPrinterPort.Value;
        if (request.KitchenPrinterIp is not null)
            branch.KitchenPrinterIp = string.IsNullOrWhiteSpace(request.KitchenPrinterIp)
                ? null
                : request.KitchenPrinterIp.Trim();
        if (request.KitchenPrinterPort.HasValue)
            branch.KitchenPrinterPort = request.KitchenPrinterPort.Value;
        if (request.PaperWidthMm.HasValue)
            branch.PaperWidthMm = request.PaperWidthMm.Value is 58 or 80 ? request.PaperWidthMm.Value : 80;
        if (request.AutoCutEnabled.HasValue)
            branch.AutoCutEnabled = request.AutoCutEnabled.Value;
        if (request.ReceiptHeader is not null)
            branch.ReceiptHeader = string.IsNullOrWhiteSpace(request.ReceiptHeader) ? null : request.ReceiptHeader.Trim();
        if (request.ReceiptFooter is not null)
            branch.ReceiptFooter = string.IsNullOrWhiteSpace(request.ReceiptFooter) ? null : request.ReceiptFooter.Trim();
        if (request.WifiPassword is not null)
            branch.WifiPassword = string.IsNullOrWhiteSpace(request.WifiPassword) ? null : request.WifiPassword.Trim();
        if (request.PosDeviceIp is not null)
            branch.PosDeviceIp = string.IsNullOrWhiteSpace(request.PosDeviceIp)
                ? null
                : request.PosDeviceIp.Trim();
        if (request.PosDevicePort.HasValue)
            branch.PosDevicePort = request.PosDevicePort.Value;

        branch.UpdatedAt = DateTime.UtcNow;
        await _db.SaveChangesAsync(ct);

        return Ok(new ApiResponse<BranchPrintSettingsDto>(true, ToDto(branch)));
    }

    private static BranchPrintSettingsDto ToDto(Branch b) => new(
        b.Id,
        b.ReceiptPrinterIp,
        b.ReceiptPrinterPort,
        b.KitchenPrinterIp,
        b.KitchenPrinterPort,
        b.PaperWidthMm is 58 or 80 ? b.PaperWidthMm : 80,
        b.AutoCutEnabled,
        b.ReceiptHeader,
        b.ReceiptFooter,
        b.WifiPassword,
        b.PosDeviceIp,
        b.PosDevicePort);
}
