using System;
using System.IO;
using System.Threading.Tasks;
using Hangfire;
using Hangfire.LiteDB;
using LittleShop.Client.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
using TeleBot;
using TeleBot.Handlers;
using TeleBot.Services;

var builder = Host.CreateApplicationBuilder(args);
public static string BrandName ?? "Little Shop";
// Configuration
builder.Configuration
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
    .AddEnvironmentVariables();

// Serilog
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("logs/telebot-.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Logging.ClearProviders();
builder.Logging.AddSerilog();

// Services
builder.Services.AddSingleton<IPrivacyService, PrivacyService>();
builder.Services.AddSingleton<SessionManager>();
builder.Services.AddSingleton<ISessionManager>(provider => provider.GetRequiredService<SessionManager>());
builder.Services.AddHostedService<SessionManager>(provider => provider.GetRequiredService<SessionManager>());

// LittleShop Client
builder.Services.AddLittleShopClient(options =>
{
    var config = builder.Configuration;
    options.BaseUrl = config["LittleShop:ApiUrl"] ?? "https://localhost:5001";
    options.TimeoutSeconds = 30;
    options.MaxRetryAttempts = 3;

    BrandName = config["LittleShop.BrandName"] ?? "Little Shop";
});

builder.Services.AddSingleton<ILittleShopService, LittleShopService>();

// Redis (if enabled)
if (builder.Configuration.GetValue<bool>("Redis:Enabled"))
{
    builder.Services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = builder.Configuration["Redis:ConnectionString"] ?? "localhost:6379";
        options.InstanceName = builder.Configuration["Redis:InstanceName"] ?? "TeleBot";
    });
}

// Hangfire (if enabled)
if (builder.Configuration.GetValue<bool>("Hangfire:Enabled"))
{
    var hangfireDb = builder.Configuration["Hangfire:DatabasePath"] ?? "hangfire.db";
    builder.Services.AddHangfire(config =>
    {
        config.UseLiteDbStorage(hangfireDb);
    });
    builder.Services.AddHangfireServer();
}

// Bot Handlers
builder.Services.AddSingleton<ICommandHandler, CommandHandler>();
builder.Services.AddSingleton<ICallbackHandler, CallbackHandler>();
builder.Services.AddSingleton<IMessageHandler, MessageHandler>();

// Bot Manager Service (for registration and metrics)
builder.Services.AddHttpClient<BotManagerService>();
builder.Services.AddSingleton<BotManagerService>();
builder.Services.AddHostedService<BotManagerService>();

// Message Delivery Service - Single instance
builder.Services.AddSingleton<MessageDeliveryService>();
builder.Services.AddSingleton<IMessageDeliveryService>(sp => sp.GetRequiredService<MessageDeliveryService>());
builder.Services.AddHostedService<MessageDeliveryService>(sp => sp.GetRequiredService<MessageDeliveryService>());

// Product Carousel Service
builder.Services.AddHttpClient<ProductCarouselService>();
builder.Services.AddSingleton<IProductCarouselService, ProductCarouselService>();

// Bot Service
builder.Services.AddHostedService<TelegramBotService>();

// Build and run
var host = builder.Build();

try
{
    Log.Information("Starting TeleBot - Privacy-First E-Commerce Bot");
    Log.Information("Privacy Mode: {PrivacyMode}", builder.Configuration["Privacy:Mode"]);
    Log.Information("Ephemeral by Default: {Ephemeral}", builder.Configuration["Privacy:EphemeralByDefault"]);
    Log.Information("Tor Enabled: {Tor}", builder.Configuration["Privacy:EnableTor"]);
    
    await host.RunAsync();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application start-up failed");
}
finally
{
    Log.CloseAndFlush();
}