import { StudyListResponse, HistoryResponse, PruningResponse, StudyStatus } from '../types';

const API_BASE = '/api';

export interface OptimizationControlResponse {
  success: boolean;
  message: string;
  pid?: number;
}

export interface ReadmeResponse {
  content: string;
  path: string;
}

export interface ReportResponse {
  content: string;
  generated_at?: string;
}

export interface ConfigResponse {
  config: Record<string, any>;
  objectives: Array<{
    name: string;
    direction: string;
    weight?: number;
    target?: number;
    units?: string;
  }>;
  design_variables: Array<{
    name: string;
    min: number;
    max: number;
    baseline?: number;
    units?: string;
  }>;
  constraints?: Array<{
    name: string;
    type: string;
    max_value?: number;
    min_value?: number;
    units?: string;
  }>;
}

export interface ProcessStatus {
  is_running: boolean;
  pid?: number;
  start_time?: string;
  iteration?: number;
  fea_count?: number;
  nn_count?: number;
}

export interface ModelFile {
  name: string;
  path: string;
  extension: string;
  size_bytes: number;
  size_display: string;
  modified: string;
}

export interface ModelFilesResponse {
  study_id: string;
  model_dir: string;
  files: ModelFile[];
  count: number;
}

class ApiClient {
  async getStudies(): Promise<StudyListResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies`);
    if (!response.ok) throw new Error('Failed to fetch studies');
    return response.json();
  }

  async getStudyStatus(studyId: string): Promise<StudyStatus> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/status`);
    if (!response.ok) throw new Error('Failed to fetch study status');
    return response.json();
  }

  async getStudyHistory(studyId: string): Promise<HistoryResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/history`);
    if (!response.ok) throw new Error('Failed to fetch study history');
    return response.json();
  }

  async getStudyPruning(studyId: string): Promise<PruningResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/pruning`);
    if (!response.ok) throw new Error('Failed to fetch pruning data');
    return response.json();
  }

  async createStudy(config: any): Promise<{ study_id: string }> {
    const response = await fetch(`${API_BASE}/optimization/studies`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(config),
    });
    if (!response.ok) throw new Error('Failed to create study');
    return response.json();
  }

  async getStudyReport(studyId: string): Promise<ReportResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/report`);
    if (!response.ok) throw new Error('Failed to fetch report');
    return response.json();
  }

  async getStudyReadme(studyId: string): Promise<ReadmeResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/readme`);
    if (!response.ok) throw new Error('Failed to fetch README');
    return response.json();
  }

  async getStudyConfig(studyId: string): Promise<ConfigResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/config`);
    if (!response.ok) throw new Error('Failed to fetch config');
    return response.json();
  }

  async getConsoleOutput(studyId: string, lines: number = 200): Promise<{
    lines: string[];
    total_lines: number;
    displayed_lines: number;
    log_file: string | null;
    timestamp: string;
    message?: string;
  }> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/console?lines=${lines}`);
    if (!response.ok) throw new Error('Failed to fetch console output');
    return response.json();
  }

  async getProcessStatus(studyId: string): Promise<ProcessStatus> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/process`);
    if (!response.ok) throw new Error('Failed to fetch process status');
    return response.json();
  }

  // Control operations
  async startOptimization(studyId: string, options?: {
    freshStart?: boolean;
    maxIterations?: number;
    feaBatchSize?: number;
    tuneTrials?: number;
    ensembleSize?: number;
    patience?: number;
  }): Promise<OptimizationControlResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/start`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(options || {}),
    });
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'Failed to start optimization');
    }
    return response.json();
  }

  async stopOptimization(studyId: string): Promise<OptimizationControlResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/stop`, {
      method: 'POST',
    });
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'Failed to stop optimization');
    }
    return response.json();
  }

  async validateOptimization(studyId: string, options?: {
    topN?: number;
  }): Promise<OptimizationControlResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/validate`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(options || {}),
    });
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'Failed to start validation');
    }
    return response.json();
  }

  async generateReport(studyId: string): Promise<ReportResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/report/generate`, {
      method: 'POST',
    });
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'Failed to generate report');
    }
    return response.json();
  }

  // Optuna dashboard
  async launchOptunaDashboard(studyId: string): Promise<{ url: string; pid: number }> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/optuna-dashboard`, {
      method: 'POST',
    });
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'Failed to launch Optuna dashboard');
    }
    return response.json();
  }

  // Model files
  async getModelFiles(studyId: string): Promise<ModelFilesResponse> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/model-files`);
    if (!response.ok) throw new Error('Failed to fetch model files');
    return response.json();
  }

  async openFolder(studyId: string, folderType: 'model' | 'results' | 'setup' = 'model'): Promise<{ success: boolean; message: string; path: string }> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/open-folder?folder_type=${folderType}`, {
      method: 'POST',
    });
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'Failed to open folder');
    }
    return response.json();
  }

  async getBestSolution(studyId: string): Promise<{
    study_id: string;
    best_trial: {
      trial_number: number;
      objective: number;
      design_variables: Record<string, number>;
      user_attrs?: Record<string, any>;
      timestamp?: string;
    } | null;
    first_trial: {
      trial_number: number;
      objective: number;
      design_variables: Record<string, number>;
    } | null;
    improvements: Record<string, {
      initial: number;
      final: number;
      improvement_pct: number;
      absolute_change: number;
    }>;
    total_trials: number;
  }> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/best-solution`);
    if (!response.ok) throw new Error('Failed to fetch best solution');
    return response.json();
  }

  async exportData(studyId: string, format: 'csv' | 'json' | 'config'): Promise<{
    filename?: string;
    content: string;
    content_type?: string;
    study_id?: string;
    total_trials?: number;
    trials?: any[];
  }> {
    const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/export/${format}`);
    if (!response.ok) throw new Error(`Failed to export ${format}`);
    return response.json();
  }
}

export const apiClient = new ApiClient();
