using System.Diagnostics;
using System.IO;
using System.Reflection;
using ClaudeDo.Data;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace ClaudeDo.Ui.ViewModels.Modals;

public sealed partial class SettingsModalViewModel : ViewModelBase
{
    private readonly WorkerClient _worker;

    [ObservableProperty] private string _defaultClaudeInstructions = "";
    [ObservableProperty] private string _defaultModel = "sonnet";
    [ObservableProperty] private int _defaultMaxTurns = 30;
    [ObservableProperty] private string _defaultPermissionMode = "bypassPermissions";
    [ObservableProperty] private string _worktreeStrategy = "sibling";
    [ObservableProperty] private string? _centralWorktreeRoot;
    [ObservableProperty] private bool _worktreeAutoCleanupEnabled;
    [ObservableProperty] private int _worktreeAutoCleanupDays = 7;

    [ObservableProperty] private string _statusMessage = "";
    [ObservableProperty] private bool _isBusy;
    [ObservableProperty] private bool _showResetConfirm;
    [ObservableProperty] private string _validationError = "";

    public IReadOnlyList<string> Models { get; } = new[] { "opus", "sonnet", "haiku" };
    public IReadOnlyList<string> PermissionModes { get; } = new[]
        { "bypassPermissions", "acceptEdits", "plan", "default" };
    public IReadOnlyList<string> WorktreeStrategies { get; } = new[] { "sibling", "central" };

    public string AppVersion { get; } =
        Assembly.GetExecutingAssembly().GetName().Version?.ToString(3) ?? "0.0.0";

    public string DataFolderPath { get; } = Paths.AppDataRoot();
    public string LogsFolderPath { get; } = Path.Combine(Paths.AppDataRoot(), "logs");
    public string WorkerConfigPath { get; } = Path.Combine(Paths.AppDataRoot(), "worker.config.json");

    public Action? CloseAction { get; set; }

    public SettingsModalViewModel(WorkerClient worker)
    {
        _worker = worker;
    }

    public async Task LoadAsync()
    {
        IsBusy = true;
        try
        {
            var dto = await _worker.GetAppSettingsAsync();
            if (dto is not null)
            {
                DefaultClaudeInstructions = dto.DefaultClaudeInstructions ?? "";
                DefaultModel = dto.DefaultModel ?? "sonnet";
                DefaultMaxTurns = dto.DefaultMaxTurns;
                DefaultPermissionMode = dto.DefaultPermissionMode ?? "bypassPermissions";
                WorktreeStrategy = dto.WorktreeStrategy ?? "sibling";
                CentralWorktreeRoot = dto.CentralWorktreeRoot;
                WorktreeAutoCleanupEnabled = dto.WorktreeAutoCleanupEnabled;
                WorktreeAutoCleanupDays = dto.WorktreeAutoCleanupDays;
            }
            else
            {
                StatusMessage = "Worker offline — settings read-only.";
            }
        }
        finally { IsBusy = false; }
    }

    private bool Validate()
    {
        if (DefaultMaxTurns < 1 || DefaultMaxTurns > 200)
        { ValidationError = "Max turns must be between 1 and 200."; return false; }

        if (WorktreeAutoCleanupEnabled &&
            (WorktreeAutoCleanupDays < 1 || WorktreeAutoCleanupDays > 365))
        { ValidationError = "Cleanup days must be between 1 and 365."; return false; }

        if (WorktreeStrategy == "central")
        {
            if (string.IsNullOrWhiteSpace(CentralWorktreeRoot))
            { ValidationError = "Central worktree root is required for Central strategy."; return false; }
            if (!Directory.Exists(CentralWorktreeRoot))
            { ValidationError = $"Directory not found: {CentralWorktreeRoot}"; return false; }
        }

        ValidationError = "";
        return true;
    }

    [RelayCommand]
    private async Task Save()
    {
        if (!Validate()) return;

        IsBusy = true;
        try
        {
            var dto = new AppSettingsDto(
                DefaultClaudeInstructions ?? "",
                DefaultModel ?? "sonnet",
                DefaultMaxTurns,
                DefaultPermissionMode ?? "bypassPermissions",
                WorktreeStrategy ?? "sibling",
                string.IsNullOrWhiteSpace(CentralWorktreeRoot) ? null : CentralWorktreeRoot,
                WorktreeAutoCleanupEnabled,
                WorktreeAutoCleanupDays);
            await _worker.UpdateAppSettingsAsync(dto);
            CloseAction?.Invoke();
        }
        catch (Exception ex)
        {
            StatusMessage = $"Save failed: {ex.Message}";
        }
        finally { IsBusy = false; }
    }

    [RelayCommand]
    private void Cancel() => CloseAction?.Invoke();

    [RelayCommand]
    private async Task CleanupWorktrees()
    {
        IsBusy = true;
        StatusMessage = "";
        try
        {
            var result = await _worker.CleanupFinishedWorktreesAsync();
            StatusMessage = result is null
                ? "Worker offline."
                : $"Removed {result.Removed} worktree(s).";
        }
        finally { IsBusy = false; }
    }

    [RelayCommand]
    private void RequestResetConfirm() => ShowResetConfirm = true;

    [RelayCommand]
    private void CancelResetConfirm() => ShowResetConfirm = false;

    [RelayCommand]
    private async Task ConfirmResetAll()
    {
        ShowResetConfirm = false;
        IsBusy = true;
        StatusMessage = "";
        try
        {
            var result = await _worker.ResetAllWorktreesAsync();
            if (result is null)
                StatusMessage = "Worker offline.";
            else if (result.Blocked)
                StatusMessage = $"Cannot force-remove: {result.RunningTasks} task(s) still running. Cancel them first.";
            else
                StatusMessage = $"Removed {result.Removed} worktree(s) from {result.TasksAffected} task(s).";
        }
        finally { IsBusy = false; }
    }

    [RelayCommand]
    private async Task RestoreDefaultAgents()
    {
        IsBusy = true;
        StatusMessage = "";
        try
        {
            var result = await _worker.RestoreDefaultAgentsAsync();
            if (result is null)
                StatusMessage = "Worker offline.";
            else if (result.Copied == 0 && result.Skipped == 0)
                StatusMessage = "No default agents bundled.";
            else if (result.Copied == 0)
                StatusMessage = "All default agents already present.";
            else
                StatusMessage = $"Restored {result.Copied} default agent(s).";

            await _worker.RefreshAgentsAsync();
        }
        catch (Exception ex)
        {
            StatusMessage = $"Restore failed: {ex.Message}";
        }
        finally { IsBusy = false; }
    }

    [RelayCommand]
    private void OpenPath(string? path)
    {
        if (string.IsNullOrWhiteSpace(path)) return;
        try
        {
            var target = File.Exists(path) ? path : (Directory.Exists(path) ? path : null);
            if (target is null) return;
            Process.Start(new ProcessStartInfo("explorer.exe", $"\"{target}\"") { UseShellExecute = true });
        }
        catch { /* ignore */ }
    }
}
