using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Haoliang.Models.Template;
using Haoliang.Data.Repositories;
using Haoliang.Data.Entities;

namespace Haoliang.Data.Repositories
{
    public interface ITemplateRepository : IRepository<CNCBrandTemplate>
    {
        Task<CNCBrandTemplate> GetByBrandNameAsync(string brandName);
        Task<IEnumerable<CNCBrandTemplate>> GetEnabledTemplatesAsync();
        Task<bool> TemplateExistsAsync(string brandName);
        Task UpdateTemplateEnabledAsync(int templateId, bool isEnabled);
        Task<IEnumerable<CNCBrandTemplate>> GetTemplatesByFieldAsync(string standardFieldId);
        Task<bool> IsFieldMappedAsync(int templateId, string standardFieldId);
    }

    public class TemplateRepository : Repository<CNCBrandTemplate>, ITemplateRepository
    {
        private readonly CNCDbContext _context;

        public TemplateRepository(CNCDbContext context) : base(context)
        {
            _context = context;
        }

        public async Task<CNCBrandTemplate> GetByBrandNameAsync(string brandName)
        {
            return await _context.CNCTemplates
                .FirstOrDefaultAsync(t => t.BrandName == brandName);
        }

        public async Task<IEnumerable<CNCBrandTemplate>> GetEnabledTemplatesAsync()
        {
            return await _context.CNCTemplates
                .Where(t => t.IsEnabled)
                .OrderBy(t => t.BrandName)
                .ToListAsync();
        }

        public async Task<bool> TemplateExistsAsync(string brandName)
        {
            return await _context.CNCTemplates
                .AnyAsync(t => t.BrandName == brandName);
        }

        public async Task UpdateTemplateEnabledAsync(int templateId, bool isEnabled)
        {
            var template = await GetByIdAsync(templateId);
            if (template != null)
            {
                template.IsEnabled = isEnabled;
                template.UpdatedAt = DateTime.Now;
                
                Update(template);
                await SaveAsync();
            }
        }

        public async Task<IEnumerable<CNCBrandTemplate>> GetTemplatesByFieldAsync(string standardFieldId)
        {
            return await _context.CNCTemplates
                .Where(t => t.IsEnabled && t.FieldMappings.Any(f => f.StandardFieldId == standardFieldId))
                .OrderBy(t => t.BrandName)
                .ToListAsync();
        }

        public async Task<bool> IsFieldMappedAsync(int templateId, string standardFieldId)
        {
            var template = await GetByIdAsync(templateId);
            return template != null && template.FieldMappings.Any(f => f.StandardFieldId == standardFieldId);
        }
    }

    public interface ITemplateFieldMappingRepository : IRepository<TemplateFieldMapping>
    {
        Task<IEnumerable<TemplateFieldMapping>> GetByTemplateIdAsync(int templateId);
        Task<TemplateFieldMapping> GetByTemplateAndFieldAsync(int templateId, string standardFieldId);
        Task<bool> DeleteByTemplateIdAsync(int templateId);
        Task<int> CountMappingsByTemplateIdAsync(int templateId);
        Task<IEnumerable<TemplateFieldMapping>> GetMappingsByDataTypeAsync(string dataType);
    }

    public class TemplateFieldMappingRepository : Repository<TemplateFieldMapping>, ITemplateFieldMappingRepository
    {
        private readonly CNCDbContext _context;

        public TemplateFieldMappingRepository(CNCDbContext context) : base(context)
        {
            _context = context;
        }

        public async Task<IEnumerable<TemplateFieldMapping>> GetByTemplateIdAsync(int templateId)
        {
            return await _context.TemplateFieldMappings
                .Where(tf => tf.TemplateId == templateId)
                .OrderBy(tf => tf.StandardFieldId)
                .ToListAsync();
        }

        public async Task<TemplateFieldMapping> GetByTemplateAndFieldAsync(int templateId, string standardFieldId)
        {
            return await _context.TemplateFieldMappings
                .FirstOrDefaultAsync(tf => tf.TemplateId == templateId && tf.StandardFieldId == standardFieldId);
        }

        public async Task<bool> DeleteByTemplateIdAsync(int templateId)
        {
            var mappings = await GetByTemplateIdAsync(templateId);
            if (mappings.Any())
            {
                RemoveRange(mappings);
                await SaveAsync();
                return true;
            }
            return false;
        }

        public async Task<int> CountMappingsByTemplateIdAsync(int templateId)
        {
            return await _context.TemplateFieldMappings
                .CountAsync(tf => tf.TemplateId == templateId);
        }

        public async Task<IEnumerable<TemplateFieldMapping>> GetMappingsByDataTypeAsync(string dataType)
        {
            return await _context.TemplateFieldMappings
                .Where(tf => tf.DataType == dataType)
                .OrderBy(tf => tf.TemplateId)
                .ThenBy(tf => tf.StandardFieldId)
                .ToListAsync();
        }
    }
}