using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using MTWorkHR.Core.Email;
using MTWorkHR.Core.Global;
using MTWorkHR.Core.IRepositories.Base;
using MTWorkHR.Core.IRepositories;
using MTWorkHR.Core.UnitOfWork;
using MTWorkHR.Infrastructure.DBContext;
using MTWorkHR.Infrastructure.EmailService;
using MTWorkHR.Infrastructure.Repositories;
using MTWorkHR.Infrastructure.UnitOfWorks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MTWorkHR.Infrastructure.Entities;
using Microsoft.Extensions.Options;

namespace MTWorkHR.Infrastructure
{
    public static class InfrastructureServiceRegistration
    {
        public static IServiceCollection AddInfrastructureIdentityServices(this IServiceCollection services, AppSettingsConfiguration config)
        {
            services.AddSingleton(config);

            
            services.AddDbContext<HRDataContext>(options =>
                options.UseSqlServer(
                    config.ConnectionStrings.MTWorkHRConnectionString  //configuration.GetSection("ConnectionString:MTWorkHRConnectionString").Value
                    ));
           
            services.AddIdentity<ApplicationUser, ApplicationRole>().AddEntityFrameworkStores<HRDataContext>().AddDefaultTokenProviders();

           

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero,
                    ValidIssuer = config.JwtSettings.Issuer,
                    ValidAudience = config.JwtSettings.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.JwtSettings.SecretKey))
                };

                // This is the important part to allow SignalR to work with JWT tokens
                options.Events = new JwtBearerEvents
                {
                    OnMessageReceived = context =>
                    {
                        var accessToken = context.Request.Query["access_token"];
                        if (!string.IsNullOrEmpty(accessToken) &&
                            (context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream"))
                        {
                            context.Token = accessToken;
                        }
                        return Task.CompletedTask;
                    }
                };
            });


            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
            services.AddScoped(typeof(IRepositoryLog<>), typeof(RepositoryLog<>));
            services.AddScoped(typeof(ICompanyRepository), typeof(CompanyRepository));

            services.AddScoped(typeof(IProjectRepository), typeof(ProjectRepository));
            services.AddScoped(typeof(ITaskStatusRepository), typeof(TaskStatusRepository));
            services.AddScoped(typeof(IUserTaskRepository), typeof(UserTaskRepository));
            services.AddScoped(typeof(IUserTaskAttachmentRepository), typeof(UserTaskAttachmentRepository));
            services.AddScoped(typeof(IUserTaskHistoryRepository), typeof(UserTaskHistoryRepository));
            
            services.AddScoped(typeof(ITeamRepository), typeof(TeamRepository));
            services.AddScoped(typeof(ITeamUserRepository), typeof(TeamUserRepository));
            services.AddScoped(typeof(IMeetingRepository), typeof(MeetingRepository));
            services.AddScoped(typeof(IMeetingUserRepository), typeof(MeetingUserRepository));
            services.AddScoped(typeof(IAttendanceRepository), typeof(AttendanceRepository));
            services.AddScoped(typeof(IOrderAllocationRepository), typeof(OrderAllocationRepository));
            services.AddScoped(typeof(IOrderRequestRepository), typeof(OrderRequestRepository));
            services.AddScoped(typeof(IOrderTypeRepository), typeof(OrderTypeRepository));
            services.AddScoped(typeof(ILeaveTypeRepository), typeof(LeaveTypeRepository));
            services.AddScoped(typeof(ICountryLookupRepository), typeof(CountryLookupRepository));
            services.AddScoped(typeof(IIndustryRepository), typeof(IndustryRepository));
            services.AddScoped(typeof(IJobTitleRepository), typeof(JobTitleRepository));
            services.AddScoped(typeof(IQualificationRepository), typeof(QualificationRepository));
            services.AddScoped(typeof(IUniversityRepository), typeof(UniversityRepository));
            services.AddScoped(typeof(ILoginOTPRepository), typeof(LoginOTPRepository));
            services.AddScoped(typeof(ICityRepository), typeof(CityRepository));
            services.AddScoped(typeof(IProjectTeamRepository), typeof(ProjectTeamRepository));
            services.AddScoped(typeof(IChatMessageRepository), typeof(ChatMessageRepository));
            services.AddScoped(typeof(IContractRepository), typeof(ContractRepository));
            services.AddScoped(typeof(IContractTaskAttachmentRepository), typeof(ContractTaskAttachmentRepository));
            services.AddScoped(typeof(IProjectStageAttachmentRepository), typeof(ProjectStageAttachmentRepository));
            services.AddScoped(typeof(ISubscriptionConfigurationRepository), typeof(SubscriptionConfigurationRepository));
            services.AddScoped(typeof(IInvoiceRepository), typeof(InvoiceRepository));
            services.AddScoped(typeof(IJobInterviewRepository), typeof(JobInterviewRepository));

            services.AddScoped(typeof(IHubConnectionRepository), typeof(HubConnectionRepository));
            

            services.AddScoped(typeof(IPermissionRepository), typeof(PermissionRepository));
            services.AddScoped(typeof(IRolePermissionRepository<RolePermission>), typeof(RolePermissionRepository));
            services.AddScoped(typeof(IUserRoleRepository<IdentityUserRole<string>>), typeof(UserRoleRepository));

            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped<IUnitOfWorkLog, UnitOfWorkLog>();
            services.AddTransient<IMailSender, MailSender>();
            services.AddScoped<ApplicationUserManager>();
            services.AddScoped<GlobalInfo>();


            //services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
            return services;
        }
    }
}
