# Copyright 2023 Clivern. All rights reserved.
# Use of this source code is governed by the MIT
# license that can be found in the LICENSE file.

defmodule LynxWeb.LockController do
  @moduledoc """
  Lock Controller
  """

  use LynxWeb, :controller

  require Logger

  alias Lynx.Module.LockModule
  alias Lynx.Module.EnvironmentModule

  plug :auth when action in [:lock, :unlock]

  defp auth(conn, _opts) do
    with {user, secret} <- Plug.BasicAuth.parse_basic_auth(conn) do
      result =
        EnvironmentModule.is_access_allowed(%{
          team_slug: conn.params["t_slug"],
          project_slug: conn.params["p_slug"],
          env_slug: conn.params["e_slug"],
          username: user,
          secret: secret
        })

      case result do
        {:error, msg} ->
          Logger.info(msg)

          conn
          |> put_status(:forbidden)
          |> render("error.json", %{
            message: "Access is forbidden"
          })
          |> halt

        {:ok, _, _, _} ->
          conn
      end
    else
      _ -> conn |> Plug.BasicAuth.request_basic_auth() |> halt()
    end
  end

  @doc """
  Lock Endpoint
  """
  def lock(conn, params) do
    is_locked =
      LockModule.is_locked(%{
        t_slug: params["t_slug"] || "",
        p_slug: params["p_slug"] || "",
        e_slug: params["e_slug"] || ""
      })

    case is_locked do
      {:locked, lock} ->
        conn
        |> put_status(:locked)
        |> render("lock_data.json", %{
          lock: lock
        })

      {:not_found, msg} ->
        conn
        |> put_status(:not_found)
        |> render("error.json", %{
          message: msg
        })

      {:success, _} ->
        action =
          LockModule.lock_action(%{
            t_slug: params["t_slug"] || "",
            p_slug: params["p_slug"] || "",
            e_slug: params["e_slug"] || "",
            uuid: params["ID"] || "",
            operation: params["Operation"] || "",
            info: params["Info"] || "",
            who: params["Who"] || "",
            version: params["Version"] || "",
            path: params["Path"] || ""
          })

        case action do
          {:success, ""} ->
            conn
            |> put_status(:ok)
            |> render("lock.json", %{})

          {:not_found, msg} ->
            conn
            |> put_status(:not_found)
            |> render("error.json", %{
              message: msg
            })

          {:error, msg} ->
            conn
            |> put_status(:internal_server_error)
            |> render("error.json", %{
              message: msg
            })
        end
    end
  end

  @doc """
  Unlock Endpoint
  """
  def unlock(conn, params) do
    action =
      LockModule.unlock_action(%{
        t_slug: params["t_slug"] || "",
        p_slug: params["p_slug"] || "",
        e_slug: params["e_slug"] || ""
      })

    case action do
      {:success, ""} ->
        conn
        |> put_status(:ok)
        |> render("unlock.json", %{})

      {:not_found, msg} ->
        conn
        |> put_status(:not_found)
        |> render("error.json", %{
          message: msg
        })

      {:error, msg} ->
        conn
        |> put_status(:internal_server_error)
        |> render("error.json", %{
          message: msg
        })
    end
  end
end
