import axios, { AxiosError, AxiosResponse } from 'axios';
import { isSensorData, isDevice, isHistoryResponse, isApiResponse } from '../utils/typeGuards';

const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://sensor.geumdo.net';

const api = axios.create({
  baseURL: API_BASE_URL,
  timeout: 30000, // 30초로 증가
});

// API 설정 로깅
console.log('🔧 API Configuration:', {
  baseURL: API_BASE_URL,
  timeout: 30000,
  env: process.env.REACT_APP_API_URL
});

// API 응답 구조 검증 함수 - 강화된 검증
const validateApiResponse = (response: any, endpoint: string): boolean => {
  if (!response || typeof response !== 'object') {
    console.error(`Invalid response type for ${endpoint}:`, typeof response);
    return false;
  }
  
  // 엔드포인트별 검증 로직
  if (endpoint.includes('/latest')) {
    return response.hasOwnProperty('data') && response.data !== null;
  }
  
  if (endpoint.includes('/devices') && !endpoint.includes('/history')) {
    return response.hasOwnProperty('devices') && Array.isArray(response.devices);
  }
  
  if (endpoint.includes('/history')) {
    const isValid = response.hasOwnProperty('success') && 
                   response.hasOwnProperty('data') && 
                   response.hasOwnProperty('total') &&
                   Array.isArray(response.data);
    
    if (!isValid) {
      console.error(`Invalid history response structure for ${endpoint}:`, {
        hasSuccess: response.hasOwnProperty('success'),
        hasData: response.hasOwnProperty('data'),
        hasTotal: response.hasOwnProperty('total'),
        dataIsArray: Array.isArray(response.data),
        response: response
      });
    }
    
    return isValid;
  }
  
  return true;
};

// 센서 데이터 필수 필드 검증
const validateSensorDataFields = (data: any): boolean => {
  const requiredFields = [
    'id', 'device_id', 'node_id', 'temperature', 'humidity', 
    'longitude', 'latitude', 'recorded_time', 'received_time'
  ];
  
  return requiredFields.every(field => {
    const value = data[field];
    if (field === 'device_id' || field === 'recorded_time' || field === 'received_time') {
      return typeof value === 'string' && value.length > 0;
    }
    if (field === 'id' || field === 'node_id') {
      return typeof value === 'number' && Number.isInteger(value) && value >= 0;
    }
    if (field === 'temperature' || field === 'humidity' || field === 'longitude' || field === 'latitude') {
      return typeof value === 'number' && !isNaN(value) && isFinite(value);
    }
    return true;
  });
};

// 디바이스 데이터 필수 필드 검증
const validateDeviceFields = (data: any): boolean => {
  const requiredFields = [
    'id', 'device_id', 'name', 'description', 'status', 
    'last_seen', 'created_at', 'updated_at'
  ];
  
  return requiredFields.every(field => {
    const value = data[field];
    if (field === 'id') {
      return typeof value === 'number' && Number.isInteger(value) && value >= 0;
    }
    if (['device_id', 'name', 'status'].includes(field)) {
      return typeof value === 'string' && value.length > 0;
    }
    if (field === 'description') {
      return typeof value === 'string'; // description은 빈 문자열도 허용
    }
    if (['last_seen', 'created_at', 'updated_at'].includes(field)) {
      return typeof value === 'string' && value.length > 0 && !isNaN(Date.parse(value));
    }
    return true;
  });
};

// 데이터 타입 일관성 검사
const validateDataConsistency = (data: any, type: 'sensor' | 'device' | 'history'): boolean => {
  try {
    switch (type) {
      case 'sensor':
        return isSensorData(data) && validateSensorDataFields(data);
      case 'device':
        return isDevice(data) && validateDeviceFields(data);
      case 'history':
        return isHistoryResponse(data);
      default:
        return false;
    }
  } catch (error) {
    console.error(`Data consistency validation failed for type ${type}:`, error);
    return false;
  }
};

// 전역 에러 처리 인터셉터
api.interceptors.response.use(
  (response: AxiosResponse) => {
    console.log('API Response:', response.config.url, response.data);
    // 응답 구조 검증
    if (!validateApiResponse(response.data, response.config.url || '')) {
      throw new Error('Invalid API response structure');
    }
    return response;
  },
  (error: AxiosError) => {
    console.error('Axios Error Details:', {
      message: error.message,
      code: error.code,
      status: error.response?.status,
      statusText: error.response?.statusText,
      data: error.response?.data,
      url: error.config?.url,
      method: error.config?.method,
      headers: error.config?.headers
    });
    
    // 네트워크 에러 처리
    if (!error.response) {
      console.error('Network error:', error.message);
      throw new Error('네트워크 연결에 실패했습니다. 인터넷 연결을 확인해주세요.');
    }
    
    // HTTP 상태 코드별 에러 처리
    const status = error.response.status;
    let errorMessage = '알 수 없는 오류가 발생했습니다.';
    
    switch (status) {
      case 400:
        errorMessage = '잘못된 요청입니다.';
        break;
      case 401:
        errorMessage = '인증이 필요합니다.';
        break;
      case 403:
        errorMessage = '접근 권한이 없습니다.';
        break;
      case 404:
        errorMessage = '요청한 리소스를 찾을 수 없습니다.';
        break;
      case 500:
        errorMessage = '서버 내부 오류가 발생했습니다.';
        break;
      case 503:
        errorMessage = '서비스가 일시적으로 사용할 수 없습니다.';
        break;
      default:
        errorMessage = `서버 오류 (${status})가 발생했습니다.`;
    }
    
    console.error(`API Error ${status}:`, error.response.data);
    throw new Error(errorMessage);
  }
);

export interface SensorData {
  id: number;
  device_id: string;
  node_id: number;
  temperature: number;
  humidity: number;
  longitude: number;
  latitude: number;
  // 추가 센서 데이터 필드
  float_value?: number;
  signed_int32_value?: number;
  unsigned_int32_value?: number;
  raw_tem?: number;
  raw_hum?: number;
  // 환경 센서 데이터
  pm10?: number;
  pm25?: number;
  pressure?: number;
  illumination?: number;
  tvoc?: number;
  co2?: number;
  o2?: number;
  co?: number;
  recorded_time: string;
  received_time: string;
}

export interface Device {
  id: number;
  device_id: string;
  name: string;
  description: string;
  status: string;
  last_seen: string;
  created_at: string;
  updated_at: string;
}

export interface HistoryResponse {
  success: boolean;
  data: SensorData[];
  total: number;
}

// 센서 데이터 수신
export const sendSensorData = async (data: any): Promise<any> => {
  console.log('📤 센서 데이터 전송 시작:', data);
  try {
    const response = await api.post('/api/sensor-data', data);
    console.log('✅ 센서 데이터 전송 성공:', response.data);
    return response.data;
  } catch (error) {
    console.error('❌ 센서 데이터 전송 실패:', error);
    throw error;
  }
};

// 최신 센서 데이터 조회 - 타입 안전성 및 데이터 검증 강화
export const getLatestData = async (deviceId: string): Promise<SensorData | null> => {
  const startTime = Date.now();
  const url = `/api/devices/${deviceId}/latest`;
  
  console.log(`📡 최신 데이터 요청 시작 - 디바이스: ${deviceId}`);
  console.log(`🔗 요청 URL: ${process.env.REACT_APP_API_URL || 'http://sensor.geumdo.net'}${url}`);
  
  try {
    const response = await api.get(url);
    const responseTime = Date.now() - startTime;
    
    console.log(`✅ 최신 데이터 요청 성공 - 디바이스: ${deviceId} (응답시간: ${responseTime}ms)`);
    console.log(`📊 응답 데이터 크기: ${JSON.stringify(response.data).length} bytes`);
    
    // 응답 데이터 검증
    if (!response.data || !response.data.data) {
      console.warn(`⚠️ 디바이스 ${deviceId}에 대한 데이터가 없습니다.`);
      console.log('🔍 응답 구조:', response.data);
      return null;
    }
    
    const sensorData = response.data.data;
    
    // 필수 필드 검증
    if (!sensorData.device_id || typeof sensorData.device_id !== 'string') {
      console.error(`❌ 디바이스 ${deviceId} 응답에서 잘못된 device_id:`, sensorData);
      return null;
    }
    
    // 데이터 타입 일관성 검사
    if (!validateDataConsistency(sensorData, 'sensor')) {
      console.error(`❌ 디바이스 ${deviceId} 데이터 일관성 검증 실패:`, sensorData);
      return null;
    }
    
    console.log(`✅ 디바이스 ${deviceId} 데이터 검증 완료:`, {
      device_id: sensorData.device_id,
      temperature: sensorData.temperature,
      humidity: sensorData.humidity,
      recorded_time: sensorData.recorded_time
    });
    
    return sensorData;
  } catch (error) {
    const responseTime = Date.now() - startTime;
    console.error(`❌ 디바이스 ${deviceId} 최신 데이터 요청 실패 (응답시간: ${responseTime}ms):`, error);
    
    if (error instanceof Error) {
      console.error('🔍 에러 상세 정보:', {
        message: error.message,
        name: error.name,
        stack: error.stack
      });
    }
    
    return null;
  }
};

// 히스토리 데이터 조회 - 데이터 검증 강화
export const getHistory = async (
  deviceId: string, 
  limit: number = 100, 
  offset: number = 0,
  startTime?: string,
  endTime?: string
): Promise<HistoryResponse> => {
  const startTimeRequest = Date.now();
  const params: any = { limit, offset };
  if (startTime) params.start_time = startTime;
  if (endTime) params.end_time = endTime;
  
  console.log(`📡 히스토리 데이터 요청 시작 - 디바이스: ${deviceId}`);
  console.log(`🔧 요청 파라미터:`, params);
  
  try {
    const response = await api.get(`/api/devices/${deviceId}/history`, { params });
    const responseTime = Date.now() - startTimeRequest;
    
    console.log(`✅ 히스토리 데이터 요청 성공 - 디바이스: ${deviceId} (응답시간: ${responseTime}ms)`);
    console.log(`📊 수신된 데이터 수: ${response.data.data?.length || 0}개`);
    
    // 응답 데이터 검증
    if (!validateDataConsistency(response.data, 'history')) {
      console.error(`❌ 디바이스 ${deviceId} 히스토리 데이터 검증 실패:`, response.data);
      throw new Error('Invalid history data format');
    }
    
    console.log(`✅ 디바이스 ${deviceId} 히스토리 데이터 검증 완료`);
    
    return response.data;
  } catch (error) {
    const responseTime = Date.now() - startTimeRequest;
    console.error(`❌ 디바이스 ${deviceId} 히스토리 데이터 요청 실패 (응답시간: ${responseTime}ms):`, error);
    throw error;
  }
};

// 디바이스 목록 조회 - 데이터 검증 강화
export const getDevices = async (): Promise<Device[]> => {
  const startTime = Date.now();
  
  try {
    const fullUrl = `${api.defaults.baseURL}/api/devices`;
    console.log('🔍 디바이스 목록 조회 시작');
    console.log('🔗 요청 URL:', fullUrl);
    console.log('🔧 API 설정:', {
      baseURL: api.defaults.baseURL,
      timeout: api.defaults.timeout,
      headers: api.defaults.headers
    });
    
    const response = await api.get('/api/devices');
    const responseTime = Date.now() - startTime;
    
    console.log('✅ 디바이스 목록 조회 성공 (응답시간:', responseTime, 'ms)');
    console.log('📊 응답 데이터:', response.data);
    
    // 응답 데이터 검증
    if (!response.data.devices || !Array.isArray(response.data.devices)) {
      console.error('❌ 잘못된 디바이스 응답 구조:', response.data);
      throw new Error('Invalid devices data format');
    }
    
    console.log(`📊 총 디바이스 수: ${response.data.devices.length}개`);
    
    // 각 디바이스 데이터 검증
    const validDevices = response.data.devices.filter((device: any) => {
      if (!validateDataConsistency(device, 'device')) {
        console.warn('⚠️ 잘못된 디바이스 데이터 발견:', device);
        return false;
      }
      return true;
    });
    
    if (validDevices.length !== response.data.devices.length) {
      console.warn(`⚠️ ${response.data.devices.length - validDevices.length}개의 잘못된 디바이스 데이터가 필터링되었습니다.`);
    }
    
    console.log(`✅ 유효한 디바이스 수: ${validDevices.length}개`);
    return validDevices;
  } catch (error) {
    const responseTime = Date.now() - startTime;
    console.error('❌ 디바이스 목록 조회 실패 (응답시간:', responseTime, 'ms):', error);
    throw error;
  }
};

// 헬스체크
export const healthCheck = async (): Promise<any> => {
  const startTime = Date.now();
  console.log('🏥 헬스체크 시작');
  
  try {
    const response = await api.get('/api/health');
    const responseTime = Date.now() - startTime;
    
    console.log('✅ 헬스체크 성공 (응답시간:', responseTime, 'ms):', response.data);
    return response.data;
  } catch (error) {
    const responseTime = Date.now() - startTime;
    console.error('❌ 헬스체크 실패 (응답시간:', responseTime, 'ms):', error);
    throw error;
  }
};

export default api; 