using System.Windows;
using MahApps.Metro.Controls;
using ControlzEx.Theming;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Windows.Media.Imaging;
using System.Diagnostics;
using Microsoft.Win32;
using System.Windows.Forms;

namespace ImageCatalog_2
{
    public partial class MainWindow : MetroWindow
    {
        private readonly DataModel _model;
        private bool _isDarkTheme = false;
        public MainWindow(DataModel model)
        {
            InitializeComponent();
            _model = model;
            DataContext = _model;
            // Set product version in status bar (use ProductVersion rather than AssemblyVersion)
            try
            {
                var entry = System.Reflection.Assembly.GetEntryAssembly();
                string version = string.Empty;
                if (entry is not null && !string.IsNullOrEmpty(entry.Location))
                {
                    try
                    {
                        version = FileVersionInfo.GetVersionInfo(entry.Location).ProductVersion ?? string.Empty;
                    }
                    catch { }
                }
                if (string.IsNullOrWhiteSpace(version))
                {
                    // fallback to assembly version
                    version = entry?.GetName().Version?.ToString() ?? string.Empty;
                }
                VersionTextBlock.Text = string.IsNullOrWhiteSpace(version) ? string.Empty : $"v{version}";
            }
            catch { }
            // Ensure MahApps resource dictionaries are loaded so chrome/styles are available
            EnsureMahAppsResourcesLoaded();

            // Apply theme based on user preference or system setting (default to light)
            ApplyTheme(isDark: false);
            // Subscribe to DataModel events that require UI dialogs
            _model.SelectSourceFolderRequested += Model_SelectSourceFolderRequested;
            _model.SelectDestinationFolderRequested += Model_SelectDestinationFolderRequested;
            _model.SelectLogoFileRequested += Model_SelectLogoFileRequested;
            _model.SaveSettingsRequested += Model_SaveSettingsRequested;
            _model.LoadSettingsRequested += Model_LoadSettingsRequested;
            _model.SelectColorRequested += Model_SelectColorRequested;
            _model.SelectTransparentColorRequested += Model_SelectTransparentColorRequested;
            _model.SelectModelsFolderRequested += Model_SelectModelsFolderRequested;
            _model.SelectCsvOutputRequested += Model_SelectCsvOutputRequested;

            // Watch for logo changes to update preview
            _model.PropertyChanged += Model_PropertyChanged;
        }

        private void ApplyTheme(bool isDark)
        {
            try
            {
                var rd = isDark ? (ResourceDictionary)Resources["DarkTheme"] : (ResourceDictionary)Resources["LightTheme"];
                foreach (var key in rd.Keys)
                {
                    // If the theme dictionary uses suffixed keys (e.g. "WindowBackgroundBrush.Dark"),
                    // map them to the base key ("WindowBackgroundBrush") so existing DynamicResource lookups update.
                    string outKey = key?.ToString() ?? string.Empty;
                    if (outKey.EndsWith(".Light", StringComparison.OrdinalIgnoreCase))
                        outKey = outKey.Substring(0, outKey.Length - ".Light".Length);
                    else if (outKey.EndsWith(".Dark", StringComparison.OrdinalIgnoreCase))
                        outKey = outKey.Substring(0, outKey.Length - ".Dark".Length);

                    Resources[outKey] = rd[key];
                }
            }
            catch
            {
                // ignore theme failures
            }
        }

        private void Model_SelectModelsFolderRequested(object? sender, EventArgs e)
        {
            var dlg = new System.Windows.Forms.FolderBrowserDialog();
            var starting = string.IsNullOrWhiteSpace(_model.ModelsFolderPath) ? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) : _model.ModelsFolderPath;
            dlg.SelectedPath = starting;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _model.ModelsFolderPath = dlg.SelectedPath + Path.DirectorySeparatorChar;
            }
        }

        private void OpenModelsFolder_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var path = _model.ModelsFolderPath;
                if (string.IsNullOrWhiteSpace(path)) return;
                path = path.Trim().Trim('"');
                if (File.Exists(path))
                {
                    System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
                    return;
                }
                if (Directory.Exists(path))
                {
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = path, UseShellExecute = true });
                    return;
                }
            }
            catch { }
        }

        private void Model_SelectCsvOutputRequested(object? sender, EventArgs e)
        {
            var dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.Filter = "CSV file (*.csv)|*.csv|All files (*.*)|*.*";
            if (!string.IsNullOrWhiteSpace(_model.CsvOutputPath)) dlg.FileName = _model.CsvOutputPath;
            var result = dlg.ShowDialog(this);
            if (result == true)
            {
                _model.CsvOutputPath = dlg.FileName;
            }
        }

        private void OpenCsvOutputFolder_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var path = _model.CsvOutputPath;
                if (string.IsNullOrWhiteSpace(path)) return;
                path = path.Trim().Trim('"');
                if (File.Exists(path))
                {
                    System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
                    return;
                }
                var dir = Path.GetDirectoryName(path);
                if (!string.IsNullOrWhiteSpace(dir) && Directory.Exists(dir))
                {
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = dir, UseShellExecute = true });
                    return;
                }
            }
            catch { }
        }

        private void Model_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e is null || string.IsNullOrWhiteSpace(e.PropertyName)) return;
            if (e.PropertyName == nameof(_model.LogoFile))
            {
                UpdateLogoPreview(_model.LogoFile);
            }
        }

        private void Model_SelectSourceFolderRequested(object? sender, EventArgs e)
        {
            var dlg = new System.Windows.Forms.FolderBrowserDialog();
            var starting = string.IsNullOrWhiteSpace(_model.SourcePath) ? Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) : _model.SourcePath;
            dlg.SelectedPath = starting;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _model.SourcePath = dlg.SelectedPath + Path.DirectorySeparatorChar;
            }
        }

        private void OpenSourceFolder_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var path = _model.SourcePath;
                if (string.IsNullOrWhiteSpace(path)) return;
                path = path.Trim().Trim('"');
                if (File.Exists(path))
                {
                    System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
                    return;
                }
                if (Directory.Exists(path))
                {
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = path, UseShellExecute = true });
                    return;
                }
            }
            catch (Exception ex)
            {
                // ignore for now, or could show a message
            }
        }

        private void Model_SelectDestinationFolderRequested(object? sender, EventArgs e)
        {
            var dlg = new System.Windows.Forms.FolderBrowserDialog();
            var starting = string.IsNullOrWhiteSpace(_model.DestinationPath) ? Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) : _model.DestinationPath;
            dlg.SelectedPath = starting;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _model.DestinationPath = dlg.SelectedPath + Path.DirectorySeparatorChar;
            }

        }

        private void OpenDestinationFolder_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var path = _model.DestinationPath;
                if (string.IsNullOrWhiteSpace(path)) return;
                path = path.Trim().Trim('"');
                if (File.Exists(path))
                {
                    System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\"");
                    return;
                }
                if (Directory.Exists(path))
                {
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = path, UseShellExecute = true });
                    return;
                }
            }
            catch (Exception ex)
            {
                // ignore for now
            }
        }

        private void Model_SelectLogoFileRequested(object? sender, EventArgs e)
        {
            var dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp;*.gif";
            if (!string.IsNullOrWhiteSpace(_model.LogoFile)) dlg.FileName = _model.LogoFile;
            var result = dlg.ShowDialog(this);
            if (result == true)
            {
                _model.LogoFile = dlg.FileName;
            }
        }

        private async void Model_SaveSettingsRequested(object? sender, string filePath)
        {
            var dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.Filter = "Setup (*.xml)|*.xml|All valid files (*.*)|*.*";
            var result = dlg.ShowDialog(this);
            if (result == true)
            {
                await _model.SaveSettingsToFileAsync(dlg.FileName);
            }
        }

        private async void Model_LoadSettingsRequested(object? sender, string filePath)
        {
            var dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.Filter = "Setup (*.xml)|*.xml|All valid files (*.*)|*.*";
            var result = dlg.ShowDialog(this);
            if (result == true)
            {
                await _model.LoadSettingsFromFileAsync(dlg.FileName);
            }
        }

        private void Model_SelectColorRequested(object? sender, EventArgs e)
        {
            var dlg = new System.Windows.Forms.ColorDialog { AllowFullOpen = true };
            if (!string.IsNullOrWhiteSpace(_model.TextColorRGB))
            {
                try { dlg.Color = System.Drawing.ColorTranslator.FromHtml(_model.TextColorRGB); } catch { }
            }
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _model.TextColorRGB = System.Drawing.ColorTranslator.ToHtml(dlg.Color);
            }
        }

        private void Model_SelectTransparentColorRequested(object? sender, EventArgs e)
        {
            var dlg = new System.Windows.Forms.ColorDialog { AllowFullOpen = true };
            try { dlg.Color = System.Drawing.ColorTranslator.FromHtml(_model.TransparentColor); } catch { }
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _model.TransparentColor = System.Drawing.ColorTranslator.ToHtml(dlg.Color);
            }
        }

        private void ToggleTheme_Click(object? sender, RoutedEventArgs e)
        {
            ToggleTheme();
        }

        private void ToggleTheme()
        {
            try
            {
                _isDarkTheme = !_isDarkTheme;

                // Use MahApps ThemeManager to change the application theme (handles chrome and brushes)
                try
                {
                    var themeName = _isDarkTheme ? "Dark.Blue" : "Light.Blue";
                    ThemeManager.Current.ChangeTheme(System.Windows.Application.Current, themeName);
                }
                catch
                {
                    // Fall back silently if ThemeManager isn't available
                }

                // Still apply local resource overrides so any app-specific keys update
                ApplyTheme(_isDarkTheme);
            }
            catch
            {
                // ignore toggle failures
            }
        }

        private void EnsureMahAppsResourcesLoaded()
        {
            try
            {
                var app = System.Windows.Application.Current;
                if (app is null)
                    return;

                var mds = app.Resources.MergedDictionaries;

                // Helper to add if missing
                void AddIfMissing(string uriString)
                {
                    if (!mds.Any(d => d.Source is not null && d.Source.OriginalString.Equals(uriString, StringComparison.OrdinalIgnoreCase)))
                    {
                        mds.Add(new ResourceDictionary { Source = new Uri(uriString) });
                    }
                }

                AddIfMissing("pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml");
                AddIfMissing("pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml");
                // Ensure a default theme is present
                if (!mds.Any(d => d.Source is not null && d.Source.OriginalString.IndexOf("/MahApps.Metro;component/Styles/Themes/", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    AddIfMissing("pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml");
                    _isDarkTheme = false;
                }
            }
            catch
            {
                // ignore; styling will fallback to local resources
            }
        }

        private void UpdateLogoPreview(string? path)
        {
            if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
            {
                LogoPreview.Source = null;
                return;
            }

            try
            {
                var bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.CacheOption = BitmapCacheOption.OnLoad;
                bitmap.UriSource = new Uri(path);
                bitmap.EndInit();
                LogoPreview.Source = bitmap;
            }
            catch
            {
                LogoPreview.Source = null;
            }
        }
    }
}

