defmodule Mix.Tasks.Backfill.Checks do
  @shortdoc "Backfill checks for existing SNMP-enabled devices"

  @moduledoc """
  Backfill checks for existing devices with SNMP discovery data.

  This task creates check records for all devices that have existing
  snmp_device records with sensors, interfaces, processors, or storage.

  Usage:
      mix backfill.checks
      mix backfill.checks --dry-run
  """

  use Mix.Task

  import Ecto.Query

  alias Towerops.Devices
  alias Towerops.Repo
  alias Towerops.Snmp.Discovery

  require Logger

  @impl Mix.Task
  def run(args) do
    Mix.Task.run("app.start")

    dry_run = "--dry-run" in args

    if dry_run do
      IO.puts("=== DRY RUN MODE - No changes will be made ===\n")
    end

    devices =
      Repo.all(
        from d in Devices.Device,
          where: d.snmp_enabled == true,
          preload: [:organization, snmp_device: [:sensors, :interfaces, :processors, :storage]]
      )

    IO.puts("Found #{length(devices)} SNMP-enabled devices\n")

    Enum.each(devices, fn device ->
      if device.snmp_device do
        backfill_device_checks(device, dry_run)
      else
        IO.puts("Skipping #{device.name} - no SNMP discovery data")
      end
    end)

    IO.puts("\n=== Backfill complete ===")
  end

  defp backfill_device_checks(device, dry_run) do
    snmp_device = device.snmp_device
    sensor_count = length(snmp_device.sensors)
    interface_count = length(snmp_device.interfaces)
    processor_count = length(snmp_device.processors)
    storage_count = length(snmp_device.storage)

    total = sensor_count + interface_count + processor_count + storage_count

    cond do
      total == 0 ->
        IO.puts("Skipping #{device.name} - no discovered entities")

      dry_run ->
        print_device_summary(device, sensor_count, interface_count, processor_count, storage_count)
        IO.puts("  [DRY RUN] Would create #{total} checks")

      true ->
        print_device_summary(device, sensor_count, interface_count, processor_count, storage_count)
        create_and_report_checks(device, snmp_device)
    end
  end

  defp print_device_summary(device, sensors, interfaces, processors, storage) do
    IO.puts("\n#{device.name} (#{device.ip_address}):")
    IO.puts("  - #{sensors} sensors")
    IO.puts("  - #{interfaces} interfaces")
    IO.puts("  - #{processors} processors")
    IO.puts("  - #{storage} storage")
  end

  defp create_and_report_checks(device, snmp_device) do
    result = Discovery.create_checks_from_discovery(device, snmp_device)
    created = result.sensors + result.interfaces + result.processors + result.storage

    if result.errors == [] do
      IO.puts("  ✓ Created #{created} checks")
    else
      IO.puts("  ✓ Created #{created} checks (#{length(result.errors)} errors)")
      print_errors(result.errors)
    end
  end

  defp print_errors(errors) do
    Enum.each(errors, fn error ->
      IO.puts("    ⚠ #{error.type}: #{error.message}")
    end)
  end
end
