import axios, { AxiosInstance, AxiosError } from 'axios';
import {
  User,
  LoginRequest,
  RegisterRequest,
  AuthTokens,
  Medication,
  CreateMedicationRequest,
  UpdateMedicationRequest,
  DrugInteraction,
  CheckInteractionRequest,
  CheckNewMedicationRequest,
  HealthStat,
  CreateHealthStatRequest,
  TrendData,
  LabResult,
  ApiError
} from '../types/api';

// API base URL - change this for production
const API_BASE = process.env.REACT_APP_API_URL || 'http://solaria:8001/api';

class ApiService {
  private client: AxiosInstance;
  private token: string | null = null;

  constructor() {
    this.client = axios.create({
      baseURL: API_BASE,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    // Load token from localStorage
    this.token = localStorage.getItem('token');
    if (this.token) {
      this.setAuthHeader(this.token);
    }

    // Request interceptor
    this.client.interceptors.request.use(
      (config) => {
        if (this.token) {
          config.headers.Authorization = `Bearer ${this.token}`;
        }
        return config;
      },
      (error) => Promise.reject(error)
    );

    // Response interceptor for error handling
    this.client.interceptors.response.use(
      (response) => response,
      (error: AxiosError) => {
        if (error.response?.status === 401) {
          // Clear token and redirect to login
          this.logout();
          window.location.href = '/login';
        }
        return Promise.reject(this.handleError(error));
      }
    );
  }

  private handleError(error: AxiosError): ApiError {
    if (error.response) {
      const data = error.response.data as any;
      return {
        message: data.error || data.message || 'An error occurred',
        code: String(error.response.status),
        details: data,
      };
    } else if (error.request) {
      return {
        message: 'No response from server',
        code: 'NETWORK_ERROR',
      };
    } else {
      return {
        message: error.message || 'Unknown error',
        code: 'UNKNOWN',
      };
    }
  }

  private setAuthHeader(token: string) {
    this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
  }

  setToken(token: string) {
    this.token = token;
    localStorage.setItem('token', token);
    this.setAuthHeader(token);
  }

  getToken(): string | null {
    return this.token;
  }

  logout() {
    this.token = null;
    localStorage.removeItem('token');
    delete this.client.defaults.headers.common['Authorization'];
  }

  // Authentication endpoints
  async login(email: string, password: string): Promise<AuthTokens> {
    const response = await this.client.post<AuthTokens>('/auth/login', {
      email,
      password,
    });
    this.setToken(response.data.token);
    return response.data;
  }

  async register(data: RegisterRequest): Promise<AuthTokens> {
    const response = await this.client.post<AuthTokens>('/auth/register', data);
    this.setToken(response.data.token);
    return response.data;
  }

  async getCurrentUser(): Promise<User> {
    const response = await this.client.get<User>('/auth/me');
    return response.data;
  }

  // Medication endpoints
  async getMedications(): Promise<Medication[]> {
    const response = await this.client.get<Medication[]>('/medications');
    return response.data;
  }

  async getMedication(id: string): Promise<Medication> {
    const response = await this.client.get<Medication>(`/medications/${id}`);
    return response.data;
  }

  async createMedication(data: CreateMedicationRequest): Promise<Medication> {
    const response = await this.client.post<Medication>('/medications', data);
    return response.data;
  }

  async updateMedication(id: string, data: UpdateMedicationRequest): Promise<Medication> {
    const response = await this.client.put<Medication>(`/medications/${id}`, data);
    return response.data;
  }

  async deleteMedication(id: string): Promise<void> {
    await this.client.delete(`/medications/${id}`);
  }

  // Drug Interaction endpoints (Phase 2.8)
  async checkInteractions(medications: string[]): Promise<DrugInteraction[]> {
    const response = await this.client.post<DrugInteraction[]>('/interactions/check', {
      medications,
    });
    return response.data;
  }

  async checkNewMedication(name: string, dosage: string): Promise<DrugInteraction[]> {
    const response = await this.client.post<DrugInteraction[]>('/interactions/check-new', {
      name,
      dosage,
    });
    return response.data;
  }

  // Health Statistics endpoints
  async getHealthStats(): Promise<HealthStat[]> {
    const response = await this.client.get<HealthStat[]>('/health-stats');
    return response.data;
  }

  async getHealthStat(id: string): Promise<HealthStat> {
    const response = await this.client.get<HealthStat>(`/health-stats/${id}`);
    return response.data;
  }

  async createHealthStat(data: CreateHealthStatRequest): Promise<HealthStat> {
    const response = await this.client.post<HealthStat>('/health-stats', data);
    return response.data;
  }

  async updateHealthStat(id: string, data: Partial<CreateHealthStatRequest>): Promise<HealthStat> {
    const response = await this.client.put<HealthStat>(`/health-stats/${id}`, data);
    return response.data;
  }

  async deleteHealthStat(id: string): Promise<void> {
    await this.client.delete(`/health-stats/${id}`);
  }

  async getHealthTrends(): Promise<TrendData[]> {
    const response = await this.client.get<TrendData[]>('/health-stats/trends');
    return response.data;
  }

  // Lab Results endpoints
  async getLabResults(): Promise<LabResult[]> {
    const response = await this.client.get<LabResult[]>('/lab-results');
    return response.data;
  }

  async getLabResult(id: string): Promise<LabResult> {
    const response = await this.client.get<LabResult>(`/lab-results/${id}`);
    return response.data;
  }

  async createLabResult(data: any): Promise<LabResult> {
    const response = await this.client.post<LabResult>('/lab-results', data);
    return response.data;
  }

  async updateLabResult(id: string, data: any): Promise<LabResult> {
    const response = await this.client.put<LabResult>(`/lab-results/${id}`, data);
    return response.data;
  }

  async deleteLabResult(id: string): Promise<void> {
    await this.client.delete(`/lab-results/${id}`);
  }
}

// Export singleton instance
export const apiService = new ApiService();
export default apiService;
