import {
  ConditionType,
  CreateDailyConditionInput,
  CreateDailyConditionOutput,
  DailyCondition,
  DailyConditionsFilters,
  GetDailyConditionOutput,
  GetDailyConditionsOutput,
  GetLaboratoriesOutput,
  GetLaboratoryOutput,
  Laboratory,
  UpdateDailyConditionInput,
  UpdateDailyConditionOutput,
} from './types'

// Базовый URL для API (может быть настроен через переменные окружения)
const BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api'

// API для лабораторий
export const laboratoriesApi = {
  // Получить все лаборатории
  getAll: async (): Promise<Laboratory[]> => {
    const response = await fetch(`${BASE_URL}/laboratories/`)
    if (!response.ok) {
      throw new Error('Ошибка загрузки лабораторий')
    }
    const data: GetLaboratoriesOutput = await response.json()
    return data.laboratories
  },

  // Получить лабораторию по ID
  getById: async (id: string): Promise<Laboratory | null> => {
    const response = await fetch(`${BASE_URL}/laboratories/${id}`)
    if (!response.ok) {
      if (response.status === 404) {
        return null
      }
      throw new Error('Ошибка получения лаборатории')
    }
    const data: GetLaboratoryOutput = await response.json()
    return data.laboratory
  },
}

// API для ежедневных условий
export const dailyConditionsApi = {
  // Получить условия по фильтрам
  get: async (
    filters: DailyConditionsFilters = {}
  ): Promise<DailyCondition[]> => {
    const searchParams = new URLSearchParams()
    if (filters.laboratory_id) {
      searchParams.append('laboratory_id', filters.laboratory_id)
    }
    if (filters.start_date) {
      searchParams.append('start_date', filters.start_date)
    }
    if (filters.end_date) {
      searchParams.append('end_date', filters.end_date)
    }

    const url = searchParams.toString()
      ? `${BASE_URL}/daily-conditions/?${searchParams}`
      : `${BASE_URL}/daily-conditions/`

    const response = await fetch(url)
    if (!response.ok) {
      throw new Error('Ошибка загрузки условий')
    }
    const data: GetDailyConditionsOutput = await response.json()
    return data.daily_conditions
  },

  // Получить конкретное условие по ID
  getById: async (id: string): Promise<DailyCondition | null> => {
    const response = await fetch(`${BASE_URL}/daily-conditions/${id}`)
    if (!response.ok) {
      if (response.status === 404) {
        return null
      }
      throw new Error('Ошибка получения условия')
    }
    const data: GetDailyConditionOutput = await response.json()
    return data.daily_condition
  },

  // Создать новые условия
  create: async (input: CreateDailyConditionInput): Promise<string> => {
    const response = await fetch(`${BASE_URL}/daily-conditions/`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(input),
    })
    if (!response.ok) {
      const error = await response
        .json()
        .catch(() => ({ message: 'Ошибка сохранения условий' }))
      throw new Error(error.message || 'Ошибка сохранения условий')
    }
    const data: CreateDailyConditionOutput = await response.json()
    return data.id
  },

  // Обновить условия
  update: async (
    id: string,
    input: UpdateDailyConditionInput
  ): Promise<string> => {
    const response = await fetch(`${BASE_URL}/daily-conditions/${id}`, {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(input),
    })
    if (!response.ok) {
      throw new Error('Ошибка обновления условий')
    }
    const data: UpdateDailyConditionOutput = await response.json()
    return data.id
  },

  // Удалить условия
  delete: async (id: string): Promise<void> => {
    const response = await fetch(`${BASE_URL}/daily-conditions/${id}`, {
      method: 'DELETE',
    })
    if (!response.ok) {
      throw new Error('Ошибка удаления условий')
    }
  },
}

// Комбинированный API для работы с элементом
export const elementApi = {
  // Получить лабораторию с её типами условий
  getLaboratoryData: async (
    laboratoryId: string
  ): Promise<{
    laboratory: Laboratory
    conditionTypes: ConditionType[]
  }> => {
    const laboratory = await laboratoriesApi.getById(laboratoryId)
    if (!laboratory) {
      throw new Error('Лаборатория не найдена')
    }

    return {
      laboratory,
      conditionTypes: laboratory.condition_types,
    }
  },

  // Получить ежедневные условия для конкретной лаборатории и даты
  getDailyConditions: async (
    laboratoryId: string,
    date: string
  ): Promise<DailyCondition | null> => {
    const conditions = await dailyConditionsApi.get({
      laboratory_id: laboratoryId,
      start_date: date,
      end_date: date,
    })
    return conditions.length > 0 ? conditions[0] : null
  },

  // Сохранить или обновить условия из элемента
  saveElementConditions: async (data: {
    laboratoryId: string
    date: string
    conditions: Record<string, any>
    existingConditionId?: string
  }): Promise<DailyCondition> => {
    const input: CreateDailyConditionInput | UpdateDailyConditionInput = {
      laboratory_id: data.laboratoryId,
      measurement_date: data.date,
      conditions: data.conditions,
    }

    let conditionId: string

    if (data.existingConditionId) {
      // Обновляем существующие условия
      conditionId = await dailyConditionsApi.update(
        data.existingConditionId,
        input as UpdateDailyConditionInput
      )
    } else {
      // Создаем новые условия
      conditionId = await dailyConditionsApi.create(
        input as CreateDailyConditionInput
      )
    }

    // Получаем обновленные данные
    const savedCondition = await dailyConditionsApi.getById(conditionId)
    if (!savedCondition) {
      throw new Error('Ошибка получения сохраненных условий')
    }

    return savedCondition
  },
}

// Вспомогательные функции
export const verificationConditionsUtils = {
  // Валидация значения условия
  validateConditionValue: (
    value: any,
    dataType: string = 'string',
    minValue?: number,
    maxValue?: number
  ): { isValid: boolean; error?: string } => {
    if (dataType === 'number') {
      const numValue = parseFloat(value)
      if (isNaN(numValue)) {
        return { isValid: false, error: 'Должно быть числом' }
      }
      if (minValue !== undefined && numValue < minValue) {
        return { isValid: false, error: `Минимальное значение: ${minValue}` }
      }
      if (maxValue !== undefined && numValue > maxValue) {
        return { isValid: false, error: `Максимальное значение: ${maxValue}` }
      }
    }
    return { isValid: true }
  },

  // Форматирование значения с единицей измерения
  formatValueWithUnit: (value: any, unit?: string): string => {
    if (value === undefined || value === null || value === '') {
      return '-'
    }
    return unit ? `${value} ${unit}` : value.toString()
  },

  // Получение ключа условия для хранения в conditions JSON (обычно используется ID типа условия)
  getConditionKey: (conditionTypeId: string): string => {
    return conditionTypeId
  },

  // Генерация ключа на основе названия условия (для обратной совместимости)
  generateConditionKey: (conditionTypeName: string): string => {
    return conditionTypeName
      .toLowerCase()
      .replace(/\s+/g, '_')
      .replace(/[^\w]/g, '')
  },

  // Проверка, является ли строка валидным UUID
  isValidUUID: (str: string): boolean => {
    const uuidRegex =
      /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
    return uuidRegex.test(str)
  },
}
