using ConfigurationPannel.Services;
using Inspectron.Epson;
using Inspectron.Epson.PrintServer.ConfigurationSources;
using Inspectron.Epson.PrintServer.PrintServices;
using Inspectron.Epson.PrintServer.WorkAreaSources;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Reflection;
using ConfigurationManager = ConfigurationPannel.Services.ConfigurationManager;

namespace ConfigurationPannel.Pages;

[Authorize]
public class ConfigureModel : PageModel
{
    private readonly ConfigurationManager _configManager;
    private readonly PrintServerHostedService _printServerService;
    private readonly LogoService _logoService;
    private readonly IWebHostEnvironment _env;
    private readonly DiscoveryService _discoveryService;
    private readonly ILogger<ConfigureModel> _logger;

    public ConfigureModel(
        ConfigurationManager configManager,
        PrintServerHostedService printServerService,
        LogoService logoService,
        IWebHostEnvironment env,
        ILogger<ConfigureModel> logger)
    {
        _configManager = configManager;
        _printServerService = printServerService;
        _logoService = logoService;
        _env = env;
        _discoveryService = new DiscoveryService();
        _logger = logger;
    }

    public List<WorkArea> WorkAreas { get; set; } = new();
    public List<DiscoveredPrinter> DiscoveredPrinters { get; set; } = new();
    public Dictionary<string, PrinterConfiguration> CurrentAssignments { get; set; } = new();
    public List<string> AvailableLogos { get; set; } = new();

    [BindProperty]
    public List<WorkAreaAssignment> WorkAreaAssignments { get; set; } = new();

    [BindProperty]
    public IFormFile? UploadedLogo { get; set; }

    public string SuccessMessage { get; set; } = string.Empty;
    public string ErrorMessage { get; set; } = string.Empty;

    public async Task<IActionResult> OnGetAsync()
    {
        try
        {
            // Load current configuration
            var config = await _configManager.LoadConfigurationAsync();

            // Get work areas from API
            var workAreaSource = new JamesWorkAreaSource(config);
            WorkAreas = await workAreaSource.GetWorkAreasAsync();

            // Map current assignments
            CurrentAssignments = config.PrinterConfigurations
                .GroupBy(kv => kv.Value.AreaId)
                .ToDictionary(g => g.Key, g => g.First().Value);

            // Initial discovery (quick timeout for page load)
            DiscoveredPrinters = await _discoveryService.DiscoverPrintersAsync(TimeSpan.FromSeconds(3));
            
            // Load available logos
            AvailableLogos = _logoService.GetAllLogos();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error loading configuration page");
            ErrorMessage = "Error loading configuration: " + ex.Message;
        }

        return Page();
    }

    public async Task<IActionResult> OnPostDiscoverAsync()
    {
        try
        {
            var printers = await _discoveryService.DiscoverPrintersAsync(TimeSpan.FromSeconds(5));
            
            return new JsonResult(printers.Select(p => new
            {
                ipAddress = p.IPAddress,
                modelName = p.ModelName,
                macAddress = p.MACAddress
            }));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error discovering printers");
            return new JsonResult(new { error = ex.Message }) { StatusCode = 500 };
        }
    }

    public async Task<IActionResult> OnPostUploadLogoAsync()
    {
        try
        {
            if (UploadedLogo != null)
            {
                var filename = await _logoService.SaveLogoAsync(UploadedLogo);
                SuccessMessage = $"Logo uploaded successfully: {filename}";
            }
            else
            {
                ErrorMessage = "No file selected";
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error uploading logo");
            ErrorMessage = "Error uploading logo: " + ex.Message;
        }

        return await OnGetAsync();
    }

    public async Task<IActionResult> OnPostCleanLogosAsync()
    {
        try
        {
            var config = await _configManager.LoadConfigurationAsync();
            var usedLogos = config.PrinterConfigurations.Values
                .Select(p => p.LogoFilename)
                .Where(f => !string.IsNullOrEmpty(f))
                .ToList();

            var cleanedLogos = _logoService.CleanUnusedLogos(usedLogos!);

            if (cleanedLogos.Any())
            {
                SuccessMessage = $"Cleaned {cleanedLogos.Count} unused logo(s): {string.Join(", ", cleanedLogos)}";
            }
            else
            {
                SuccessMessage = "No unused logos found";
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error cleaning logos");
            ErrorMessage = "Error cleaning logos: " + ex.Message;
        }

        return await OnGetAsync();
    }

    public async Task<IActionResult> OnPostSaveAsync()
    {
        try
        {
            // Load current config
            var config = await _configManager.LoadConfigurationAsync();

            // Clear existing printer configurations
            var newPrinterConfigurations = new Dictionary<string, PrinterConfiguration>();

            // Build new configurations from assignments
            foreach (var assignment in WorkAreaAssignments)
            {
                if (!string.IsNullOrEmpty(assignment.PrinterAddress))
                {
                    var printerKey = assignment.PrinterAddress;

                    if (!newPrinterConfigurations.ContainsKey(printerKey))
                    {
                        newPrinterConfigurations[printerKey] = new PrinterConfiguration
                        {
                            Address = assignment.PrinterAddress,
                            AreaId = assignment.WorkAreaId,
                            FontSize = assignment.FontSize,
                            LogoFilename = assignment.LogoFilename
                        };

                        // Copy logo to printer service directory
                        if (!string.IsNullOrEmpty(assignment.LogoFilename))
                        {
                            var printerServicePath = Path.Combine("logos");
                            _logoService.CopyLogoToDirectory(assignment.LogoFilename, printerServicePath);
                        }
                    }
                }
            }

            // Update configuration
            config.PrinterConfigurations = newPrinterConfigurations;

            // Save configuration
            await _configManager.SaveConfigurationAsync(config);

            // Restart PrintLoop with new configuration
            await _printServerService.RestartAsync();

            SuccessMessage = "Configuration saved and print server restarted successfully!";
            _logger.LogInformation("Configuration saved successfully");

            // Reload page data
            return await OnGetAsync();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error saving configuration");
            ErrorMessage = "Error saving configuration: " + ex.Message;
            return await OnGetAsync();
        }
    }
}

public class WorkAreaAssignment
{
    public string WorkAreaId { get; set; } = string.Empty;
    public string WorkAreaName { get; set; } = string.Empty;
    public string PrinterAddress { get; set; } = string.Empty;
    public int FontSize { get; set; } = 1;
    public string? LogoFilename { get; set; }
}
