import { join } from 'node:path';
import { homedir } from 'node:os';

const PROXY_PORT = Number(process.env.ANTHROPIC_PROXY_PORT ?? '5051');
const ANTHROPIC_API_BASE = 'https://api.anthropic.com';
const CREDENTIALS_PATH = join(homedir(), '.claude', '.credentials.json');

// Generate a random proxy secret at startup — shared with Claude Code spawns
// Prefix must match a real Anthropic API key format (sk-ant-api03-*) so Claude Code accepts it
export const proxySecret = `sk-ant-api03-${crypto.randomUUID()}`;

type CredentialsFile = {
  claudeAiOauth?: {
    accessToken?: string;
  };
};

async function readOAuthToken(): Promise<string | null> {
  try {
    const file = Bun.file(CREDENTIALS_PATH);
    if (!(await file.exists())) return null;
    const data = (await file.json()) as CredentialsFile;
    return data.claudeAiOauth?.accessToken?.trim() || null;
  } catch {
    return null;
  }
}

export function startAnthropicProxy() {
  Bun.serve({
    port: PROXY_PORT,
    hostname: '127.0.0.1',
    idleTimeout: 0,

    async fetch(req) {
      const url = new URL(req.url);

      // Validate proxy secret
      const incomingKey = req.headers.get('x-api-key');
      if (incomingKey !== proxySecret) {
        return new Response(JSON.stringify({ error: 'Unauthorized' }), {
          status: 401,
          headers: { 'Content-Type': 'application/json' },
        });
      }

      // Read fresh OAuth token
      const token = await readOAuthToken();
      if (!token) {
        return new Response(JSON.stringify({ error: 'No OAuth token available' }), {
          status: 502,
          headers: { 'Content-Type': 'application/json' },
        });
      }

      // Build upstream URL
      const upstream = `${ANTHROPIC_API_BASE}${url.pathname}${url.search}`;

      // Clone headers, replace proxy secret with real OAuth token
      const headers = new Headers(req.headers);
      headers.set('x-api-key', token);
      headers.delete('host');

      // Read request body fully before forwarding — avoids stream-in-stream issues
      const body = req.body ? await req.arrayBuffer() : null;

      // Forward request
      const upstreamRes = await fetch(upstream, {
        method: req.method,
        headers,
        body,
      });

      // Build clean response headers
      const resHeaders = new Headers();
      for (const [key, value] of upstreamRes.headers) {
        const lower = key.toLowerCase();
        // Skip hop-by-hop and encoding headers that may have been consumed by fetch
        if (lower === 'content-encoding' || lower === 'content-length' || lower === 'transfer-encoding') continue;
        resHeaders.set(key, value);
      }

      return new Response(upstreamRes.body, {
        status: upstreamRes.status,
        statusText: upstreamRes.statusText,
        headers: resHeaders,
      });
    },
  });

  console.log(`[anthropic-proxy] listening on 127.0.0.1:${PROXY_PORT}`);
}
