/* release_notes.rs
 *
 * Copyright 2026 Christian Kruse
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

pub struct ReleaseNote {
    pub version: &'static str,
    pub date: &'static str,
    pub summary: &'static str,
    pub sections: &'static [ReleaseSection],
    // If true, this release will trigger the What's-New dialog automatically
    pub show_on_upgrade: bool,
}

pub struct ReleaseSection {
    pub heading: &'static str,
    pub items: &'static [&'static str],
}

pub const RELEASE_NOTES: &[ReleaseNote] = &[
    ReleaseNote {
        version: "0.3.0",
        date: "2026-05-13",
        summary: "This release brings full merge support, accessibility improvements, an in-app release notes viewer \
                  and macOS support.",
        show_on_upgrade: true,
        sections: &[
            ReleaseSection {
                heading: "New features",
                items: &[
                    "Full merge workflow: initiate, resolve and complete merges from within Gitte",
                    "In-app release notes dialog with a notification banner when a new version is available",
                    "New \"compact UI\" setting for denser layouts",
                    "Multiple selection support in the changed files list",
                    "Keyboard shortcut for opening the shortcuts help",
                    "macOS support (dynamic gettext path, environment setup, documentation)",
                    "DOAP metadata file added",
                ],
            },
            ReleaseSection {
                heading: "UI improvements and fixes",
                items: &[
                    "Diff view now uses a proper text view with a gutter for line numbers and markers. You can now \
                     mark and copy diffs in the log viewer! 🥳",
                    "Numerous accessibility (a11y) refinements",
                    "Word-based diffs tweaked for better readability",
                    "Gracefully handle very large diffs",
                    "Long file paths in the diff view header are now ellipsized instead of pushing the toolbar off \
                     screen; the full path is available as a tooltip",
                    "Default window size increased to 1280x1024",
                ],
            },
            ReleaseSection {
                heading: "Under the hood",
                items: &[
                    "macOS port (thanks to René de Hesselle, https://floss.social/@rdh)",
                    "New GNOME style icons (thanks to Jakub Steiner, https://jimmac.eu)",
                    "Switched many widgets to use the relm4::view! macro and CSS classes instead of magic numbers",
                    "New test coverage for git helpers",
                    "WorkingCopyView refactored, ChangedFileRow moved into its own file",
                    "Continuous Integration (CI) added",
                    "Updated translations (i18n / l10n)",
                    "Dependency updates",
                    "Flatpak sandbox now bypasses git hooks, credential helpers and aliases by default to avoid \
                     confusing failures; a new \"Bypass local Git config\" preference makes this toggleable per \
                     repository",
                    "Various bugfixes (race condition on startup, --no-pager always set)",
                ],
            },
        ],
    },
    ReleaseNote {
        version: "0.2.0",
        date: "2026-05-07",
        summary: "This release brings interactive rebasing, more configurability and a number of refinements.",
        show_on_upgrade: true,
        sections: &[
            ReleaseSection {
                heading: "New features",
                items: &[
                    "Rebasing features: reorder, drop, reword, edit and squash/fixup commits from the commit log",
                    "Remote operations (push, pull, fetch, clone) now use the git CLI for better credential handling \
                     and protocol support",
                    "Configurable font for the diff view",
                    "Command line arguments handling: open a repository directly from the terminal, e.g. \"gitte \
                     ~/Code/projects/Gitte\"",
                    "New unified stash modal when actions ask to stash pending changes",
                    "Ahead/behind status indicator for the current branch in the workspace view",
                    "Double-click on a local branch switches to it",
                    "Marker for merge commits in the commit log",
                    "Additional information in the commit log viewer",
                    "A few small easter eggs",
                ],
            },
            ReleaseSection {
                heading: "Under the hood",
                items: &[
                    "Ukrainian translation (thanks to Dymko <Dymkovych@proton.me>)",
                    "German translation",
                    "AUR package documentation (thanks to Kainoa Kanter <kainoa@t1c.dev>)",
                    "a lot of bugfixes",
                ],
            },
        ],
    },
    ReleaseNote {
        version: "0.1.10",
        date: "2026-04-29",
        summary: "This release adds small improvements around importing repositories and the start screen.",
        show_on_upgrade: false,
        sections: &[
            ReleaseSection {
                heading: "New features",
                items: &["Import multiple repository folders at once"],
            },
            ReleaseSection {
                heading: "Fixes",
                items: &[
                    "Workaround for the file picker's folder selection mode for when xdg-desktop-portal is too old",
                ],
            },
        ],
    },
    ReleaseNote {
        version: "0.1.9",
        date: "2026-04-27",
        summary: "This release fixes two bugs.",
        show_on_upgrade: false,
        sections: &[ReleaseSection {
            heading: "Fixes",
            items: &[
                "Stashed untracked files are now correctly shown in the stashes view",
                "~/.config/git/config is now correctly read in Flatpak builds",
            ],
        }],
    },
    ReleaseNote {
        version: "0.1.8",
        date: "2026-04-27",
        summary: "This release adds several new features, refinements and fixes.",
        show_on_upgrade: false,
        sections: &[
            ReleaseSection {
                heading: "New features",
                items: &[
                    "Word-based diffs in both the diff view for pending changes and the commit log viewer",
                    "Working copy view can now be displayed as either a split or a unified view, configurable via a \
                     new setting",
                    "Search filter in the working copy view to quickly locate changed files",
                    "Support for git archive to export repository snapshots",
                    "Validation of tag and branch names when creating them",
                    "New keyboard shortcut and context menu entry for common actions",
                    "New application icon",
                ],
            },
            ReleaseSection {
                heading: "UI improvements",
                items: &[
                    "Branch and remote names as well as tags can now be shortened / ellipsized",
                    "Invalid repository rows on the start screen are no longer activatable",
                ],
            },
            ReleaseSection {
                heading: "Fixes",
                items: &[
                    "Do not leak signal handlers",
                    "Do not deselect the current item unexpectedly",
                    "Stop complaining that a tag could not be found while in detached HEAD state",
                    "Default to the \"main\" branch name when no config option is set",
                ],
            },
        ],
    },
    ReleaseNote {
        version: "0.1.7",
        date: "2026-04-20",
        summary: "This release brings new features and a number of UI improvements.",
        show_on_upgrade: false,
        sections: &[
            ReleaseSection {
                heading: "New features",
                items: &[
                    "Commit log search: quickly find commits by message text, author or date",
                    "Hideable sidebar: toggle the sidebar to gain more screen space, with a keyboard shortcut for \
                     quick access. If hidden, new headerbar actions are available for quick access to common tasks.",
                ],
            },
            ReleaseSection {
                heading: "UI improvements",
                items: &[
                    "Header bar actions now display labels for better discoverability",
                    "Hamburger menu moved to the rightmost position for consistency",
                    "Tooltips for working tree and index status indicators in the file list",
                    "Commit message editor now can enforce a maximum line length",
                ],
            },
        ],
    },
    ReleaseNote {
        version: "0.1.6",
        date: "2026-04-18",
        summary: "Gitte can now checkout tags or commits and clone repositories.",
        show_on_upgrade: false,
        sections: &[],
    },
    ReleaseNote {
        version: "0.1.5",
        date: "2026-04-17",
        summary: "Fix an issue with pushing tags. Also fix a race condition leading to a crash when changing the \
                  commit hash in the create tag modal.",
        show_on_upgrade: false,
        sections: &[],
    },
    ReleaseNote {
        version: "0.1.4",
        date: "2026-04-17",
        summary: "Flatpak adjustments: we now use the portal for secrets. Users are now also able to configure the \
                  SSH key to use per repo and remote.",
        show_on_upgrade: false,
        sections: &[],
    },
    ReleaseNote {
        version: "0.1.3",
        date: "2026-04-16",
        summary: "A fix in push code (now always pushes tags and sets the upstream when wanted by the user) and a new \
                  per-repo setting: git identity.",
        show_on_upgrade: false,
        sections: &[],
    },
    ReleaseNote {
        version: "0.1.2",
        date: "2026-04-16",
        summary: "Fixes global gitconfig lookup in Flatpak sandboxes once and for all. Also use relm4 icons for all \
                  icons.",
        show_on_upgrade: false,
        sections: &[],
    },
    ReleaseNote {
        version: "0.1.1",
        date: "2026-04-16",
        summary: "Fixes for flatpak builds, nicer title bar.",
        show_on_upgrade: false,
        sections: &[],
    },
    ReleaseNote {
        version: "0.1.0",
        date: "2026-04-06",
        summary: "Initial release.",
        show_on_upgrade: false,
        sections: &[],
    },
];

pub fn all() -> &'static [ReleaseNote] {
    RELEASE_NOTES
}

pub fn upgrade_path(from: &str, to: &str) -> Vec<&'static ReleaseNote> {
    if from == to {
        return Vec::new();
    }

    let to_idx = RELEASE_NOTES.iter().position(|n| n.version == to);
    let from_idx = RELEASE_NOTES.iter().position(|n| n.version == from);

    match (to_idx, from_idx) {
        (Some(to_idx), Some(from_idx)) if to_idx < from_idx => RELEASE_NOTES[to_idx..from_idx]
            .iter()
            .filter(|n| n.show_on_upgrade)
            .collect(),

        (Some(to_idx), _) => RELEASE_NOTES
            .get(to_idx)
            .filter(|n| n.show_on_upgrade)
            .into_iter()
            .collect(),

        _ => Vec::new(),
    }
}
