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>
/// Papierkorb: listet und stellt soft-gelöschte Datensätze der 5 Core-Objekte mit vollem CRUD
/// wieder her. Reine API-Gruppierung für die Papierkorb-Seite in omsorgapp — kein eigener
/// ModuleType/eigenes Recht, jede Route ist über das Recht des jeweiligen Objekts gegated
/// (z. B. ModuleType.Employees + PermissionAction.Recover), analog zu den bestehenden
/// Delete-Endpoints in EmployeesController/FacilitiesController/etc.
/// </summary>
[ApiController]
[Authorize]
[Route("api/trash")]
public class TrashController : ControllerBase
{
    private readonly IEmployeeService _employeeService;
    private readonly IFacilityService _facilityService;
    private readonly IContractService _contractService;
    private readonly IOrderService _orderService;
    private readonly IFacilityContactService _facilityContactService;
    private readonly IFacilityQualificationRateService _facilityQualificationRateService;
    private readonly IEmployeeFacilityDistanceService _employeeFacilityDistanceService;
    private readonly IAbsenceService _absenceService;
    private readonly ITimeEntryService _timeEntryService;
    private readonly IAssignmentService _assignmentService;

    public TrashController(
        IEmployeeService employeeService,
        IFacilityService facilityService,
        IContractService contractService,
        IOrderService orderService,
        IFacilityContactService facilityContactService,
        IFacilityQualificationRateService facilityQualificationRateService,
        IEmployeeFacilityDistanceService employeeFacilityDistanceService,
        IAbsenceService absenceService,
        ITimeEntryService timeEntryService,
        IAssignmentService assignmentService)
    {
        _employeeService = employeeService;
        _facilityService = facilityService;
        _contractService = contractService;
        _orderService = orderService;
        _facilityContactService = facilityContactService;
        _facilityQualificationRateService = facilityQualificationRateService;
        _employeeFacilityDistanceService = employeeFacilityDistanceService;
        _absenceService = absenceService;
        _timeEntryService = timeEntryService;
        _assignmentService = assignmentService;
    }

    [HttpGet("employees")]
    [RequirePermission(ModuleType.Employees, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashEmployeeResponse>>> GetDeletedEmployees([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var employees = await _employeeService.GetDeletedAsync(search, cancellationToken);
        return Ok(employees.Select(e => new TrashEmployeeResponse(e.Id, e.FirstName, e.LastName, e.DeletedAt)).ToList());
    }

    [HttpPost("employees/{id:guid}/restore")]
    [RequirePermission(ModuleType.Employees, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreEmployee(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _employeeService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("facilities")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashFacilityResponse>>> GetDeletedFacilities([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var facilities = await _facilityService.GetDeletedAsync(search, cancellationToken);
        return Ok(facilities.Select(f => new TrashFacilityResponse(f.Id, f.Name, f.DeletedAt)).ToList());
    }

    [HttpPost("facilities/{id:guid}/restore")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreFacility(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _facilityService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("contracts")]
    [RequirePermission(ModuleType.Contracts, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashContractResponse>>> GetDeletedContracts([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var contracts = await _contractService.GetDeletedAsync(search, cancellationToken);
        return Ok(contracts.Select(c => new TrashContractResponse(c.Id, c.ContractType, c.DeletedAt)).ToList());
    }

    [HttpPost("contracts/{id:guid}/restore")]
    [RequirePermission(ModuleType.Contracts, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreContract(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _contractService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("orders")]
    [RequirePermission(ModuleType.Orders, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashOrderResponse>>> GetDeletedOrders([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var orders = await _orderService.GetDeletedAsync(search, cancellationToken);
        return Ok(orders.Select(o => new TrashOrderResponse(o.Id, o.RequiredQualification, o.DeletedAt)).ToList());
    }

    [HttpPost("orders/{id:guid}/restore")]
    [RequirePermission(ModuleType.Orders, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreOrder(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _orderService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("facility-contacts")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashFacilityContactResponse>>> GetDeletedFacilityContacts([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var contacts = await _facilityContactService.GetDeletedAsync(search, cancellationToken);
        return Ok(contacts.Select(c => new TrashFacilityContactResponse(c.Id, c.FacilityId, c.Name, c.DeletedAt)).ToList());
    }

    [HttpPost("facility-contacts/{id:guid}/restore")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreFacilityContact(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _facilityContactService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("facility-qualification-rates")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashFacilityQualificationRateResponse>>> GetDeletedFacilityQualificationRates([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var rates = await _facilityQualificationRateService.GetDeletedAsync(search, cancellationToken);
        return Ok(rates.Select(r => new TrashFacilityQualificationRateResponse(r.Id, r.FacilityId, r.Qualification, r.DeletedAt)).ToList());
    }

    [HttpPost("facility-qualification-rates/{id:guid}/restore")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreFacilityQualificationRate(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _facilityQualificationRateService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("employee-facility-distances")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashEmployeeFacilityDistanceResponse>>> GetDeletedEmployeeFacilityDistances([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var distances = await _employeeFacilityDistanceService.GetDeletedAsync(search, cancellationToken);
        return Ok(distances.Select(d => new TrashEmployeeFacilityDistanceResponse(d.Id, d.FacilityId, d.EmployeeId, d.DistanceKm, d.DeletedAt)).ToList());
    }

    [HttpPost("employee-facility-distances/{id:guid}/restore")]
    [RequirePermission(ModuleType.Facilities, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreEmployeeFacilityDistance(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _employeeFacilityDistanceService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("absences")]
    [RequirePermission(ModuleType.Absences, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashAbsenceResponse>>> GetDeletedAbsences([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var absences = await _absenceService.GetDeletedAsync(search, cancellationToken);
        return Ok(absences.Select(a => new TrashAbsenceResponse(a.Id, a.Type, a.DeletedAt)).ToList());
    }

    [HttpPost("absences/{id:guid}/restore")]
    [RequirePermission(ModuleType.Absences, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreAbsence(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _absenceService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("time-entries")]
    [RequirePermission(ModuleType.TimeEntries, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashTimeEntryResponse>>> GetDeletedTimeEntries([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var timeEntries = await _timeEntryService.GetDeletedAsync(search, cancellationToken);
        return Ok(timeEntries.Select(t => new TrashTimeEntryResponse(t.Id, t.Date, t.DeletedAt)).ToList());
    }

    [HttpPost("time-entries/{id:guid}/restore")]
    [RequirePermission(ModuleType.TimeEntries, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreTimeEntry(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _timeEntryService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }

    [HttpGet("assignments")]
    [RequirePermission(ModuleType.Assignments, PermissionAction.Recover)]
    public async Task<ActionResult<IReadOnlyList<TrashAssignmentResponse>>> GetDeletedAssignments([FromQuery] string? search, CancellationToken cancellationToken)
    {
        var assignments = await _assignmentService.GetDeletedAsync(search, cancellationToken);
        return Ok(assignments.Select(a => new TrashAssignmentResponse(a.Id, a.Employee.FirstName, a.Employee.LastName, a.DeletedAt)).ToList());
    }

    [HttpPost("assignments/{id:guid}/restore")]
    [RequirePermission(ModuleType.Assignments, PermissionAction.Recover)]
    public async Task<IActionResult> RestoreAssignment(Guid id, CancellationToken cancellationToken)
    {
        var restored = await _assignmentService.RestoreAsync(id, cancellationToken);
        return restored ? NoContent() : NotFound();
    }
}
