using System.IO;
using System.Threading.Tasks;
using System.Windows.Threading;

using CamBooth.App.Core.AppSettings;
using CamBooth.App.Core.Logging;
using CamBooth.App.Features.Camera;
using CamBooth.App.Features.PhotoPrismUpload;
using CamBooth.App.Features.PictureGallery;

namespace CamBooth.App;

public class MainWindowViewModel
{
	private readonly Logger _logger;
	private readonly AppSettingsService _appSettings;
	private readonly PictureGalleryService _pictureGalleryService;
	private readonly CameraService _cameraService;
	private readonly PhotoPrismUploadService _photoPrismUploadService;
	private readonly DispatcherTimer _galleryPromptTimer;

	public bool IsPhotoProcessRunning { get; private set; }

	// The running focus task — shared between StartTakePhotoProcess and OnTimerElapsed
	private Task _focusTask = Task.CompletedTask;

	// Events → MainWindow subscribes and updates UI
	public event Action<string, string>? LoadingProgressChanged; // (statusText, countText)
	public event Action? InitializationCompleted;
	public event Action? GalleryPromptRequested;
	public event Action? GalleryPromptDismissed;


	public MainWindowViewModel(
		Logger logger,
		AppSettingsService appSettings,
		PictureGalleryService pictureGalleryService,
		CameraService cameraService,
		PhotoPrismUploadService photoPrismUploadService)
	{
		_logger = logger;
		_appSettings = appSettings;
		_pictureGalleryService = pictureGalleryService;
		_cameraService = cameraService;
		_photoPrismUploadService = photoPrismUploadService;

		_galleryPromptTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
		_galleryPromptTimer.Tick += (_, _) => DismissGalleryPrompt();

		if (appSettings.PhotoPrismAutoUploadEnabled)
			_ = InitializePhotoUploadAsync();
	}


	public async Task InitializeAsync()
	{
		try
		{
			await LoadThumbnailsAsync();
			await Task.Delay(500);
		}
		catch (Exception ex)
		{
			_logger.Error($"Initialization error: {ex.Message}");
		}
		finally
		{
			InitializationCompleted?.Invoke();
		}
	}


	/// <summary>
	/// Starts autofocus in the background. The effective timeout is capped so focus
	/// is guaranteed to complete before the countdown timer fires.
	/// </summary>
	public Task BeginFocusAsync(int delaySeconds, int focusTimeoutMs, int countdownSeconds)
	{
		// Ensure focus always finishes at least 500ms before the timer fires.
		var maxAllowedMs = (countdownSeconds - delaySeconds) * 1000 - 500;
		var effectiveTimeoutMs = Math.Max(200, Math.Min(focusTimeoutMs, maxAllowedMs));
		_focusTask = RunFocusAsync(delaySeconds, effectiveTimeoutMs);
		return _focusTask;
	}

	private async Task RunFocusAsync(int delaySeconds, int focusTimeoutMs)
	{
		if (delaySeconds > 0)
			await Task.Delay(TimeSpan.FromSeconds(delaySeconds));
		await _cameraService.PrepareFocusAsync(focusTimeoutMs);
	}

	/// <summary>
	/// Called when the timer fires. Focus is already guaranteed complete — takes photo immediately.
	/// Throws on camera error so the caller can show a message.
	/// </summary>
	public void TakePhotoAfterTimer()
	{
		IsPhotoProcessRunning = false;
		_cameraService.TakePhoto();
		ShowGalleryPrompt();
	}


	public void StartPhotoProcess()
	{
		IsPhotoProcessRunning = true;
		_focusTask = Task.CompletedTask;
		DismissGalleryPrompt();
	}


	public void CancelPhotoProcess()
	{
		IsPhotoProcessRunning = false;
	}


	public void ShowGalleryPrompt()
	{
		GalleryPromptRequested?.Invoke();
		_galleryPromptTimer.Stop();
		_galleryPromptTimer.Start();
	}


	public void DismissGalleryPrompt()
	{
		_galleryPromptTimer.Stop();
		GalleryPromptDismissed?.Invoke();
	}


	private async Task LoadThumbnailsAsync()
	{
		var pictureLocation = _appSettings.PictureLocation;

		if (!Directory.Exists(pictureLocation))
		{
			LoadingProgressChanged?.Invoke("Keine Fotos gefunden", "0 Fotos");
			await Task.Delay(1000);
			return;
		}

		string[] imageExtensions = [".jpg", ".jpeg", ".png", ".bmp", ".gif"];
		var totalCount = Directory.EnumerateFiles(pictureLocation!)
			.Count(f => imageExtensions.Contains(Path.GetExtension(f).ToLowerInvariant()));

		if (totalCount == 0)
		{
			LoadingProgressChanged?.Invoke("Keine Fotos gefunden", "Bereit für neue Aufnahmen!");
			await Task.Delay(1000);
			return;
		}

		var photoLabel = totalCount == 1 ? "Foto" : "Fotos";
		LoadingProgressChanged?.Invoke($"Lade {totalCount} {photoLabel}...", $"0 / {totalCount}");
		await _pictureGalleryService.LoadThumbnailsToCache();
		LoadingProgressChanged?.Invoke("Fotos erfolgreich geladen!", $"{totalCount} {photoLabel} bereit");
	}


	private async Task InitializePhotoUploadAsync()
	{
		_logger.Info("PhotoPrism Auto-Upload aktiviert. Authentifiziere...");
		var authSuccess = await _photoPrismUploadService.AuthenticateAsync();
		if (authSuccess)
			_logger.Info("PhotoPrism-Authentifizierung erfolgreich!");
		else
			_logger.Warning("PhotoPrism-Authentifizierung fehlgeschlagen.");
	}
}
