module Tests.E2e.LobbyTests

open System
open System.Threading.Tasks
open Expecto
open Microsoft.Playwright
open Dsl
open Tests.E2e.Fixture2

type LoginPage = {
  UsernameField: Locator
  PasswordField: Locator
  SigninButton: Transition<HomePage>
}
and CreateGameModal = {
  GameNameField: Locator
  MaxPlayersField: Locator
  RoundsField: Locator
  CreateButton: Transition<GameDetailsPage>
}
and GameDetailsPage = {
  Heading: Locator
  LobbyHeading: Locator
  PlayersHeading: Locator
  StartGameButton: Transition<HomePage>
  ReadyButton: Locator
}
and HomePage = {
  SigninLink: Transition<LoginPage>
  CreateGameButton: Transition<CreateGameModal>
  GamesList: {| JoinGameButton: string -> Transition<GameDetailsPage> |}
}

let joinGameButton name (pom:HomePage) =
  pom.GamesList.JoinGameButton name

open type Locators
let plr =

  let joinGameButton(gameName:string)=
      Locator "div.mantine-Group-root"
      |||> (fun locator page ->
         locator.Filter(LocatorFilterOptions(Has = ByText(gameName,exact=true) page))
      )
      ||> _.GetByRole(AriaRole.Button)
      ||> _.First
  let rec login() =
    {
      UsernameField = Label  "Username"
      PasswordField = Label  "Password"
      SigninButton = Button "Sign in", home
    }
  and createGameModal() =
    {
      GameNameField = Label  "Game name"
      MaxPlayersField = Label  "Max players"
      RoundsField = Label  "Rounds"
      CreateButton = Button("Create",exact=true), fun()->gameDetails()
    }
  and gameDetails() =
    {
      Heading = Heading  ""
      LobbyHeading = Heading  "Game lobby"
      PlayersHeading = Heading  "Players"
      StartGameButton = Button "Start game", home
      ReadyButton = Heading  "xxx"
    }
  and home() =
    {
      SigninLink = Link "Sign in", login
      CreateGameButton = Button "Create game", createGameModal
      GamesList =
        {|
          JoinGameButton =
            fun gameName ->
            joinGameButton gameName , gameDetails

        |}
    }

  {|
    Login = login
    CreateGameModal = createGameModal
    GameDetails = gameDetails
    Home = home
  |}

open FsToolkit.ErrorHandling

[<Tests>]
let browserTests =
  (testFixtureTask browserFixture [
    "Sign in navigates to dashboard",
    fun b -> task {
        use! ctx1 = b.NewContextAsync()
        let! page1 = ctx1.NewPageAsync()
        let options ={|
            name = "test"
            maxPlayers = 2
            maxRounds = 2
            |}

        do! page1.GoToAsync("https://localhost:5001")
        do! pageTest(page1, plr.Home()) {
            click _.SigninLink
            fill _.UsernameField "jannik"
            fill _.PasswordField "a"
            click _.SigninButton
            expectVisible _.CreateGameButton
            click _.CreateGameButton
            fill _.GameNameField options.name
            fill _.MaxPlayersField (options.maxPlayers.ToString())
            fill _.RoundsField (options.maxRounds.ToString())
            click _.CreateButton
        }

        use! ctx2 = b.NewContextAsync()
        let! page2 = ctx2.NewPageAsync()
        do! page2.GoToAsync("https://localhost:5001")
        do! pageTest(page2,plr.Home()) {
              click _.SigninLink
              fill _.UsernameField "Alice"
              fill _.PasswordField "a"
              click _.SigninButton
              expectVisible _.CreateGameButton

              wait_s 1
              takeAriaSnapshot
              printf "Check for game %s" options.name
              expectVisible (joinGameButton options.name)
              takeAriaSnapshot (joinGameButton options.name)
              click (joinGameButton options.name)
              expectVisible _.LobbyHeading
              expectVisible _.PlayersHeading
              //expectVisible (fun pom -> pom.ReadyButton)
              page (fun page->
                Assertions.Expect(page.GetByLabel "foo").ToBeVisibleAsync()
                )
        }

        return ()
    }
 ])
 |> Seq.toList
 |> ftestList "lobby"

[<Tests>]
let x =
  (testFixtureTask pageFixture [
    "Sign in navigates to dashboard",
    fun page -> task {
          do! page.GoToAsync("https://localhost:5001")
          do! pageTest (page,plr.Home()) {
                click _.SigninLink
                fill _.UsernameField "jannik"
                fill _.PasswordField "a"
                click _.SigninButton
                expectVisible _.CreateGameButton
          }
    }
 ])
 |> Seq.toList
 |> testList "lobby"