const PERCEPTION_API_BASE = '/api/v1';
const TOKEN_KEY = 'auth_token';
function authHeader(): Record<string, string> {
  const t = localStorage.getItem(TOKEN_KEY);
  return t ? { Authorization: `Bearer ${t}` } : {};
}

export type ImpactLevel = 'high' | 'medium' | 'low';
export type EventStatus = 'enacted' | 'draft' | 'consultation';
export type EventSource = 'MIIT' | 'UN-ECE' | 'ISO' | '国标委' | 'EUR-Lex' | 'IATF';

export interface RegulationEvent {
  id: string;
  source: EventSource;
  source_label: string;
  standard_code: string;
  title: string;
  summary: string;
  impact_level: ImpactLevel;
  published_at: string;
  effective_at: string | null;
  category: string;
  tags: string[];
  source_url: string;
  status: EventStatus;
}

export interface PerceptionStats {
  total: number;
  high_impact: number;
  medium_impact: number;
  low_impact: number;
  recent_90d: number;
}

export interface EventListResponse {
  events: RegulationEvent[];
  total: number;
}

export interface AffectedDoc {
  doc_id: string;
  doc_name: string;
  score: number;
  snippet: string;
  clause: string;
}

export interface AnalysisSSEMessage {
  type: 'sources' | 'content' | 'done' | 'error';
  docs?: AffectedDoc[];
  text?: string;
}

export async function getPerceptionStats(): Promise<PerceptionStats> {
  const res = await fetch(`${PERCEPTION_API_BASE}/perception/stats`, { headers: authHeader() });
  if (!res.ok) throw new Error(`stats failed: ${res.status}`);
  return res.json() as Promise<PerceptionStats>;
}

export async function listEvents(params?: {
  source?: string;
  impact_level?: string;
  limit?: number;
}): Promise<EventListResponse> {
  const query = new URLSearchParams();
  if (params?.source) query.set('source', params.source);
  if (params?.impact_level) query.set('impact_level', params.impact_level);
  if (params?.limit) query.set('limit', String(params.limit));
  const res = await fetch(`${PERCEPTION_API_BASE}/perception/events?${query.toString()}`, { headers: authHeader() });
  if (!res.ok) throw new Error(`list events failed: ${res.status}`);
  return res.json() as Promise<EventListResponse>;
}

export async function analyzeEvent(
  eventId: string,
  onMessage: (msg: AnalysisSSEMessage) => void,
  onComplete?: () => void,
  signal?: AbortSignal,
): Promise<void> {
  try {
    const res = await fetch(`${PERCEPTION_API_BASE}/perception/events/${eventId}/analyze`, {
      method: 'POST',
      headers: { Accept: 'text/event-stream', ...authHeader() },
      signal,
    });
    if (!res.ok || !res.body) throw new Error(`analyze failed: ${res.status}`);

    const reader = res.body.getReader();
    const decoder = new TextDecoder();
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      buffer += decoder.decode(value, { stream: true });
      const parts = buffer.split('\n\n');
      buffer = parts.pop() ?? '';
      for (const block of parts) {
        if (!block.trim()) continue;
        let eventName = 'message';
        const dataLines: string[] = [];
        for (const line of block.split('\n')) {
          if (line.startsWith('event:')) eventName = line.slice(6).trim();
          else if (line.startsWith('data:')) dataLines.push(line.slice(5).trim());
        }
        const payload = dataLines.join('\n');
        if (!payload) continue;

        if (eventName === 'sources') {
          try {
            const docs = JSON.parse(payload) as AffectedDoc[];
            onMessage({ type: 'sources', docs });
          } catch { /* ignore */ }
        } else if (eventName === 'content') {
          onMessage({ type: 'content', text: payload });
        } else if (eventName === 'done') {
          onMessage({ type: 'done' });
        } else if (eventName === 'error') {
          onMessage({ type: 'error', text: payload });
        }
      }
    }
    if (buffer.trim()) {
      // flush remaining
    }
    onComplete?.();
  } catch (err) {
    if (err instanceof DOMException && err.name === 'AbortError') return;
    onMessage({ type: 'error', text: err instanceof Error ? err.message : String(err) });
    onComplete?.();
  }
}
