defmodule ToweropsWeb.DeviceLive.NestedShowTest do
  use ToweropsWeb.ConnCase

  import Phoenix.LiveViewTest

  alias Towerops.Monitoring
  alias Towerops.Organizations
  alias Towerops.Sites

  setup :register_and_log_in_user

  setup %{user: user} do
    {:ok, organization} = Organizations.create_organization(%{name: "Test Org"}, user.id)

    {:ok, site} =
      Sites.create_site(%{
        name: "Test Site",
        organization_id: organization.id
      })

    {:ok, device} =
      Towerops.Devices.create_device(%{
        name: "Test Router",
        ip_address: "192.168.1.1",
        site_id: site.id,
        organization_id: organization.id
      })

    %{organization: organization, site: site, device: device}
  end

  describe "Show" do
    test "displays device information", %{conn: conn, device: device, organization: _org} do
      {:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      assert html =~ device.name
      assert html =~ device.ip_address
    end

    test "displays overview tab by default", %{conn: conn, device: device, organization: _org} do
      {:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      assert html =~ "Overview"
    end

    test "displays metrics when device has checks", %{
      conn: conn,
      device: device,
      organization: _org
    } do
      # Create some checks
      Monitoring.create_check(%{
        device_id: device.id,
        status: :success,
        response_time_ms: 10,
        checked_at: DateTime.utc_now()
      })

      Monitoring.create_check(%{
        device_id: device.id,
        status: :success,
        response_time_ms: 15,
        checked_at: DateTime.utc_now()
      })

      Monitoring.create_check(%{
        device_id: device.id,
        status: :failure,
        response_time_ms: nil,
        checked_at: DateTime.utc_now()
      })

      {:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      assert html =~ "Device Information"
    end

    test "displays empty state when no checks exist", %{
      conn: conn,
      device: device,
      organization: _org
    } do
      {:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      assert html =~ device.name
    end

    test "refreshes data periodically", %{conn: conn, device: device, organization: _org} do
      {:ok, view, _html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      # Trigger a status change
      Monitoring.create_check(%{
        device_id: device.id,
        status: :failure,
        response_time_ms: nil,
        checked_at: DateTime.utc_now()
      })

      # Send refresh message
      send(view.pid, :refresh_data)

      # Poll for processing with early exit (max 50ms)
      Enum.reduce_while(1..5, nil, fn _, _ ->
        try do
          {:halt, render(view)}
        rescue
          _ ->
            Process.sleep(10)
            {:cont, nil}
        end
      end)

      # View should still be alive
      assert render(view)
    end

    test "requires authentication", %{device: device, organization: _org} do
      conn = build_conn()
      {:error, redirect} = live(conn, ~p"/devices/#{device.id}")

      assert {:redirect, %{to: path}} = redirect
      assert path == ~p"/users/log-in"
    end

    test "handles equipment_status_changed event", %{
      conn: conn,
      device: device,
      organization: _org
    } do
      {:ok, view, _html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      # Simulate status change event
      send(view.pid, {:device_status_changed, device.id, :up, 25})

      # Poll for processing with early exit (max 50ms)
      Enum.reduce_while(1..5, nil, fn _, _ ->
        try do
          {:halt, render(view)}
        rescue
          _ ->
            Process.sleep(10)
            {:cont, nil}
        end
      end)

      # View should still be alive and render
      assert render(view)
    end

    test "handles discovery_completed event", %{
      conn: conn,
      device: device,
      organization: _org
    } do
      {:ok, view, _html} = live(conn, ~p"/devices/#{device.id}?tab=overview")

      # Simulate discovery completed event
      send(view.pid, {:discovery_completed, device.id})

      # Poll for processing with early exit (max 50ms)
      html =
        Enum.reduce_while(1..5, nil, fn _, _ ->
          try do
            {:halt, render(view)}
          rescue
            _ ->
              Process.sleep(10)
              {:cont, nil}
          end
        end) || render(view)

      assert html =~ "Discovery completed"
    end

    test "switches to different tabs", %{conn: conn, device: device, organization: _org} do
      {:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=events")

      assert html =~ device.name
    end
  end
end
