// Copyright 2023-2024 Gentoo Authors
// Distributed under the terms of the GNU General Public License v2

namespace Gdmt.Commit

module Private =
    open System
    open System.IO

    open LibGit2Sharp
    open SimpleLog.SimpleLog
    open System.Text.RegularExpressions

    open Gdmt.Shared
    open Gdmt.Shared.Types

    let GetChangedFiles (repoTopDirectory: string) : StringList =
        use repo = new Repository(repoTopDirectory)

        repo.Diff.Compare<TreeChanges>(repo.Head.Tip.Tree, DiffTargets.WorkingDirectory)
        |> Seq.map (fun change -> Path.GetFileName change.Path)
        |> List.ofSeq

    let UpdateEbuildManifests () : unit =
        LogMessage Debug "Updating manifests"
        ExecProcess([ "pkgdev"; "manifest" ]).Run().Check()
        LogMessage Success "Successfully updated manifests"

    let GitAddAll () : unit =
        ExecProcess([ "git"; "add"; "--all"; "." ]).Run().Check()

    let PkgcheckScan () : unit =
        LogMessage Debug "Scanning with pkgcheck"
        ExecProcess([ "pkgcheck"; "scan"; "--exit"; "error" ]).Run().Check()
        LogMessage Success "Scan with pkgcheck succeeded"

    let IsEbuildFile (path: string) : bool = Regex.IsMatch(path, ".*\.ebuild$")

    let IsLiveEbuildFile (path: string) : bool =
        IsEbuildFile path && Regex.IsMatch(path, ".*9999\..*")

    let GetLatestNonLiveEbuildFile (path: string) : string =
        let latestEbuilds =
            Directory.GetFiles(path, "*.ebuild")
            |> Array.filter (IsLiveEbuildFile >> not)
            |> Array.sort
            |> Array.rev

        match latestEbuilds with
        | [||] -> "no latest ebuild file available" |> Exception |> raise
        | _ -> latestEbuilds |> Array.head

    let TestEbuilds (ebuildFiles: StringSequence) : unit =
        for ebuild: string in ebuildFiles do
            match ebuild with
            | f when File.Exists f ->
                LogMessage Debug $"Testing ebuild: {f}"

                ExecProcess([ "gdmt"; "ebuild"; "--test"; f; "clean"; "install"; "clean" ])
                    .Run()
                    .Check()

                LogMessage Success $"Ebuild test passed for: {f}"
            | f -> LogMessage Debug $"Ebuild file does not exist: {f}"

    let GuardCommitMessage (commitMessage: string) : unit =
        if String.IsNullOrEmpty commitMessage then
            "the effective commit message is empty" |> Exception |> raise

    let CreateTags (tagType: string) (sources: StringArray) : string =
        sources
        |> Array.map (fun source ->
            match source with
            | s when String.IsNullOrEmpty s -> ""
            | s when Regex.IsMatch(s, "http.*") -> $"{tagType}: {s}\n"
            | s -> $"{tagType}: https://bugs.gentoo.org/{s}\n")
        |> String.concat ""
