# frozen_string_literal: true

class Issue < ApplicationRecord
  has_many :events, dependent: :nullify

  enum :status, { open: 0, resolved: 1, ignored: 2 }

  validates :title, presence: true

  scope :recent, -> { order(last_seen: :desc) }
  scope :by_frequency, -> { order(count: :desc) }

  # Callbacks for email notifications
  after_create :notify_new_issue, if: :should_notify_new_issue?
  after_update :notify_issue_reopened, if: :was_reopened?

  # Real-time updates
  after_create_commit do
    broadcast_refresh
  end

  after_update_commit do
    broadcast_refresh  # Refreshes the issue show page
    broadcast_refresh_to("issues")  # Refreshes the issues index
  end

  def self.group_event(event_payload)
    fingerprint = generate_fingerprint(event_payload)

    find_or_create_by(fingerprint: fingerprint) do |issue|
      issue.title = extract_title(event_payload)
      issue.exception_type = extract_exception_type(event_payload)
      issue.first_seen = Time.current
      issue.last_seen = Time.current
      issue.status = :open
    end
  end

  def self.generate_fingerprint(payload)
    # Use Sentry's fingerprint if provided
    if payload["fingerprint"].present?
      payload["fingerprint"].join("::")
    else
      # Generate from exception type + location
      type = payload.dig("exception", "values", 0, "type")
      file = payload.dig("exception", "values", 0, "stacktrace", "frames", -1, "filename")
      line = payload.dig("exception", "values", 0, "stacktrace", "frames", -1, "lineno")

      # Fallback to message if no exception
      if type.blank?
        message = payload["message"] || "Unknown Error"
        Digest::MD5.hexdigest(message)
      else
        "#{type}::#{file}::#{line}"
      end
    end
  end

  def self.extract_title(payload)
    payload.dig("exception", "values", 0, "value") ||
      payload["message"] ||
      payload.dig("exception", "values", 0, "type") ||
      "Unknown Error"
  end

  def self.extract_exception_type(payload)
    payload.dig("exception", "values", 0, "type")
  end

  def record_event!(timestamp: Time.current)
    update!(
      count: count + 1,
      last_seen: timestamp
    )
  end

  private

  def notify_new_issue
    IssueMailer.new_issue(self).deliver_later
  end

  def notify_issue_reopened
    IssueMailer.issue_reopened(self).deliver_later
  end

  def should_notify_new_issue?
    # Only notify for new issues in production environment or if explicitly enabled
    Rails.env.production? || ENV['SPLAT_EMAIL_NOTIFICATIONS'] == 'true'
  end

  def was_reopened?
    # Check if status changed from resolved to open
    saved_change_to_status?(from: 1, to: 0)  # resolved=1, open=0
  end
end
