import https from 'https'
import http from 'http'
import { URL } from 'url'
import type { StoreType } from './storeTypes'

interface ApiResponse<T = unknown> {
  data: T
  status: number
}

interface ApiError {
  status: number
  message: string
  detail?: unknown
}

export class ApiClient {
  private store: StoreType

  constructor(store: StoreType) {
    this.store = store
  }

  private getBaseUrl(): string {
    return this.store.get('settings').apiUrl || 'https://marathon.animeenigma.ru/api/v1'
  }

  private getToken(): string | null {
    return this.store.get('token')
  }

  async request<T>(
    method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
    endpoint: string,
    data?: unknown
  ): Promise<ApiResponse<T>> {
    const baseUrl = this.getBaseUrl().replace(/\/$/, '') // Remove trailing slash
    const cleanEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`
    const fullUrl = `${baseUrl}${cleanEndpoint}`
    const url = new URL(fullUrl)
    const token = this.getToken()

    const isHttps = url.protocol === 'https:'
    const httpModule = isHttps ? https : http

    const body = data ? JSON.stringify(data) : undefined

    const options = {
      hostname: url.hostname,
      port: url.port || (isHttps ? 443 : 80),
      path: url.pathname + url.search,
      method,
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        ...(token ? { 'Authorization': `Bearer ${token}` } : {}),
        ...(body ? { 'Content-Length': Buffer.byteLength(body) } : {}),
      },
    }

    console.log(`[ApiClient] ${method} ${url.href}`)

    return new Promise((resolve, reject) => {
      const req = httpModule.request(options, (res) => {
        let responseData = ''

        res.on('data', (chunk) => {
          responseData += chunk
        })

        res.on('end', () => {
          console.log(`[ApiClient] Response status: ${res.statusCode}`)
          console.log(`[ApiClient] Response body: ${responseData.substring(0, 500)}`)
          try {
            const parsed = responseData ? JSON.parse(responseData) : {}

            if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
              resolve({
                data: parsed as T,
                status: res.statusCode,
              })
            } else {
              const error: ApiError = {
                status: res.statusCode || 500,
                message: parsed.detail || 'Request failed',
                detail: parsed.detail,
              }
              reject(error)
            }
          } catch (e) {
            console.error('[ApiClient] Parse error:', e)
            console.error('[ApiClient] Raw response:', responseData)
            reject({
              status: res.statusCode || 500,
              message: 'Failed to parse response',
            })
          }
        })
      })

      req.on('error', (e) => {
        console.error('[ApiClient] Request error:', e)
        reject({
          status: 0,
          message: e.message || 'Network error',
        })
      })

      req.setTimeout(30000, () => {
        console.error('[ApiClient] Request timeout')
        req.destroy()
        reject({
          status: 0,
          message: 'Request timeout',
        })
      })

      if (body) {
        req.write(body)
      }

      req.end()
    })
  }

  async get<T>(endpoint: string): Promise<ApiResponse<T>> {
    return this.request<T>('GET', endpoint)
  }

  async post<T>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> {
    return this.request<T>('POST', endpoint, data)
  }

  async put<T>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> {
    return this.request<T>('PUT', endpoint, data)
  }

  async patch<T>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> {
    return this.request<T>('PATCH', endpoint, data)
  }

  async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
    return this.request<T>('DELETE', endpoint)
  }
}
