import api from '../api';
import { addCSRFTokenToHeaders, getCSRFToken, generateAndStoreCSRFToken } from '../utils/csrfUtils';
import { ApiRequestOptions } from '../hooks/useApi';

// ============================================================================
// Types
// ============================================================================

export interface CoachingContext {
  id: string;
  userId: string;
  mandateId: string;
  instanceId: string;
  title: string;
  description?: string;
  category: string;
  status: string;
  goals?: string;
  insights?: string;
  sessionCount: number;
  taskCount: number;
  lastSessionAt?: string;
  createdAt?: string;
  updatedAt?: string;
}

export interface CoachingSession {
  id: string;
  contextId: string;
  userId: string;
  status: string;
  personaId?: string;
  summary?: string;
  durationSeconds: number;
  messageCount: number;
  competenceScore?: number;
  emailSent: boolean;
  startedAt?: string;
  endedAt?: string;
}

export interface CoachingPersona {
  id: string;
  userId: string;
  key: string;
  label: string;
  description: string;
  gender?: string;
  category: string;
  isActive: boolean;
}

export interface CoachingBadge {
  id: string;
  userId: string;
  badgeKey: string;
  label?: string;
  description?: string;
  icon?: string;
  awardedAt?: string;
}

export interface CoachingMessage {
  id: string;
  sessionId: string;
  contextId: string;
  role: 'user' | 'assistant' | 'system';
  content: string;
  contentType: string;
  audioRef?: string;
  createdAt?: string;
}

export interface CoachingTask {
  id: string;
  contextId: string;
  sessionId?: string;
  title: string;
  description?: string;
  status: string;
  priority: string;
  dueDate?: string;
  completedAt?: string;
  createdAt?: string;
}

export interface CoachingScore {
  id: string;
  contextId: string;
  sessionId: string;
  dimension: string;
  score: number;
  trend: string;
  evidence?: string;
  createdAt?: string;
}

export interface CoachingUserProfile {
  id: string;
  userId: string;
  dailyReminderTime?: string;
  dailyReminderEnabled: boolean;
  emailSummaryEnabled: boolean;
  streakDays: number;
  longestStreak: number;
  totalSessions: number;
  totalMinutes: number;
  lastSessionAt?: string;
}

export interface DashboardData {
  totalContexts: number;
  activeContexts: number;
  totalSessions: number;
  totalMinutes: number;
  streakDays: number;
  longestStreak: number;
  averageScore?: number;
  recentScores: CoachingScore[];
  openTasks: number;
  completedTasks: number;
  goalProgress?: number;
  badges?: CoachingBadge[];
  level?: { number: number; label: string; totalSessions: number };
  contexts: Array<{ id: string; title: string; category: string; sessionCount: number; lastSessionAt?: string; goalProgress?: number }>;
}

export interface SSEEvent {
  type: string;
  data?: any;
  timestamp?: string;
}

export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<any>;

// ============================================================================
// Context API
// ============================================================================

export async function getContextsApi(request: ApiRequestFunction, instanceId: string): Promise<CoachingContext[]> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts`, method: 'get' });
  return data.contexts || [];
}

export async function createContextApi(request: ApiRequestFunction, instanceId: string, body: {
  title: string; description?: string; category?: string; goals?: string[];
}): Promise<CoachingContext> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts`, method: 'post', data: body });
  return data.context;
}

export async function getContextDetailApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<{
  context: CoachingContext; tasks: CoachingTask[]; scores: CoachingScore[]; sessions: CoachingSession[];
}> {
  const data = await request({
    url: `/api/commcoach/${instanceId}/contexts/${contextId}`,
    method: 'get',
    params: { _t: Date.now() },
  });
  const ctx = data?.context ?? data;
  return {
    context: ctx,
    tasks: data?.tasks ?? [],
    scores: data?.scores ?? [],
    sessions: data?.sessions ?? [],
  };
}

export async function updateContextApi(request: ApiRequestFunction, instanceId: string, contextId: string, body: any): Promise<CoachingContext> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}`, method: 'put', data: body });
  return data.context;
}

export async function deleteContextApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<void> {
  await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}`, method: 'delete' });
}

export async function archiveContextApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<CoachingContext> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}/archive`, method: 'post' });
  return data.context;
}

export async function activateContextApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<CoachingContext> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}/activate`, method: 'post' });
  return data.context;
}

// ============================================================================
// Session API
// ============================================================================

export async function startSessionApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<{
  session: CoachingSession; messages: CoachingMessage[]; resumed: boolean;
}> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}/sessions/start`, method: 'post' });
  return data;
}

export async function startSessionStreamApi(
  instanceId: string,
  contextId: string,
  onEvent: (event: SSEEvent) => void,
  onError?: (error: Error) => void,
  onComplete?: () => void,
  personaId?: string,
): Promise<void> {
  try {
    const baseURL = api.defaults.baseURL || '';
    const personaParam = personaId ? `?personaId=${encodeURIComponent(personaId)}` : '';
    const url = `${baseURL}/api/commcoach/${instanceId}/contexts/${contextId}/sessions/start${personaParam}`;

    const headers: Record<string, string> = { 'Content-Type': 'application/json' };
    const authToken = localStorage.getItem('authToken');
    if (authToken) headers['Authorization'] = `Bearer ${authToken}`;
    if (!getCSRFToken()) generateAndStoreCSRFToken();
    addCSRFTokenToHeaders(headers);

    const response = await fetch(url, {
      method: 'POST',
      headers,
      credentials: 'include',
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    if (!response.body) throw new Error('Response body is null');

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

    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop() || '';

        for (const line of lines) {
          if (line.startsWith('data: ')) {
            try {
              const jsonStr = line.slice(6);
              if (jsonStr.trim()) {
                const event: SSEEvent = JSON.parse(jsonStr);
                onEvent(event);
              }
            } catch {
              // skip malformed lines
            }
          }
        }
      }
      onComplete?.();
    } finally {
      reader.releaseLock();
    }
  } catch (error: any) {
    if (onError) onError(error instanceof Error ? error : new Error(String(error)));
    else throw error;
  }
}

export async function getSessionApi(request: ApiRequestFunction, instanceId: string, sessionId: string): Promise<{
  session: CoachingSession; messages: CoachingMessage[];
}> {
  const data = await request({ url: `/api/commcoach/${instanceId}/sessions/${sessionId}`, method: 'get' });
  return data;
}

export async function completeSessionApi(request: ApiRequestFunction, instanceId: string, sessionId: string): Promise<CoachingSession> {
  const data = await request({ url: `/api/commcoach/${instanceId}/sessions/${sessionId}/complete`, method: 'post' });
  return data.session;
}

export async function cancelSessionApi(request: ApiRequestFunction, instanceId: string, sessionId: string): Promise<void> {
  await request({ url: `/api/commcoach/${instanceId}/sessions/${sessionId}/cancel`, method: 'post' });
}

// ============================================================================
// Streaming Chat API
// ============================================================================

export interface SendMessageOptions {
  fileIds?: string[];
  dataSourceIds?: string[];
  featureDataSourceIds?: string[];
  allowedProviders?: string[];
}

export async function sendMessageStreamApi(
  instanceId: string,
  sessionId: string,
  content: string,
  onEvent: (event: SSEEvent) => void,
  onError?: (error: Error) => void,
  onComplete?: () => void,
  signal?: AbortSignal,
  options?: SendMessageOptions,
): Promise<void> {
  try {
    const baseURL = api.defaults.baseURL || '';
    const url = `${baseURL}/api/commcoach/${instanceId}/sessions/${sessionId}/message/stream`;

    const headers: Record<string, string> = { 'Content-Type': 'application/json' };
    const authToken = localStorage.getItem('authToken');
    if (authToken) headers['Authorization'] = `Bearer ${authToken}`;
    if (!getCSRFToken()) generateAndStoreCSRFToken();
    addCSRFTokenToHeaders(headers);

    const body: Record<string, unknown> = { content };
    if (options?.fileIds?.length) body.fileIds = options.fileIds;
    if (options?.dataSourceIds?.length) body.dataSourceIds = options.dataSourceIds;
    if (options?.featureDataSourceIds?.length) body.featureDataSourceIds = options.featureDataSourceIds;
    if (options?.allowedProviders?.length) body.allowedProviders = options.allowedProviders;

    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(body),
      credentials: 'include',
      signal,
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    if (!response.body) throw new Error('Response body is null');

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

    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop() || '';

        for (const line of lines) {
          if (line.startsWith('data: ')) {
            try {
              const jsonStr = line.slice(6);
              if (jsonStr.trim()) {
                const event: SSEEvent = JSON.parse(jsonStr);
                onEvent(event);
              }
            } catch {
              // skip malformed lines
            }
          }
        }
      }
      onComplete?.();
    } finally {
      reader.releaseLock();
    }
  } catch (error: any) {
    if (onError) onError(error instanceof Error ? error : new Error(String(error)));
    else throw error;
  }
}

export async function sendAudioStreamApi(
  instanceId: string,
  sessionId: string,
  audioBlob: Blob,
  onEvent: (event: SSEEvent) => void,
  onError?: (error: Error) => void,
  onComplete?: () => void,
): Promise<void> {
  try {
    const baseURL = api.defaults.baseURL || '';
    const url = `${baseURL}/api/commcoach/${instanceId}/sessions/${sessionId}/audio/stream`;

    const headers: Record<string, string> = { 'Content-Type': 'application/octet-stream' };
    const authToken = localStorage.getItem('authToken');
    if (authToken) headers['Authorization'] = `Bearer ${authToken}`;
    const pathMatch = window.location.pathname.match(/^\/mandates\/([^/]+)\/([^/]+)\/([^/]+)/);
    if (pathMatch) {
      headers['X-Mandate-Id'] = pathMatch[1];
      headers['X-Instance-Id'] = pathMatch[3];
    }
    if (!getCSRFToken()) generateAndStoreCSRFToken();
    addCSRFTokenToHeaders(headers);

    const audioBuffer = await audioBlob.arrayBuffer();

    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: audioBuffer,
      credentials: 'include',
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`HTTP ${response.status}: ${errorText}`);
    }

    if (!response.body) throw new Error('Response body is null');

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

    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop() || '';

        for (const line of lines) {
          if (line.startsWith('data: ')) {
            try {
              const jsonStr = line.slice(6);
              if (jsonStr.trim()) onEvent(JSON.parse(jsonStr));
            } catch { /* skip */ }
          }
        }
      }
      onComplete?.();
    } finally {
      reader.releaseLock();
    }
  } catch (error: any) {
    if (onError) onError(error instanceof Error ? error : new Error(String(error)));
    else throw error;
  }
}

// ============================================================================
// Task API
// ============================================================================

export async function getTasksApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<CoachingTask[]> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}/tasks`, method: 'get' });
  return data.tasks || [];
}

export async function createTaskApi(request: ApiRequestFunction, instanceId: string, contextId: string, body: {
  title: string; description?: string; priority?: string; dueDate?: string;
}): Promise<CoachingTask> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}/tasks`, method: 'post', data: body });
  return data.task;
}

export async function updateTaskApi(request: ApiRequestFunction, instanceId: string, taskId: string, body: any): Promise<CoachingTask> {
  const data = await request({ url: `/api/commcoach/${instanceId}/tasks/${taskId}`, method: 'put', data: body });
  return data.task;
}

export async function updateTaskStatusApi(request: ApiRequestFunction, instanceId: string, taskId: string, status: string): Promise<CoachingTask> {
  const data = await request({ url: `/api/commcoach/${instanceId}/tasks/${taskId}/status`, method: 'put', data: { status } });
  return data.task;
}

export async function deleteTaskApi(request: ApiRequestFunction, instanceId: string, taskId: string): Promise<void> {
  await request({ url: `/api/commcoach/${instanceId}/tasks/${taskId}`, method: 'delete' });
}

// ============================================================================
// Dashboard API
// ============================================================================

export async function getDashboardApi(request: ApiRequestFunction, instanceId: string): Promise<DashboardData> {
  const data = await request({ url: `/api/commcoach/${instanceId}/dashboard`, method: 'get' });
  return data.dashboard;
}

// ============================================================================
// Profile API
// ============================================================================

export async function getProfileApi(request: ApiRequestFunction, instanceId: string): Promise<CoachingUserProfile> {
  const data = await request({ url: `/api/commcoach/${instanceId}/profile`, method: 'get' });
  return data.profile;
}

export async function updateProfileApi(request: ApiRequestFunction, instanceId: string, body: any): Promise<CoachingUserProfile> {
  const data = await request({ url: `/api/commcoach/${instanceId}/profile`, method: 'put', data: body });
  return data.profile;
}

// ============================================================================
// Persona API (Iteration 2)
// ============================================================================

export async function getPersonasApi(request: ApiRequestFunction, instanceId: string): Promise<CoachingPersona[]> {
  const data = await request({ url: `/api/commcoach/${instanceId}/personas`, method: 'get' });
  return data.personas || [];
}

export async function createPersonaApi(request: ApiRequestFunction, instanceId: string, body: {
  label: string; description: string; gender?: string; systemPromptOverride?: string;
}): Promise<CoachingPersona> {
  const data = await request({ url: `/api/commcoach/${instanceId}/personas`, method: 'post', data: body });
  return data.persona;
}

export async function deletePersonaApi(request: ApiRequestFunction, instanceId: string, personaId: string): Promise<void> {
  await request({ url: `/api/commcoach/${instanceId}/personas/${personaId}`, method: 'delete' });
}

// ============================================================================
// Badge API (Iteration 2)
// ============================================================================

export async function getBadgesApi(request: ApiRequestFunction, instanceId: string): Promise<CoachingBadge[]> {
  const data = await request({ url: `/api/commcoach/${instanceId}/badges`, method: 'get' });
  return data.badges || [];
}

// ============================================================================
// Export API (Iteration 2)
// ============================================================================

export function getDossierExportUrl(instanceId: string, contextId: string, format: string = 'md'): string {
  const baseURL = api.defaults.baseURL || '';
  return `${baseURL}/api/commcoach/${instanceId}/contexts/${contextId}/export?format=${format}`;
}

export function getSessionExportUrl(instanceId: string, sessionId: string, format: string = 'md'): string {
  const baseURL = api.defaults.baseURL || '';
  return `${baseURL}/api/commcoach/${instanceId}/sessions/${sessionId}/export?format=${format}`;
}

// ============================================================================
// Score History API (Iteration 2)
// ============================================================================

export async function getScoreHistoryApi(request: ApiRequestFunction, instanceId: string, contextId: string): Promise<Record<string, Array<{
  score: number; trend: string; evidence?: string; createdAt?: string; sessionId?: string;
}>>> {
  const data = await request({ url: `/api/commcoach/${instanceId}/contexts/${contextId}/scores/history`, method: 'get' });
  return data.history || {};
}
