using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OmsorgCore.Api.Contracts;
using OmsorgCore.Api.Security;
using OmsorgCore.Application.Services;
using OmsorgCore.Domain.Entities;
using OmsorgCore.Domain.Enums;

namespace OmsorgCore.Api.Controllers;

/// <summary>
/// Ansprechpartner sind eine 1:n-Unterressource von Facility (REQUIREMENTS.md FR-EIN-2) — kein
/// eigenständiges Core-Objekt, daher unter /api/facilities/{facilityId}/contacts und mit den
/// gleichen Facilities-Rechten gegated statt einem eigenen ModuleType.
/// </summary>
[ApiController]
[Authorize]
[Route("api/facilities/{facilityId:guid}/contacts")]
public class FacilityContactsController : ControllerBase
{
    private readonly IFacilityService _facilityService;
    private readonly IFacilityContactService _facilityContactService;

    public FacilityContactsController(IFacilityService facilityService, IFacilityContactService facilityContactService)
    {
        _facilityService = facilityService;
        _facilityContactService = facilityContactService;
    }

    [HttpGet]
    [RequirePermission(ModuleType.Facilities, PermissionAction.View)]
    public async Task<ActionResult<IReadOnlyList<FacilityContactResponse>>> GetAll(Guid facilityId, CancellationToken cancellationToken)
    {
        if (await _facilityService.GetByIdAsync(facilityId, cancellationToken) is null)
        {
            return NotFound();
        }

        var contacts = await _facilityContactService.GetByFacilityIdAsync(facilityId, cancellationToken);
        return Ok(contacts.Select(ToResponse).ToList());
    }

    [HttpPost]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Create)]
    public async Task<ActionResult<FacilityContactResponse>> Create(Guid facilityId, CreateFacilityContactRequest request, CancellationToken cancellationToken)
    {
        if (await _facilityService.GetByIdAsync(facilityId, cancellationToken) is null)
        {
            return NotFound();
        }

        var fieldError = ValidateRequest(request.Name, request.Role, request.Department, request.PhoneNumber, request.Email, request.Notes);
        if (fieldError is not null)
        {
            return BadRequest(fieldError);
        }

        var contact = new FacilityContact
        {
            FacilityId = facilityId,
            Name = request.Name,
            Role = request.Role,
            Department = request.Department,
            PhoneNumber = request.PhoneNumber,
            Email = request.Email,
            Notes = request.Notes
        };

        var created = await _facilityContactService.CreateAsync(contact, cancellationToken);
        return CreatedAtAction(nameof(GetAll), new { facilityId }, ToResponse(created));
    }

    [HttpPut("{id:guid}")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Edit)]
    public async Task<ActionResult<FacilityContactResponse>> Update(Guid facilityId, Guid id, UpdateFacilityContactRequest request, CancellationToken cancellationToken)
    {
        var existing = await _facilityContactService.GetByIdAsync(id, cancellationToken);
        if (existing is null || existing.FacilityId != facilityId)
        {
            return NotFound();
        }

        var fieldError = ValidateRequest(request.Name, request.Role, request.Department, request.PhoneNumber, request.Email, request.Notes);
        if (fieldError is not null)
        {
            return BadRequest(fieldError);
        }

        var updates = new FacilityContact
        {
            Name = request.Name,
            Role = request.Role,
            Department = request.Department,
            PhoneNumber = request.PhoneNumber,
            Email = request.Email,
            Notes = request.Notes
        };

        var updated = await _facilityContactService.UpdateAsync(id, updates, cancellationToken);
        return updated is null ? NotFound() : Ok(ToResponse(updated));
    }

    [HttpDelete("{id:guid}")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Delete)]
    public async Task<IActionResult> Delete(Guid facilityId, Guid id, CancellationToken cancellationToken)
    {
        var existing = await _facilityContactService.GetByIdAsync(id, cancellationToken);
        if (existing is null || existing.FacilityId != facilityId)
        {
            return NotFound();
        }

        var deleted = await _facilityContactService.DeleteAsync(id, cancellationToken);
        return deleted ? NoContent() : NotFound();
    }

    private static string? ValidateRequest(string name, string? role, string? department, string? phoneNumber, string? email, string? notes)
    {
        if (string.IsNullOrWhiteSpace(name) || name.Length > 200)
        {
            return "Name ist erforderlich und darf maximal 200 Zeichen lang sein.";
        }

        if (role is { Length: > 100 })
        {
            return "Role darf maximal 100 Zeichen lang sein.";
        }

        if (department is { Length: > 100 })
        {
            return "Department darf maximal 100 Zeichen lang sein.";
        }

        if (phoneNumber is { Length: > 50 })
        {
            return "PhoneNumber darf maximal 50 Zeichen lang sein.";
        }

        if (email is { Length: > 200 })
        {
            return "Email darf maximal 200 Zeichen lang sein.";
        }

        if (notes is { Length: > 1000 })
        {
            return "Notes darf maximal 1000 Zeichen lang sein.";
        }

        return null;
    }

    private static FacilityContactResponse ToResponse(FacilityContact contact)
        => new(
            contact.Id,
            contact.FacilityId,
            contact.Name,
            contact.Role,
            contact.Department,
            contact.PhoneNumber,
            contact.Email,
            contact.Notes);
}
