defmodule Web.Settings.IdentityProviders.Mock.Show do
  use Web, :live_view
  import Web.Settings.IdentityProviders.Components
  alias Domain.{Auth, Actors}

  def mount(%{"provider_id" => provider_id}, _session, socket) do
    with {:ok, provider} <-
           Auth.fetch_provider_by_id(provider_id, socket.assigns.subject),
         {:ok, identities_count_by_provider_id} <-
           Auth.fetch_identities_count_grouped_by_provider_id(socket.assigns.subject),
         {:ok, groups_count_by_provider_id} <-
           Actors.fetch_groups_count_grouped_by_provider_id(socket.assigns.subject) do
      safe_to_delete_actors_count = Actors.count_synced_actors_for_provider(provider)

      {:ok,
       assign(socket,
         provider: provider,
         identities_count_by_provider_id: identities_count_by_provider_id,
         groups_count_by_provider_id: groups_count_by_provider_id,
         safe_to_delete_actors_count: safe_to_delete_actors_count,
         page_title: "Identity Provider #{provider.name}"
       )}
    else
      _ -> raise Web.LiveErrors.NotFoundError
    end
  end

  def render(assigns) do
    ~H"""
    <.breadcrumbs account={@account}>
      <.breadcrumb path={~p"/#{@account}/settings/identity_providers"}>
        Identity Providers Settings
      </.breadcrumb>

      <.breadcrumb path={~p"/#{@account}/settings/identity_providers/mock/#{@provider}"}>
        {@provider.name}
      </.breadcrumb>
    </.breadcrumbs>

    <.section>
      <:title>
        Identity Provider: <code>{@provider.name}</code>
        <span :if={not is_nil(@provider.disabled_at)} class="text-primary-600">(disabled)</span>
        <span :if={not is_nil(@provider.deleted_at)} class="text-red-600">(deleted)</span>
      </:title>
      <:action :if={is_nil(@provider.deleted_at)}>
        <.edit_button navigate={
          ~p"/#{@account}/settings/identity_providers/mock/#{@provider.id}/edit"
        }>
          Edit
        </.edit_button>
      </:action>
      <:action :if={is_nil(@provider.deleted_at)}>
        <.button_with_confirmation
          :if={is_nil(@provider.disabled_at)}
          id="disable"
          style="warning"
          icon="hero-lock-closed"
          on_confirm="disable"
        >
          <:dialog_title>Confirm disabling the Provider</:dialog_title>
          <:dialog_content>
            Are you sure you want to disable this Provider?
            This will <strong>immediately</strong>
            sign out all Actors who were signed in using this Provider and directory sync will be paused.
          </:dialog_content>
          <:dialog_confirm_button>
            Disable
          </:dialog_confirm_button>
          <:dialog_cancel_button>
            Cancel
          </:dialog_cancel_button>
          Disable
        </.button_with_confirmation>
        <.button_with_confirmation
          :if={not is_nil(@provider.disabled_at)}
          id="enable"
          style="warning"
          confirm_style="primary"
          icon="hero-lock-open"
          on_confirm="enable"
        >
          <:dialog_title>Confirm enabling the Provider</:dialog_title>
          <:dialog_content>
            Are you sure you want to enable this provider?
          </:dialog_content>
          <:dialog_confirm_button>
            Enable
          </:dialog_confirm_button>
          <:dialog_cancel_button>
            Cancel
          </:dialog_cancel_button>
          Enable
        </.button_with_confirmation>
      </:action>
      <:help>
        <p>
          Directory sync is enabled for this provider. Users and groups will be synced every few
          minutes on average, but could take longer for very large organizations.
        </p>
        <p>
          <.website_link path="/kb/authenticate/directory-sync">
            Read more
          </.website_link>
          about directory sync.
        </p>
      </:help>
      <:content>
        <.header>
          <:title>Details</:title>
        </.header>

        <.flash_group flash={@flash} />

        <.flash :if={@safe_to_delete_actors_count > 0} kind={:warning}>
          You have {@safe_to_delete_actors_count} Actor(s) that were synced from this provider and do not have any other identities.
          <.button_with_confirmation
            id="delete_stale_actors"
            style="danger"
            icon="hero-trash-solid"
            on_confirm="delete_stale_actors"
            class="mt-4"
          >
            <:dialog_title>Confirm deletion of stale Actors</:dialog_title>
            <:dialog_content>
              Are you sure you want to delete all Actors that were synced synced from this provider and do not have any other identities?
            </:dialog_content>
            <:dialog_confirm_button>
              Delete Actors
            </:dialog_confirm_button>
            <:dialog_cancel_button>
              Cancel
            </:dialog_cancel_button>
            Delete Actors
          </.button_with_confirmation>
        </.flash>

        <div class="bg-white overflow-hidden">
          <.vertical_table id="provider">
            <.vertical_table_row>
              <:label>Name</:label>
              <:value>
                {@provider.name}
                <.assigned_default_badge provider={@provider} />
              </:value>
            </.vertical_table_row>
            <.vertical_table_row>
              <:label>Description</:label>
              <:value>
                The Mock Identity Provider is a test provider that generates random Actors and
                Groups using the same sync mechanism as the other directory sync adapters. The
                difference is that it performs no actual network requests and generates random
                data.
              </:value>
            </.vertical_table_row>
            <.vertical_table_row>
              <:label>Status</:label>
              <:value>
                <.status provider={@provider} />
              </:value>
            </.vertical_table_row>

            <.vertical_table_row>
              <:label>Sync Status</:label>
              <:value>
                <.sync_status
                  account={@account}
                  provider={@provider}
                  identities_count_by_provider_id={@identities_count_by_provider_id}
                  groups_count_by_provider_id={@groups_count_by_provider_id}
                />
                <div
                  :if={
                    (is_nil(@provider.last_synced_at) and not is_nil(@provider.last_sync_error)) or
                      not is_nil(@provider.sync_disabled_at) or
                      (@provider.last_syncs_failed > 3 and not is_nil(@provider.last_sync_error))
                  }
                  class="w-fit p-3 mt-2 border-l-4 border-red-500 bg-red-100 rounded-md"
                >
                  <p class="font-medium text-red-700">
                    IdP provider reported an error during the last sync:
                  </p>
                  <div class="flex items-center mt-1">
                    <span class="text-red-500 font-mono">{@provider.last_sync_error}</span>
                  </div>
                </div>
              </:value>
            </.vertical_table_row>
            <.vertical_table_row>
              <:label>Number of actors to generate</:label>
              <:value>{@provider.adapter_config["num_actors"]}</:value>
            </.vertical_table_row>
            <.vertical_table_row>
              <:label>Number of groups to generate</:label>
              <:value>{@provider.adapter_config["num_groups"]}</:value>
            </.vertical_table_row>
            <.vertical_table_row>
              <:label>Max number of actors per group</:label>
              <:value>{@provider.adapter_config["max_actors_per_group"]}</:value>
            </.vertical_table_row>
            <.vertical_table_row>
              <:label>Created</:label>
              <:value>
                <.created_by schema={@provider} />
              </:value>
            </.vertical_table_row>
          </.vertical_table>
        </div>
      </:content>
    </.section>

    <.danger_zone :if={is_nil(@provider.deleted_at)}>
      <:action>
        <.button_with_confirmation
          id="delete_identity_provider"
          style="danger"
          icon="hero-trash-solid"
          on_confirm="delete"
        >
          <:dialog_title>Confirm deletion of Identity Provider</:dialog_title>
          <:dialog_content>
            Are you sure you want to delete this provider? This will remove <strong>all</strong>
            Actors and Groups associated with this provider.
          </:dialog_content>
          <:dialog_confirm_button>
            Delete Identity Provider
          </:dialog_confirm_button>
          <:dialog_cancel_button>
            Cancel
          </:dialog_cancel_button>
          Delete Identity Provider
        </.button_with_confirmation>
      </:action>
    </.danger_zone>
    """
  end

  def handle_event("delete", _params, socket) do
    {:ok, _deleted_provider} =
      Auth.delete_provider(socket.assigns.provider, socket.assigns.subject)

    {:noreply,
     push_navigate(socket, to: ~p"/#{socket.assigns.account}/settings/identity_providers")}
  end

  def handle_event("delete_stale_actors", _params, socket) do
    :ok =
      Actors.delete_stale_synced_actors_for_provider(
        socket.assigns.provider,
        socket.assigns.subject
      )

    {:noreply,
     push_navigate(socket, to: view_provider(socket.assigns.account, socket.assigns.provider))}
  end

  def handle_event("enable", _params, socket) do
    attrs = %{disabled_at: nil}
    {:ok, provider} = Auth.update_provider(socket.assigns.provider, attrs, socket.assigns.subject)
    {:ok, provider} = Auth.fetch_provider_by_id(provider.id, socket.assigns.subject)

    {:noreply, assign(socket, provider: provider)}
  end

  def handle_event("disable", _params, socket) do
    attrs = %{disabled_at: DateTime.utc_now()}
    {:ok, provider} = Auth.update_provider(socket.assigns.provider, attrs, socket.assigns.subject)
    {:ok, provider} = Auth.fetch_provider_by_id(provider.id, socket.assigns.subject)

    {:noreply, assign(socket, provider: provider)}
  end
end
