#!/usr/bin/env ruby
# FAPI Echo HTTP Server for testing x-fapi-interaction-id header handling
# This server helps test FAPI policy behavior by responding with different
# x-fapi-interaction-id header scenarios

require 'socket'
require 'json'
require 'time'

# Simple HTTP server for FAPI testing
class FapiEchoServer
  def initialize(port = 8080)
    @port = port
    @server = TCPServer.new(port)
    puts "FAPI Echo Server starting on port #{@port}..."
  end

  def start
    loop do
      client = @server.accept
      Thread.new { handle_request(client) }
    end
  end

  private

  def handle_request(client)
    request_line = client.gets
    return unless request_line

    method, path, version = parse_request_line(request_line)
    headers = parse_headers(client)
    body = read_body(client, headers)

    puts "\n=== Incoming Request ==="
    puts "#{method} #{path} #{version}"
    puts "Headers: #{headers.inspect}"
    puts "Body: #{body}" unless body.empty?

    response = build_response(method, path, headers, body)
    client.print response
    client.close
  rescue => e
    puts "Error handling request: #{e.message}"
    puts e.backtrace
    client.close rescue nil
  end

  def parse_request_line(line)
    line.strip.split(' ')
  end

  def parse_headers(client)
    headers = {}
    while (line = client.gets) && !line.strip.empty?
      key, value = line.split(':', 2)
      if key && value
        headers[key.strip.downcase] = value.strip
      else
        headers["_malformed"] = [headers["_malformed"], line].compact.join(";;;")
      end
    end
    headers
  end

  def read_body(client, headers)
    content_length = headers['content-length']
    return '' unless content_length

    client.read(content_length.to_i)
  end

  def build_response(method, path, headers, body)
    # Determine x-fapi-interaction-id based on endpoint
    received_fapi_id = headers['x-fapi-interaction-id']
    response_fapi_id = determine_fapi_id(path, received_fapi_id)

    # Build response body with echo information
    response_body = build_echo_body(method, path, headers, body, response_fapi_id)

    # Build HTTP response
    http_response = "HTTP/1.1 200 OK\r\n"
    http_response << "Content-Type: application/json\r\n"
    http_response << "Content-Length: #{response_body.bytesize}\r\n"

    # Add x-fapi-interaction-id header based on endpoint logic
    if response_fapi_id
      http_response << "x-fapi-interaction-id: #{response_fapi_id}\r\n"
    end

    http_response << "Connection: close\r\n"
    http_response << "\r\n"
    http_response << response_body

    puts "\n=== Outgoing Response ==="
    puts "x-fapi-interaction-id: #{response_fapi_id || '(not set)'}"
    puts "Body: #{response_body}"

    http_response
  end

  def determine_fapi_id(path, received_id)
    case path
    when '/wrong-fapi-id'
      "WRONG_INTERACTION_ID"
    when '/missing-fapi-id'
      # Don't include the header at all
      nil
    else
      # Echo back whatever was received (could be nil)
      received_id
    end
  end

  def build_echo_body(method, path, headers, body, response_fapi_id)
    echo_data = {
      message: "FAPI Echo Server",
      request: {
        method: method,
        path: path,
        headers: headers,
        body: body
      },
      response: {
        'x-fapi-interaction-id': response_fapi_id,
        note: fapi_behavior_note(path)
      },
      timestamp: Time.now.utc.iso8601
    }

    JSON.pretty_generate(echo_data)
  end

  def fapi_behavior_note(path)
    case path
    when '/wrong-fapi-id'
      'Endpoint returns RANDOM x-fapi-interaction-id (should be logged)'
    when '/missing-fapi-id'
      'Endpoint does NOT return x-fapi-interaction-id header (should be logged)'
    else
      'Endpoint echoes received x-fapi-interaction-id header (normal behavior)'
    end
  end
end

# Health check endpoint info
puts <<~HELP
  FAPI Echo Server - Test Endpoints:

  1. /wrong-fapi-id - Returns a wrong interaction ID
  2. /missing-fapi-id - Does NOT return x-fapi-interaction-id header

  All other paths act as standard echo endpoints mirroring back the received x-fapi-interaction-id header.

  The server listens on port 8080 by default.
  Use PORT environment variable to change the port.
HELP

server = FapiEchoServer.new
server.start