import { IdentificationResult, Language } from '../types';
import { resolveImageUri, tryResolveImageUri } from '../utils/imageUri';
import { getConfiguredApiBaseUrl, getConfiguredBackendRootUrl } from '../utils/backendUrl';
import { backendApiClient } from './backend/backendApiClient';
import { BackendDatabaseEntry, isBackendApiError } from './backend/contracts';
import { createIdempotencyKey } from '../utils/idempotency';
import { getMockCatalog, searchMockCatalog } from './backend/mockCatalog';

export interface DatabaseEntry extends IdentificationResult {
  imageUri: string;
  imageStatus?: 'ok' | 'missing' | 'invalid';
  categories: string[];
}

interface SearchOptions {
  category?: string | null;
  limit?: number;
}

export type SemanticSearchStatus = 'success' | 'timeout' | 'provider_error' | 'no_results' | 'insufficient_credits';

export interface SemanticSearchResult {
  status: SemanticSearchStatus;
  results: DatabaseEntry[];
}

const DEFAULT_SEARCH_LIMIT = 500;

const hasConfiguredPlantBackend = (): boolean => Boolean(getConfiguredBackendRootUrl());

const normalizeImageStatus = (status?: string, imageUri?: string): 'ok' | 'missing' | 'invalid' => {
  if (status === 'ok' || status === 'missing' || status === 'invalid') return status;
  const resolved = tryResolveImageUri(imageUri || '');
  if (resolved) return 'ok';
  return imageUri && imageUri.trim() ? 'invalid' : 'missing';
};

const mapBackendEntry = (entry: Partial<BackendDatabaseEntry> & { imageUri?: string | null }): DatabaseEntry => {
  const imageStatus = normalizeImageStatus(entry.imageStatus, entry.imageUri || undefined);
  const strictImageUri = tryResolveImageUri(entry.imageUri || undefined);
  const imageUri = imageStatus === 'ok'
    ? (strictImageUri || resolveImageUri(entry.imageUri))
    : (typeof entry.imageUri === 'string' ? entry.imageUri.trim() : '');

  return {
    name: entry.name || '',
    botanicalName: entry.botanicalName || '',
    confidence: typeof entry.confidence === 'number' ? entry.confidence : 0,
    description: entry.description || '',
    careInfo: entry.careInfo || { waterIntervalDays: 7, light: 'Unknown', temp: 'Unknown' },
    imageUri,
    imageStatus,
    categories: Array.isArray(entry.categories) ? entry.categories : [],
  };
};

export const PlantDatabaseService = {
  async getAllPlants(lang: Language): Promise<DatabaseEntry[]> {
    if (!hasConfiguredPlantBackend()) {
      return getMockCatalog(lang).map(mapBackendEntry);
    }

    try {
      const response = await fetch(`${getConfiguredApiBaseUrl()}/plants?lang=${lang}`);
      if (!response.ok) throw new Error('Network response was not ok');
      const data = await response.json();
      if (!Array.isArray(data)) return [];
      return data.map(mapBackendEntry);
    } catch (e) {
      console.error('Failed to fetch plants', e);
      return [];
    }
  },

  async searchPlants(query: string, lang: Language, options: SearchOptions = {}): Promise<DatabaseEntry[]> {
    const { category, limit = DEFAULT_SEARCH_LIMIT } = options;

    if (!hasConfiguredPlantBackend()) {
      let results = searchMockCatalog(query || '', lang, limit);
      if (category) {
        results = results.filter(r => r.categories.includes(category));
      }
      return results.map(mapBackendEntry);
    }

    const url = new URL(`${getConfiguredApiBaseUrl()}/plants`);
    url.searchParams.append('lang', lang);
    if (query) url.searchParams.append('q', query);
    if (category) url.searchParams.append('category', category);
    if (limit) url.searchParams.append('limit', limit.toString());

    try {
      const response = await fetch(url.toString());
      if (!response.ok) throw new Error('Network response was not ok');
      const data = await response.json();
      if (!Array.isArray(data)) return [];
      return data.map(mapBackendEntry);
    } catch (e) {
      console.error('Failed to search plants', e);
      return [];
    }
  },

  async semanticSearchDetailed(query: string, lang: Language): Promise<SemanticSearchResult> {
    const idempotencyKey = createIdempotencyKey(`semantic-${query}-${lang}`);
    try {
      const response = await backendApiClient.semanticSearch({
        query,
        language: lang,
        idempotencyKey,
      });

      const results: DatabaseEntry[] = (response.results as BackendDatabaseEntry[]).map(mapBackendEntry);
      return { status: results.length > 0 ? 'success' : 'no_results', results };
    } catch (error) {
      if (isBackendApiError(error)) {
        if (error.code === 'INSUFFICIENT_CREDITS') {
          return { status: 'insufficient_credits', results: [] };
        }
        return { status: 'provider_error', results: [] };
      }
      return { status: 'timeout', results: [] };
    }
  },
};
