import {
  Plant,
  Task,
  MaintenanceRecord,
  HarvestRecord,
  PlantHistory,
  PlantObservation,
  Fertilizer,
  Chemical
} from '../types';

class ApiService {
  private baseUrl: string;

  constructor() {
    // Use environment variable or fallback to localhost for development
    this.baseUrl = import.meta.env.VITE_API_URL || '/api';
  }

  private async handleResponse<T>(response: Response): Promise<T> {
    if (!response.ok) {
      const errorText = await response.text();
      let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
      
      try {
        const errorJson = JSON.parse(errorText);
        errorMessage = errorJson.error || errorMessage;
      } catch {
        // If not JSON, use the text as error message
        errorMessage = errorText || errorMessage;
      }
      
      throw new Error(errorMessage);
    }

    const contentType = response.headers.get('content-type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new Error('Server returned non-JSON response. Expected JSON data.');
    }
    
    return response.json();
  }

  private async makeRequest<T>(
    endpoint: string, 
    options: RequestInit = {}
  ): Promise<T> {
    const url = `${this.baseUrl}${endpoint}`;
    
    const defaultOptions: RequestInit = {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
    };

    const requestOptions = { ...defaultOptions, ...options };

    try {
      const response = await fetch(url, requestOptions);
      return this.handleResponse<T>(response);
    } catch (error) {
      if (error instanceof TypeError && error.message.includes('fetch')) {
        throw new Error('Unable to connect to the server. Please check if the backend is running.');
      }
      throw error;
    }
  }

  // Plant API methods
  async getPlants(): Promise<Plant[]> {
    return this.makeRequest<Plant[]>('/plants');
  }

  async createPlant(plant: Omit<Plant, 'id' | 'createdAt' | 'updatedAt'>): Promise<Plant> {
    return this.makeRequest<Plant>('/plants', {
      method: 'POST',
      body: JSON.stringify(plant),
    });
  }

  async updatePlant(id: number, plant: Partial<Plant>): Promise<Plant> {
    return this.makeRequest<Plant>(`/plants/${id}`, {
      method: 'PUT',
      body: JSON.stringify(plant),
    });
  }

  async deletePlant(id: number): Promise<void> {
    return this.makeRequest<void>(`/plants/${id}`, {
      method: 'DELETE',
    });
  }

  // Task API methods
  async getTasks(): Promise<Task[]> {
    return this.makeRequest<Task[]>('/tasks');
  }

  async createTask(task: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Promise<Task> {
    return this.makeRequest<Task>('/tasks', {
      method: 'POST',
      body: JSON.stringify(task),
    });
  }

  async updateTask(id: number, task: Partial<Task>): Promise<Task> {
    return this.makeRequest<Task>(`/tasks/${id}`, {
      method: 'PUT',
      body: JSON.stringify(task),
    });
  }

  async deleteTask(id: number): Promise<void> {
    return this.makeRequest<void>(`/tasks/${id}`, {
      method: 'DELETE',
    });
  }

  // Maintenance Record API methods
  async getMaintenanceRecords(): Promise<MaintenanceRecord[]> {
    return this.makeRequest<MaintenanceRecord[]>('/maintenance');
  }

  async createMaintenanceRecord(
    record: Omit<MaintenanceRecord, 'id' | 'createdAt' | 'updatedAt'>
  ): Promise<MaintenanceRecord> {
    return this.makeRequest<MaintenanceRecord>('/maintenance', {
      method: 'POST',
      body: JSON.stringify(record),
    });
  }

  async updateMaintenanceRecord(
    id: number, 
    record: Partial<MaintenanceRecord>
  ): Promise<MaintenanceRecord> {
    return this.makeRequest<MaintenanceRecord>(`/maintenance/${id}`, {
      method: 'PUT',
      body: JSON.stringify(record),
    });
  }

  async deleteMaintenanceRecord(id: number): Promise<void> {
    return this.makeRequest<void>(`/maintenance/${id}`, {
      method: 'DELETE',
    });
  }

  // Harvest Record API methods
  async getHarvestRecords(): Promise<HarvestRecord[]> {
    return this.makeRequest<HarvestRecord[]>('/harvests');
  }

  async createHarvestRecord(
    record: Omit<HarvestRecord, 'id' | 'createdAt' | 'updatedAt'>
  ): Promise<HarvestRecord> {
    return this.makeRequest<HarvestRecord>('/harvests', {
      method: 'POST',
      body: JSON.stringify(record),
    });
  }

  async updateHarvestRecord(
    id: number, 
    record: Partial<HarvestRecord>
  ): Promise<HarvestRecord> {
    return this.makeRequest<HarvestRecord>(`/harvests/${id}`, {
      method: 'PUT',
      body: JSON.stringify(record),
    });
  }

  async deleteHarvestRecord(id: number): Promise<void> {
    return this.makeRequest<void>(`/harvests/${id}`, {
      method: 'DELETE',
    });
  }

  // Plant History API methods
  async getPlantHistory(plantId: number): Promise<PlantHistory[]> {
    return this.makeRequest<PlantHistory[]>(`/plants/${plantId}/history`);
  }

  async createPlantHistory(
    history: Omit<PlantHistory, 'id' | 'createdAt' | 'updatedAt'>
  ): Promise<PlantHistory> {
    return this.makeRequest<PlantHistory>('/plant-history', {
      method: 'POST',
      body: JSON.stringify(history),
    });
  }

  async updatePlantHistory(
    id: number, 
    history: Partial<PlantHistory>
  ): Promise<PlantHistory> {
    return this.makeRequest<PlantHistory>(`/plant-history/${id}`, {
      method: 'PUT',
      body: JSON.stringify(history),
    });
  }

  // Plant Observations API methods
  async getPlantObservations(): Promise<PlantObservation[]> {
    const obs = this.makeRequest<PlantObservation[]>('/observations');
    console.log(obs);
    return obs;
  }

  async createPlantObservation(
    observation: Omit<PlantObservation, 'id' | 'createdAt' | 'updatedAt'>
  ): Promise<PlantObservation> {
    return this.makeRequest<PlantObservation>('/observations', {
      method: 'POST',
      body: JSON.stringify(observation),
    });
  }

  async updatePlantObservation(
    id: number, 
    observation: Partial<PlantObservation>
  ): Promise<PlantObservation> {
    return this.makeRequest<PlantObservation>(`/observations/${id}`, {
      method: 'PUT',
      body: JSON.stringify(observation),
    });
  }

  async deletePlantObservation(id: number): Promise<void> {
    return this.makeRequest<void>(`/observations/${id}`, {
      method: 'DELETE',
    });
  }

  // Health check
  async healthCheck(): Promise<{ status: string; message: string }> {
    return this.makeRequest<{ status: string; message: string }>('/health');
  }

  // Photo upload
  async uploadPhoto(file: File): Promise<{ photoUrl: string }> {
    const formData = new FormData();
    formData.append('photo', file);

    const url = `${this.baseUrl}/upload-photo`;

    try {
      const response = await fetch(url, {
        method: 'POST',
        body: formData,
      });

      return this.handleResponse<{ photoUrl: string }>(response);
    } catch (error) {
      if (error instanceof TypeError && error.message.includes('fetch')) {
        throw new Error('Unable to connect to the server. Please check if the backend is running.');
      }
      throw error;
    }
  }

  // Utility methods for batch operations
  async getPlantWithDetails(plantId: number): Promise<{
    plant: Plant;
    history: PlantHistory[];
    harvests: HarvestRecord[];
    maintenance: MaintenanceRecord[];
  }> {
    const [plant, history, harvests, maintenance] = await Promise.all([
      this.makeRequest<Plant>(`/plants/${plantId}`),
      this.getPlantHistory(plantId),
      this.makeRequest<HarvestRecord[]>(`/harvests?plantId=${plantId}`),
      this.makeRequest<MaintenanceRecord[]>(`/maintenance?plantId=${plantId}`)
    ]);

    return { plant, history, harvests, maintenance };
  }

  // Search and filter methods
  async searchPlants(query: string): Promise<Plant[]> {
    return this.makeRequest<Plant[]>(`/plants/search?q=${encodeURIComponent(query)}`);
  }

  async getPlantsByType(type: string): Promise<Plant[]> {
    return this.makeRequest<Plant[]>(`/plants?type=${encodeURIComponent(type)}`);
  }

  async getPlantsByHealthStatus(status: string): Promise<Plant[]> {
    return this.makeRequest<Plant[]>(`/plants?healthStatus=${encodeURIComponent(status)}`);
  }

  async getTasksByStatus(completed: boolean): Promise<Task[]> {
    return this.makeRequest<Task[]>(`/tasks?completed=${completed}`);
  }

  async getUpcomingTasks(days: number = 7): Promise<Task[]> {
    const endDate = new Date();
    endDate.setDate(endDate.getDate() + days);
    return this.makeRequest<Task[]>(`/tasks/upcoming?days=${days}`);
  }

  async getOverdueTasks(): Promise<Task[]> {
    return this.makeRequest<Task[]>('/tasks/overdue');
  }

  // Statistics methods
  async getPlantStatistics(plantId: number, year?: number): Promise<any> {
    const yearParam = year ? `?year=${year}` : '';
    return this.makeRequest<any>(`/plants/${plantId}/statistics${yearParam}`);
  }

  async getGardenSummary(): Promise<{
    totalPlants: number;
    healthyPlants: number;
    plantsNeedingAttention: number;
    totalTasks: number;
    completedTasks: number;
    upcomingTasks: number;
    totalHarvests: number;
    recentMaintenanceCount: number;
  }> {
    return this.makeRequest<any>('/dashboard/summary');
  }

  // Fertilizer API methods
  async getFertilizers(): Promise<Fertilizer[]> {
    return this.makeRequest<Fertilizer[]>('/fertilizers');
  }

  async createFertilizer(fertilizer: Omit<Fertilizer, 'id' | 'createdAt' | 'updatedAt'>): Promise<Fertilizer> {
    return this.makeRequest<Fertilizer>('/fertilizers', {
      method: 'POST',
      body: JSON.stringify(fertilizer),
    });
  }

  async updateFertilizer(id: number, fertilizer: Partial<Fertilizer>): Promise<Fertilizer> {
    return this.makeRequest<Fertilizer>(`/fertilizers/${id}`, {
      method: 'PUT',
      body: JSON.stringify(fertilizer),
    });
  }

  async deleteFertilizer(id: number): Promise<void> {
    return this.makeRequest<void>(`/fertilizers/${id}`, {
      method: 'DELETE',
    });
  }

  // Chemical API methods
  async getChemicals(): Promise<Chemical[]> {
    return this.makeRequest<Chemical[]>('/chemicals');
  }

  async createChemical(chemical: Omit<Chemical, 'id' | 'createdAt' | 'updatedAt'>): Promise<Chemical> {
    return this.makeRequest<Chemical>('/chemicals', {
      method: 'POST',
      body: JSON.stringify(chemical),
    });
  }

  async updateChemical(id: number, chemical: Partial<Chemical>): Promise<Chemical> {
    return this.makeRequest<Chemical>(`/chemicals/${id}`, {
      method: 'PUT',
      body: JSON.stringify(chemical),
    });
  }

  async deleteChemical(id: number): Promise<void> {
    return this.makeRequest<void>(`/chemicals/${id}`, {
      method: 'DELETE',
    });
  }

  // Harvest Processing API methods
  async getHarvestProcessing(): Promise<any[]> {
    return this.makeRequest<any[]>('/harvest-processing');
  }

  async createHarvestProcessing(processing: any): Promise<any> {
    return this.makeRequest<any>('/harvest-processing', {
      method: 'POST',
      body: JSON.stringify(processing),
    });
  }

  // Harvest Stock API methods
  async getHarvestStock(): Promise<any[]> {
    return this.makeRequest<any[]>('/harvest-stock');
  }

  async updateHarvestStock(id: number, stock: any): Promise<any> {
    return this.makeRequest<any>(`/harvest-stock/${id}`, {
      method: 'PUT',
      body: JSON.stringify(stock),
    });
  }

}

// Create and export a singleton instance
export const apiService = new ApiService();

// Export the class for testing purposes
export { ApiService };