using Microsoft.EntityFrameworkCore;
using Tiku.Application.Assets;
using Tiku.Application.Catalog;
using Tiku.Domain.Content;

namespace Tiku.Infrastructure.Assets;

public sealed partial class AssetManagementService
{
    public async Task<CatalogList<ContentImportJobItem>> GetImportJobsAsync(
        AssetManagementActor actor,
        ImportJobFilter filter,
        CancellationToken cancellationToken = default)
    {
        var query = dbContext.ContentImportJobs
            .AsNoTracking()
            .Where(job => job.TenantId == actor.TenantId);

        if (!string.IsNullOrWhiteSpace(filter.Status) &&
            Enum.TryParse<ContentImportStatus>(filter.Status, true, out var status))
            query = query.Where(job => job.Status == status);

        if (!string.IsNullOrWhiteSpace(filter.ImportType) &&
            Enum.TryParse<ContentImportType>(filter.ImportType, true, out var importType))
            query = query.Where(job => job.ImportType == importType);

        if (!string.IsNullOrWhiteSpace(filter.SourceFormat) &&
            Enum.TryParse<ImportSourceFormat>(filter.SourceFormat, true, out var sourceFormat))
            query = query.Where(job => job.SourceFormat == sourceFormat);

        var items = await query
            .OrderByDescending(job => job.CreatedAt)
            .Take(ResolveLimit(filter.Limit))
            .Select(job => ToJobItem(job))
            .ToArrayAsync(cancellationToken);

        return new CatalogList<ContentImportJobItem>(items);
    }

    public async Task<ContentImportJobDetail> GetImportJobAsync(
        AssetManagementActor actor,
        Guid jobId,
        CancellationToken cancellationToken = default)
    {
        var job = await dbContext.ContentImportJobs
            .AsNoTracking()
            .Where(item => item.TenantId == actor.TenantId && item.Id == jobId)
            .Select(item => ToJobItem(item))
            .SingleOrDefaultAsync(cancellationToken);

        if (job is null) throw new AssetManagementException("Import job was not found.", "import_job_not_found");

        var items = await dbContext.ContentImportItems
            .AsNoTracking()
            .Where(item => item.TenantId == actor.TenantId && item.JobId == jobId)
            .OrderBy(item => item.RowNo)
            .Take(MaxLimit)
            .Select(item => new ContentImportItemModel(
                item.Id,
                item.JobId,
                item.RowNo,
                item.ExternalId,
                item.Status,
                item.TargetType,
                item.TargetId,
                item.SourcePayload,
                item.NormalizedPayload,
                item.ContentHash,
                item.IssuesCount))
            .ToArrayAsync(cancellationToken);

        var issues = await dbContext.ContentImportIssues
            .AsNoTracking()
            .Where(issue => issue.TenantId == actor.TenantId && issue.JobId == jobId)
            .OrderBy(issue => issue.RowNo)
            .ThenBy(issue => issue.CreatedAt)
            .Take(MaxLimit)
            .Select(issue => new ContentImportIssueModel(
                issue.Id,
                issue.JobId,
                issue.ItemId,
                issue.RowNo,
                issue.Severity,
                issue.Code,
                issue.FieldPath,
                issue.Message,
                issue.Details))
            .ToArrayAsync(cancellationToken);

        return new ContentImportJobDetail(job, items, issues);
    }
}