using Sdt.Config;
using Sdt.Tui;
using Spectre.Console;

try
{
    // ── Workspace + project discovery ────────────────────────────────────────

    var workspaceResult = WorkspaceLoader.FindAndLoad();
    var projectResult = ConfigLoader.FindAndLoad();
    var cliArgs = Environment.GetCommandLineArgs().Skip(1).ToArray();
    var forceInit = cliArgs.Any(a => string.Equals(a, "init", StringComparison.OrdinalIgnoreCase) ||
                                     string.Equals(a, "--init", StringComparison.OrdinalIgnoreCase));

    if (forceInit)
    {
        var scan = ConfigBootstrapper.Scan(Directory.GetCurrentDirectory());
        var generated = ConfigBootstrapper.BuildDefaultConfig(scan);
        var path = ConfigBootstrapper.WriteDefaultConfig(scan.ProjectRoot, generated, overwrite: false);
        AnsiConsole.MarkupLine(Theme.Ok($"Initialized config at {path}"));
        projectResult = ConfigLoader.FindAndLoad(scan.ProjectRoot);
    }

    if (projectResult is null)
    {
        AnsiConsole.MarkupLine($"[bold {Theme.Red}]SDT:[/] [{Theme.Amber}]No devtool.json found[/] in current directory or any parent.");
        var bootstrap = AnsiConsole.Confirm(
            $"[{Theme.Amber}]Generate a default devtool.json for this project now?[/]",
            defaultValue: true);
        if (!bootstrap)
        {
            AnsiConsole.MarkupLine(Theme.Faint("Create a devtool.json in your project root to get started."));
            return 1;
        }

        var scan = ConfigBootstrapper.Scan(Directory.GetCurrentDirectory());
        AnsiConsole.MarkupLine(Theme.Faint($"Detected project root: {scan.ProjectRoot}"));
        if (scan.ToolFamilies.Count > 0)
            AnsiConsole.MarkupLine(Theme.Faint($"Detected tool families: {string.Join(", ", scan.ToolFamilies)}"));

        var generated = ConfigBootstrapper.BuildDefaultConfig(scan);
        var preview = ConfigBootstrapper.ToJson(generated);
        AnsiConsole.Write(new Panel(Markup.Escape(preview)).Header("Generated devtool.json preview").BorderStyle(Theme.DimStyle));

        var confirmWrite = AnsiConsole.Confirm(
            $"[{Theme.Amber}]Write generated devtool.json to {scan.ProjectRoot}?[/]",
            defaultValue: true);
        if (!confirmWrite)
            return 1;

        var path = ConfigBootstrapper.WriteDefaultConfig(scan.ProjectRoot, generated, overwrite: false);
        AnsiConsole.MarkupLine(Theme.Ok($"Created {path}"));
        projectResult = ConfigLoader.FindAndLoad(scan.ProjectRoot);
        if (projectResult is null)
        {
            AnsiConsole.MarkupLine(Theme.Fail("Generated config could not be reloaded."));
            return 1;
        }
    }

    // ── Main run loop (handles workspace project switching) ────────────────

    var currentLoaded = projectResult;
    var (workspace, workspaceRoot) = workspaceResult.HasValue
        ? (workspaceResult.Value.Config, workspaceResult.Value.WorkspaceRoot)
        : ((WorkspaceConfig?)null, (string?)null);

    while (true)
    {
        var app = new App(currentLoaded.Config, currentLoaded.ProjectRoot, currentLoaded.Warnings, workspace, workspaceRoot);
        var result = await app.RunAsync();

        if (result.Reason == AppExitReason.Quit)
            break;

        // User switched projects — reload config from new root
        if (result.Reason == AppExitReason.SwitchProject && result.NewProjectRoot is not null)
        {
            LoadedProjectConfig? loaded;
            try
            {
                loaded = ConfigLoader.FindAndLoad(result.NewProjectRoot);
            }
            catch (Exception ex)
            {
                AnsiConsole.MarkupLine(Theme.Fail(ex.Message));
                AnsiConsole.MarkupLine(Theme.Faint("Press any key to stay on current project..."));
                Console.ReadKey(intercept: true);
                continue;
            }
            if (loaded is null)
            {
                AnsiConsole.MarkupLine(Theme.Fail($"No devtool.json found at: {result.NewProjectRoot}"));
                AnsiConsole.MarkupLine(Theme.Faint("Press any key to stay on current project..."));
                Console.ReadKey(intercept: true);
                continue; // go back to current app
            }

            currentLoaded = loaded;
        }
    }

    return 0;
}
catch (Exception ex)
{
    var message = ex.Message;
    var isExpectedMigrationError =
        ex is InvalidOperationException &&
        message.Contains("Legacy targets-only config detected", StringComparison.OrdinalIgnoreCase);

    AnsiConsole.MarkupLine(Theme.Fail($"Fatal: {message}"));
    if (isExpectedMigrationError)
    {
        var configPath = ConfigLoader.FindConfigPath();
        if (!string.IsNullOrWhiteSpace(configPath))
        {
            var migrate = AnsiConsole.Confirm(
                $"[{Theme.Amber}]Apply automatic migration now (creates backup + converts targets -> workflows)?[/]",
                defaultValue: true);
            if (migrate)
            {
                var result = ConfigLoader.ApplyLegacyTargetMigration(configPath, createBackup: true);
                if (result.Success)
                {
                    AnsiConsole.MarkupLine(Theme.Ok("Migration applied successfully."));
                    if (!string.IsNullOrWhiteSpace(result.BackupPath))
                        AnsiConsole.MarkupLine(Theme.Faint($"Backup: {result.BackupPath}"));
                    AnsiConsole.MarkupLine(Theme.Faint("Run sdt.exe again in strict mode."));
                }
                else
                {
                    AnsiConsole.MarkupLine(Theme.Fail($"Migration failed: {result.Message}"));
                }
            }
        }
    }

    if (!isExpectedMigrationError)
        AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);

    return 1;
}
