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

namespace Gdmt.StableRequest

module Private =
    open System
    open System.Net.Http
    open System.Text.RegularExpressions

    open FSharp.Data
    open SimpleLog.SimpleLog

    open Gdmt.Shared
    open Gdmt.Shared.Types

    type StabilizationArrayProvider =
        JsonProvider<"""
            [
                {
                    "category": "Category",
                    "package": "Package",
                    "version": "Version",
                    "message": "Message"
                }
            ]
        """>

    let StabilizationUriBase = "https://packages.gentoo.org/maintainer/"

    let GetStabilizationArray (maintainerEmail: string) : Async<StabilizationArrayProvider.Root array> =
        async {
            let stabilizationUri =
                $"{StabilizationUriBase}/{maintainerEmail}/stabilization.json"

            let httpClient = new HttpClient()
            let! httpResponse = httpClient.GetStringAsync(stabilizationUri) |> Async.AwaitTask
            let jsonResult = StabilizationArrayProvider.Parse(httpResponse)

            return jsonResult
        }

    let GetStabilizationArchitectures (messageString: string) : StringArray =
        messageString.Split([| ' ' |])
        |> Array.filter (fun s -> s[0] = '~')
        |> Array.map (fun s -> s.Replace("~", "").Replace(",", ""))

    let AskYesNoRegex = new Regex(@"^[Yy]([Ee][Ss])?$")

    let AskYesNo () =
        match Console.ReadLine() with
        // Return (Enter) key was pressed.
        | "" -> true
        | s -> AskYesNoRegex.IsMatch(s)

    let PackageWithRevisionRegex = new Regex(@".+-r[0-9]+$")

    let RunPkgdevBugs (arches: string) (package: string) : unit =
        // When there is no revision specified we can use the "~" package operator
        // in order to say "match any revision", if there is a revision specified,
        // then we have to be exact and use "=" package operator.
        let adequatePackageAtom =
            match package with
            | s when PackageWithRevisionRegex.IsMatch(s) -> $"={package}"
            | _ -> $"~{package}"

        let pkgdevBugsArgs =
            [ "pkgdev"; "bugs"; "--stablereq"; "--arches"; arches; adequatePackageAtom ]

        let success = ExecProcess(pkgdevBugsArgs).Run().Success

        if success then
            LogMessage Success $"Successfully submitted request for {package}"
        else
            LogMessage Error $"Errors occurred when processing request"
            LogMessage Error $"Failed to submit request for {package}"

    let ProcessStabilizationItem (stabilizationItem: StabilizationArrayProvider.Root) : unit =
        let category = stabilizationItem.Category
        let package = stabilizationItem.Package
        let version = stabilizationItem.Version
        let message = stabilizationItem.Message

        let packageShortName = $"{category}/{package}"
        let packageFullName = $"{packageShortName}-{version}"
        let arches = GetStabilizationArchitectures message |> String.concat ","

        LogMessage Info $"Full package: {packageFullName}"
        LogMessage Info $"Message: {message}"
        LogMessage Info $"Stabilization architectures: {arches}"

        printf $"Use the package {packageShortName}? [Y/n] "

        if AskYesNo() then
            RunPkgdevBugs arches packageFullName
        else
            LogMessage Debug $"Skipping the package {packageShortName}"
