// defmodule WebWars.Engine.Ability.ProduceTest {
//   @moduledoc false

//   use WebWars.DataCase
//   import WebWars.Factory
//   alias Ecto.UUID
//   alias Ecto.Changeset
//   alias WebWars.Engine.{
//     Action,
//     Ability,
//     AbilityData,
//     Coord,
//     Game,
//     Power,
//     PowerData,
//     Tile,
//     TileData,
//     UnitData,
//     UserData,
//   }

//   describe "validate/2" {
//     test "validates cost, valid" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.Base.id(),
//           tile: Tile.Base.create()
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {valid?: true} = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates cost" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.Base.id(),
//           tile: Tile.Base.create()
//         },
//         subject_user_data: UserData {
//           funds: 90
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {
//         errors: [
//           params: {"can't afford", []}
//         ]
//       } = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates cost with cost bonus" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.Base.id(),
//           tile: Tile.Base.create()
//         },
//         subject_user_data: UserData {
//           funds: 90,
//           power_data: [
//             PowerData {
//               power_id: Power.CostBonus.id(),
//               params: ["-10"]
//             }
//           ]
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {valid?: true} = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates specified unit exists" {
//       id = UUID.generate()
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: ["00000000-0000-0000-0000-000000000000"],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.Base.id(),
//           tile: Tile.Base.create()
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       assert_raise Ecto.NoResultsError, fn ->
//         Ability.Produce.create().validate.(changeset, action)
//       }
//     }

//     test "validates tile can produce" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.City.id(),
//           tile: Tile.City.create()
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {
//         errors: [
//           ability_id: {"is invalid", []}
//         ]
//       } = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates unit can produce" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100,
//         ability_data: [
//           AbilityData {ability_id: Ability.Produce.id()},
//           AbilityData {ability_id: Ability.Load.id(), params: ["1"]}
//         ]
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: UnitData {
//           id: id,
//           unit: unit,
//           load_data: []
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {valid?: true} = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates unit can produce, invalid" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: UnitData {
//           id: id,
//           unit: unit
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {
//         errors: [
//           ability_id: {"is invalid", []}
//         ]
//       } = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates tile is unoccupied" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.Base.id(),
//           tile: Tile.Base.create()
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {
//           unit_data: [
//             UnitData {
//               coord: Coord {x: 0, y: 0}
//             }
//           ]
//         }
//       }
//       changeset = Changeset.change(action)

//       Changeset {
//         errors: [
//           subject: {"has no space", []}
//         ]
//       } = Ability.Produce.create().validate.(changeset, action)
//     }

//     test "validates unit isn't overloaded" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100,
//         ability_data: [
//           AbilityData {ability_id: Ability.Produce.id()},
//           AbilityData {ability_id: Ability.Load.id(), params: ["2"]}
//         ]
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: UnitData {
//           id: id,
//           unit: unit,
//           load_data: ["some id", "another id"]
//         },
//         subject_user_data: UserData {
//           funds: 100
//         },
//         game: Game {}
//       }
//       changeset = Changeset.change(action)

//       Changeset {
//         errors: [
//           subject: {"has no space", []}
//         ]
//       } = Ability.Produce.create().validate.(changeset, action)
//     }
//   }

//   describe "apply/2" {
//     test "creates unit when used with tile" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100,
//         fuel: 23
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: TileData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           tile_id: Tile.City.id(),
//           tile: Tile.City.create()
//         },
//         subject_user_data: UserData {
//           funds: 120,
//           user_id: "00000000-0000-0000-0000-000000000000",
//           team: 1,
//           faction: 1,
//           power_data: [
//             PowerData {power_id: Power.CostBonus.id(), params: ["10"]}
//           ]
//         },
//         game: Game {}
//       }

//       {game, _} = Ability.Produce.create().apply.(action)

//       assert Game {
//         user_data: [
//           UserData {
//             funds: 10,
//             user_id: "00000000-0000-0000-0000-000000000000"
//           }
//         ],
//         unit_data: [
//           UnitData {
//             unit_id: unit_id,
//             coord: Coord {x: 0, y: 0},
//             team: 1,
//             faction: 1,
//             fuel: 23,
//             user_id: "00000000-0000-0000-0000-000000000000"
//           }
//         ]
//       } = game
//       assert unit_id == unit.id
//     }

//     test "creates unit when used with unit" {
//       id = UUID.generate()
//       unit = insert(:unit, %{
//         cost: 100,
//         fuel: 23
//       })
//       action = Action {
//         kind: "ability",
//         ability_id: AbilityKind::Produce,
//         params: [unit.id],
//         subject_tile_data_id: id,
//         subject: UnitData {
//           id: id,
//           coord: Coord {x: 0, y: 0},
//           unit_id: unit.id,
//           unit: unit,
//           load_data: []
//         },
//         subject_user_data: UserData {
//           funds: 100,
//           user_id: "00000000-0000-0000-0000-000000000000",
//           team: 1,
//           faction: 1,
//           power_data: [
//             PowerData {power_id: Power.CostBonus.id(), params: ["-10"]}
//           ]
//         },
//         game: Game {}
//       }

//       {game, _} = Ability.Produce.create().apply.(action)

//       assert Game {
//         user_data: [
//           UserData {
//             funds: 10,
//             user_id: "00000000-0000-0000-0000-000000000000"
//           }
//         ],
//         unit_data: [
//           UnitData {
//             id: new_unit_id,
//             unit_id: unit_id,
//             coord: Coord {x: 0, y: 0},
//             team: 1,
//             faction: 1,
//             fuel: 23,
//             state: "exhausted",
//             user_id: "00000000-0000-0000-0000-000000000000"
//           },
//           UnitData {
//             load_data: [new_unit_id],
//             state: "exhausted"
//           }
//         ]
//       } = game
//       assert unit_id == unit.id
//     }
//   }
// }






    // test "create_action/1 kind: ability/produce as tile" {
    //   user = insert(:user)
    //   commander = insert(:commander)
    //   user_data = build(:user_data, %{
    //     turn: true,
    //     user_id: user.id,
    //     commander_id: commander.id,
    //     funds: 2_000
    //   })
    //   unit = insert(:unit, %{cost: 1_000})
    //   tile_data = build(:tile_data, %{
    //     user_id: user_data.user_id,
    //     tile_id: Tile.Base.id(),
    //     faction: user_data.faction,
    //     team: user_data.team,
    //     ability_data: [
    //       build(:ability_data, %{ability_id: Ability.Produce.id()})
    //     ]
    //   })
    //   game = insert(:game, %{
    //     weather: "Clear",
    //     unit_data: [],
    //     user_data: [user_data],
    //     tile_data: [tile_data]
    //   })

    //   tile_data = game.tile_data |> Enum.at(0)

    //   insert(:game_user, %{game: game, faction: 1})
    //   insert(:game_user, %{game: game, faction: 2})
    //   action = build(:action, %{
    //     kind: "ability",
    //     ability_id: AbilityKind::Produce,
    //     subject_tile_data_id: tile_data.id,
    //     params: [unit.id],
    //     game_id: game.id,
    //     user_id: user.id
    //   })
    //   |> Map.from_struct()

    //   assert {:ok, Action {
    //     game: Game {
    //       unit_data: [
    //         UnitData {unit_id: unit_id},
    //       ],
    //       user_data: [
    //         UserData {turn: true, funds: 1_000}
    //       ]
    //     }
    //   }} = Engine.create_action(action)
    //   assert unit.id == unit_id
    // }

    // test "create_action/1 kind: ability/produce as unit" {
    //   user = insert(:user)
    //   commander = insert(:commander)
    //   user_data = build(:user_data, %{
    //     turn: true,
    //     user_id: user.id,
    //     commander_id: commander.id,
    //     funds: 2_000
    //   })
    //   unit = insert(:unit, %{
    //     cost: 1_000,
    //     ability_data: [
    //       build(:ability_data, %{ability_id: Ability.Produce.id()}),
    //       build(:ability_data, %{ability_id: Ability.Load.id(), params: ["1"]})
    //     ]
    //   })
    //   unit_data = build(:unit_data, %{
    //     user_id: user_data.user_id,
    //     unit_id: unit.id
    //   })
    //   game = insert(:game, %{
    //     unit_data: [unit_data],
    //     user_data: [user_data]
    //   })

    //   unit_data = game.unit_data |> Enum.at(0)

    //   insert(:game_user, %{game: game, faction: 1})
    //   insert(:game_user, %{game: game, faction: 2})
    //   action = build(:action, %{
    //     kind: "ability",
    //     ability_id: AbilityKind::Produce,
    //     subject_unit_data_id: unit_data.id,
    //     params: [unit.id],
    //     game_id: game.id,
    //     user_id: user.id
    //   })
    //   |> Map.from_struct()

    //   assert {:ok, Action {
    //     game: Game {
    //       unit_data: [
    //         UnitData {unit_id: unit_one_id, load_data: []} = new_unit,
    //         UnitData {unit_id: unit_two_id, load_data: [unit_three_id]}
    //       ],
    //       user_data: [
    //         UserData {turn: true, funds: 1_000}
    //       ]
    //     }
    //   }} = Engine.create_action(action)
    //   assert unit.id == unit_one_id
    //   assert unit.id == unit_two_id
    //   assert new_unit.id == unit_three_id
    // }