# frozen_string_literal: true

class Project < ApplicationRecord
  has_many :events, dependent: :destroy

  validates :name, presence: true
  validates :slug, presence: true, uniqueness: true
  validates :public_key, presence: true, uniqueness: true

  scope :by_slug, ->(slug) { where(slug: slug) }
  scope :by_public_key, ->(key) { where(public_key: key) }
  scope :enabled, -> { where(enabled: true) }

  before_validation :generate_slug, if: :name?
  before_validation :generate_public_key, if: -> { public_key.blank? }
  before_validation :set_default_settings, if: -> { settings.blank? }

  def broadcast_events_refresh
    # Broadcast to the events stream for this project
    broadcast_refresh_to(self, "events")
  end

  def broadcast_rules_refresh
    # Broadcast to the rules stream for this project (for future rule management UI)
    broadcast_refresh_to(self, "rules")
  end

  def self.find_by_dsn(dsn)
    # Parse DSN: https://public_key@host/project_id
    return nil unless dsn.present?

    # Extract public_key from DSN
    match = dsn.match(/https?:\/\/([^@]+)@/)
    return nil unless match

    public_key = match[1]
    find_by(public_key: public_key)
  end

  def self.find_by_project_id(project_id)
    # Try slug first (nicer URLs), then fall back to ID
    find_by(slug: project_id.to_s) || find_by(id: project_id.to_i)
  end

  def dsn
    host = Current.baffle_host || ENV.fetch("BAFFLE_HOST", "localhost:3000")
    protocol = host.include?("localhost") ? "http" : "https"
    "#{protocol}://#{public_key}@#{host}/#{slug}"
  end

  def internal_dsn
    internal_host = Current.baffle_internal_host || ENV.fetch("BAFFLE_INTERNAL_HOST", nil)
    return nil unless internal_host.present?

    host = internal_host
    protocol = "http"  # Internal connections use HTTP
    "#{protocol}://#{public_key}@#{host}/#{slug}"
  end

  # WAF Analytics Methods
  def recent_events(limit: 100)
    events.recent.limit(limit)
  end

  def recent_blocked_events(limit: 100)
    events.blocked.recent.limit(limit)
  end

  def recent_rate_limited_events(limit: 100)
    events.rate_limited.recent.limit(limit)
  end

  def top_blocked_ips(limit: 10, time_range: 1.hour.ago)
    events.blocked
           .where(timestamp: time_range)
           .group(:ip_address)
           .select('ip_address, COUNT(*) as count')
           .order('count DESC')
           .limit(limit)
  end

  def event_count(time_range = nil)
    if time_range
      events.where(timestamp: time_range).count
    else
      events.count
    end
  end

  def blocked_count(time_range = nil)
    if time_range
      events.blocked.where(timestamp: time_range).count
    else
      events.blocked.count
    end
  end

  def allowed_count(time_range = nil)
    if time_range
      events.allowed.where(timestamp: time_range).count
    else
      events.allowed.count
    end
  end

  # Helper method to parse settings safely
  def parsed_settings
    if settings.is_a?(String)
      JSON.parse(settings || '{}')
    else
      settings || {}
    end
  rescue JSON::ParserError
    {}
  end

  # WAF Configuration Methods
  def rate_limit_enabled?
    parsed_settings.dig('rate_limiting', 'enabled') != false
  end

  def rate_limit_threshold
    parsed_settings.dig('rate_limiting', 'threshold') || 100
  end

  def custom_rules_enabled?
    parsed_settings.dig('custom_rules', 'enabled') == true
  end

  def block_by_country_enabled?
    parsed_settings.dig('geo_blocking', 'enabled') == true
  end

  def blocked_countries
    parsed_settings.dig('geo_blocking', 'blocked_countries') || []
  end

  def block_datacenters_enabled?
    parsed_settings.dig('datacenter_blocking', 'enabled') == true
  end

  # WAF Rule Management
  def add_ip_rule(ip_address, action, expires_at: nil, reason: nil)
    # This will integrate with the IP rules storage system
    # For now, store in settings as a temporary solution
    current_settings = parsed_settings
    ip_rules = current_settings['ip_rules'] || {}
    ip_rules[ip_address] = {
      action: action,
      expires_at: expires_at&.iso8601,
      reason: reason,
      created_at: Time.current.iso8601
    }
    update(settings: current_settings.merge('ip_rules' => ip_rules))
  end

  def remove_ip_rule(ip_address)
    current_settings = parsed_settings
    ip_rules = current_settings['ip_rules'] || {}
    ip_rules.delete(ip_address)
    update(settings: current_settings.merge('ip_rules' => ip_rules))
  end

  def blocked_ips
    ip_rules = parsed_settings['ip_rules'] || {}
    ip_rules.select { |_ip, rule| rule['action'] == 'block' }.keys
  end

  def waf_status
    return 'disabled' unless enabled?
    return 'active' if events.where(timestamp: 1.hour.ago..).exists?
    'idle'
  end

  private

  def generate_slug
    self.slug = name&.parameterize&.downcase
  end

  def generate_public_key
    # Generate a random 32-character hex string for WAF authentication
    self.public_key = SecureRandom.hex(16)
  end

  def set_default_settings
    self.settings = {
      'rate_limiting' => {
        'enabled' => true,
        'threshold' => 100,  # requests per minute
        'window' => 60       # seconds
      },
      'geo_blocking' => {
        'enabled' => false,
        'blocked_countries' => []
      },
      'datacenter_blocking' => {
        'enabled' => false,
        'allow_known_datacenters' => true
      },
      'custom_rules' => {
        'enabled' => false,
        'rules' => []
      },
      'ip_rules' => {},
      'challenge' => {
        'enabled' => true,
        'provider' => 'recaptcha'
      }
    }
  end
end
