using Nexus.Api.Data;
using Nexus.Api.DTOs;
using Nexus.Api.Repositories;

namespace Nexus.Api.Services;

public sealed class ProjectService(
    IProjectRepository projectRepo,
    IActivityRepository activityRepo) : IProjectService
{
    public async Task<IReadOnlyList<Project>> GetAllAsync(CancellationToken ct = default)
        => await projectRepo.GetAllAsync(ct);

    public async Task<Project?> GetByIdAsync(Guid id, CancellationToken ct = default)
        => await projectRepo.GetByIdAsync(id, ct);

    public async Task<IReadOnlyList<WorkTask>> GetTasksAsync(
        Guid id,
        CancellationToken ct = default)
        => await projectRepo.GetTasksAsync(id, ct);

    public async Task<Project> CreateAsync(CreateProjectRequest request, CancellationToken ct = default)
    {
        var project = new Project
        {
            Name = request.Name.Trim(),
            Description = request.Description?.Trim() ?? string.Empty,
            Status = OperationalStatus.Online
        };
        await projectRepo.AddAsync(project, ct);
        await activityRepo.AddAsync(new ActivityEvent { Type = "project", Message = $"Project {project.Name} created" }, ct);
        return project;
    }

    public async Task<Project?> UpdateAsync(Guid id, UpdateProjectRequest request, CancellationToken ct = default)
    {
        var project = await projectRepo.GetByIdAsync(id, ct);
        if (project is null) return null;

        if (!string.IsNullOrWhiteSpace(request.Name))
            project.Name = request.Name.Trim();
        if (request.Description is not null)
            project.Description = request.Description.Trim();
        if (!string.IsNullOrWhiteSpace(request.Status) && Enum.TryParse<OperationalStatus>(request.Status, true, out var parsedStatus))
            project.Status = parsedStatus;

        await projectRepo.UpdateAsync(project, ct);
        await activityRepo.AddAsync(new ActivityEvent { Type = "project", Message = $"Project {project.Name} updated" }, ct);
        return project;
    }

    public async Task<ProjectDeleteResult> DeleteAsync(Guid id, CancellationToken ct = default)
    {
        var project = await projectRepo.GetByIdAsync(id, ct);
        if (project is null) return new ProjectDeleteResult(ProjectDeleteOutcome.NotFound);

        if (await projectRepo.HasTasksAsync(id, ct))
        {
            project.Status = OperationalStatus.Offline;
            await projectRepo.UpdateAsync(project, ct);
            await activityRepo.AddAsync(new ActivityEvent { Type = "project", Message = $"Project {project.Name} archived" }, ct);
            return new ProjectDeleteResult(ProjectDeleteOutcome.Archived, project);
        }

        await activityRepo.AddAsync(new ActivityEvent { Type = "project", Message = $"Project {project.Name} deleted" }, ct);
        await projectRepo.DeleteAsync(project, ct);
        return new ProjectDeleteResult(ProjectDeleteOutcome.Deleted, project);
    }
}
