using System.Text.Json;
using JobTrackerApi.Data;
using JobTrackerApi.Services.JobImport;
using JobTrackerApi.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

namespace JobTrackerApi.Services;

public sealed class JobEnrichmentHostedService(
    BackgroundTenantRunner tenants,
    IConfiguration configuration,
    ILogger<JobEnrichmentHostedService> logger,
    IStartupReadiness startupReadiness,
    TimeProvider timeProvider) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await startupReadiness.WaitUntilReadyAsync(stoppingToken);
        if (!configuration.GetValue("Workers:JobEnrichmentEnabled", false))
        {
            logger.LogInformation("Job enrichment worker disabled (Workers:JobEnrichmentEnabled=false).");
            return;
        }

        await Task.Delay(TimeSpan.FromSeconds(10), timeProvider, stoppingToken);
        while (!stoppingToken.IsCancellationRequested)
        {
            await RunOnceAsync(stoppingToken);
            await Task.Delay(TimeSpan.FromMinutes(10), timeProvider, stoppingToken);
        }
    }

    public Task<BackgroundWorkerRunResult> RunOnceAsync(CancellationToken cancellationToken)
    {
        if (!configuration.GetValue("Workers:JobEnrichmentEnabled", false))
            return Task.FromResult(BackgroundWorkerRunResult.Disabled);
        return tenants.RunForJobOwnersAsync("job-enrichment", ProcessOwnerAsync, cancellationToken);
    }

    private static async Task ProcessOwnerAsync(IServiceProvider services, CancellationToken cancellationToken)
    {
        var db = services.GetRequiredService<JobTrackerContext>();
        var userId = db.CurrentUserId;
        var users = services.GetRequiredService<UserManager<ApplicationUser>>();
        var user = string.IsNullOrWhiteSpace(userId) ? null : await users.FindByIdAsync(userId);
        var canUseAi = user is not null && user.AiEnabled && AccountPlans.ForRoles(await users.GetRolesAsync(user)).Ai;
        var summarizer = services.GetRequiredService<ISummarizerService>();
        var jobs = await db.JobApplications
            .Where(job => !job.IsDeleted)
            .Where(job => string.IsNullOrWhiteSpace(job.ShortSummary) || string.IsNullOrWhiteSpace(job.Tags))
            .OrderByDescending(job => job.DateApplied)
            .Take(20)
            .ToListAsync(cancellationToken);

        foreach (var job in jobs)
        {
            var sourceText = string.IsNullOrWhiteSpace(job.Description) ? job.Notes : job.Description;
            if (string.IsNullOrWhiteSpace(job.Tags) && !string.IsNullOrWhiteSpace(sourceText))
            {
                var tags = SkillTagger.Detect(sourceText)
                    .Distinct(StringComparer.OrdinalIgnoreCase)
                    .OrderBy(tag => tag, StringComparer.OrdinalIgnoreCase)
                    .ToList();
                if (tags.Count > 0) job.Tags = JsonSerializer.Serialize(tags);
            }

            if (canUseAi && string.IsNullOrWhiteSpace(job.ShortSummary) && !string.IsNullOrWhiteSpace(sourceText))
            {
                var summary = await summarizer.SummarizeAsync(sourceText, 160, 60);
                if (!string.IsNullOrWhiteSpace(summary)) job.ShortSummary = summary;
            }
        }

        await db.SaveChangesAsync(cancellationToken);
    }
}
