using BookReader.Models;
using BookReader.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Maui.Graphics;

namespace BookReader.ViewModels;

public partial class SettingsViewModel : BaseViewModel
{
    private static readonly Color SuccessTone = Color.FromArgb("#2F7D5A");
    private static readonly Color WarningTone = Color.FromArgb("#C47A3E");
    private static readonly Color DangerTone = Color.FromArgb("#B64932");
    private static readonly Color NeutralTone = Color.FromArgb("#6E5648");

    private readonly ISettingsService _settingsService;
    private readonly ICalibreWebService _calibreWebService;
    private readonly INavigationService _navigationService;

    [ObservableProperty]
    private string _calibreUrl = string.Empty;

    [ObservableProperty]
    private string _calibreUsername = string.Empty;

    [ObservableProperty]
    private string _calibrePassword = string.Empty;

    [ObservableProperty]
    private int _defaultFontSize = Constants.Reader.DefaultFontSize;

    [ObservableProperty]
    private string _defaultFontFamily = "serif";

    [ObservableProperty]
    private string _defaultReaderTheme = "Тёплая";

    [ObservableProperty]
    private double _defaultBrightness = Constants.Reader.DefaultBrightness;

    [ObservableProperty]
    private string _connectionStatus = string.Empty;

    [ObservableProperty]
    private Color _connectionStatusColor = NeutralTone;

    [ObservableProperty]
    private string _connectionSecurityHint = string.Empty;

    [ObservableProperty]
    private Color _connectionSecurityColor = NeutralTone;

    [ObservableProperty]
    private bool _isConnectionTesting;

    public List<string> AvailableFonts { get; } = new()
    {
        "serif", "sans-serif", "monospace", "Georgia", "Palatino",
        "Times New Roman", "Arial", "Verdana", "Courier New"
    };

    public List<int> AvailableFontSizes { get; } = new()
    {
        12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 36, 40
    };

    public List<string> AvailableReaderThemes { get; } = new()
    {
        "Тёплая",
        "Светлая",
        "Тёмная"
    };

    partial void OnCalibreUrlChanged(string value)
    {
        UpdateConnectionSecurityHint();
    }

    public SettingsViewModel(
        ISettingsService settingsService,
        ICalibreWebService calibreWebService,
        INavigationService navigationService)
    {
        _settingsService = settingsService;
        _calibreWebService = calibreWebService;
        _navigationService = navigationService;
        Title = "Настройки";
    }

    [RelayCommand]
    public async Task LoadSettingsAsync()
    {
        CalibreUrl = await _settingsService.GetAsync(SettingsKeys.CalibreUrl);
        CalibreUsername = await _settingsService.GetAsync(SettingsKeys.CalibreUsername);
        CalibrePassword = await _settingsService.GetSecurePasswordAsync();
        DefaultFontSize = await _settingsService.GetIntAsync(SettingsKeys.DefaultFontSize, Constants.Reader.DefaultFontSize);
        DefaultFontFamily = await _settingsService.GetAsync(SettingsKeys.DefaultFontFamily, "serif");
        DefaultReaderTheme = ToDisplayTheme(await _settingsService.GetAsync(SettingsKeys.Theme, Constants.Reader.DefaultTheme));
        DefaultBrightness = await _settingsService.GetDoubleAsync(SettingsKeys.Brightness, Constants.Reader.DefaultBrightness);

        UpdateConnectionSecurityHint();
    }

    [RelayCommand]
    public async Task SaveSettingsAsync()
    {
        await PersistSettingsAsync(showNotification: true);
    }

    public async Task SaveSilentlyAsync()
    {
        await PersistSettingsAsync(showNotification: false);
    }

    [RelayCommand]
    public async Task TestConnectionAsync()
    {
        if (!TryValidateCalibreUrl(out var validationMessage))
        {
            ConnectionStatus = validationMessage;
            ConnectionStatusColor = DangerTone;
            return;
        }

        IsConnectionTesting = true;
        ConnectionStatus = "Проверяю соединение...";
        ConnectionStatusColor = NeutralTone;

        try
        {
            var success = await _calibreWebService.TestConnectionAsync(CalibreUrl, CalibreUsername, CalibrePassword);
            ConnectionStatus = success ? "Соединение установлено." : "Сервер ответил ошибкой или недоступен.";
            ConnectionStatusColor = success ? SuccessTone : DangerTone;
        }
        catch (Exception ex)
        {
            ConnectionStatus = $"Ошибка проверки: {ex.Message}";
            ConnectionStatusColor = DangerTone;
        }
        finally
        {
            IsConnectionTesting = false;
        }
    }

    private async Task PersistSettingsAsync(bool showNotification)
    {
        await _settingsService.SetAsync(SettingsKeys.CalibreUrl, CalibreUrl);
        await _settingsService.SetAsync(SettingsKeys.CalibreUsername, CalibreUsername);
        await _settingsService.SetSecurePasswordAsync(CalibrePassword);
        await _settingsService.SetIntAsync(SettingsKeys.DefaultFontSize, DefaultFontSize);
        await _settingsService.SetAsync(SettingsKeys.DefaultFontFamily, DefaultFontFamily);
        await _settingsService.SetAsync(SettingsKeys.Theme, ToStoredTheme(DefaultReaderTheme));
        await _settingsService.SetDoubleAsync(SettingsKeys.Brightness, DefaultBrightness);

        if (!string.IsNullOrWhiteSpace(CalibreUrl))
        {
            _calibreWebService.Configure(CalibreUrl, CalibreUsername, CalibrePassword);
        }

        if (showNotification)
        {
            await _navigationService.DisplayAlertAsync("Настройки", "Изменения сохранены.", "OK");
        }
    }

    private bool TryValidateCalibreUrl(out string message)
    {
        if (string.IsNullOrWhiteSpace(CalibreUrl))
        {
            message = "Введите адрес сервера Calibre.";
            return false;
        }

        if (!Uri.TryCreate(CalibreUrl, UriKind.Absolute, out var uri))
        {
            message = "Адрес сервера должен быть полным URL, например https://server.example.";
            return false;
        }

        if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
        {
            message = "Поддерживаются только адреса с http:// или https://.";
            return false;
        }

        message = string.Empty;
        return true;
    }

    private void UpdateConnectionSecurityHint()
    {
        if (string.IsNullOrWhiteSpace(CalibreUrl))
        {
            ConnectionSecurityHint = "Если Calibre доступен из интернета, используйте HTTPS. Для локальной сети HTTP допустим, но менее безопасен.";
            ConnectionSecurityColor = NeutralTone;
            return;
        }

        if (!Uri.TryCreate(CalibreUrl, UriKind.Absolute, out var uri))
        {
            ConnectionSecurityHint = "Проверьте адрес сервера. Нужен полный URL с http:// или https://.";
            ConnectionSecurityColor = DangerTone;
            return;
        }

        if (uri.Scheme == Uri.UriSchemeHttps)
        {
            ConnectionSecurityHint = "HTTPS включён: логин и пароль передаются по зашифрованному каналу.";
            ConnectionSecurityColor = SuccessTone;
            return;
        }

        if (uri.Scheme == Uri.UriSchemeHttp)
        {
            ConnectionSecurityHint = "HTTP подходит для домашней сети, но трафик и пароль не шифруются.";
            ConnectionSecurityColor = WarningTone;
            return;
        }

        ConnectionSecurityHint = "Поддерживаются только схемы http:// и https://.";
        ConnectionSecurityColor = DangerTone;
    }

    private static string ToDisplayTheme(string storedTheme) => storedTheme switch
    {
        "light" => "Светлая",
        "dark" => "Тёмная",
        _ => "Тёплая"
    };

    private static string ToStoredTheme(string displayTheme) => displayTheme switch
    {
        "Светлая" => "light",
        "Тёмная" => "dark",
        _ => Constants.Reader.DefaultTheme
    };
}
