/**
 * Enhanced logo management system with local caching and logoapi integration
 */

// IndexedDB setup for logo caching
const DB_NAME = 'LogoCache';
const DB_VERSION = 1;
const STORE_NAME = 'logos';
const CACHE_DURATION = 7 * 24 * 60 * 60 * 1000; // 7 days

interface CachedLogo {
  id: string;
  url: string;
  blob?: Blob;
  timestamp: number;
  source: 'logoapi' | 'facr' | 'upload';
  lastUsed: number;
}

let dbPromise: Promise<IDBDatabase> | null = null;

const initDB = (): Promise<IDBDatabase> => {
  if (dbPromise) return dbPromise;
  
  dbPromise = new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION);
    
    request.onerror = () => reject(request.error);
    request.onsuccess = () => resolve(request.result);
    
    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      if (!db.objectStoreNames.contains(STORE_NAME)) {
        const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' });
        store.createIndex('lastUsed', 'lastUsed', { unique: false });
        store.createIndex('source', 'source', { unique: false });
      }
    };
  });
  
  return dbPromise;
};

/**
 * Get logo from cache
 */
const getCachedLogo = async (id: string): Promise<CachedLogo | null> => {
  try {
    const db = await initDB();
    const tx = db.transaction(STORE_NAME, 'readonly');
    const store = tx.objectStore(STORE_NAME);
    
    return new Promise((resolve) => {
      const request = store.get(id);
      request.onsuccess = () => {
        const logo = request.result as CachedLogo | undefined;
        if (!logo) {
          resolve(null);
          return;
        }
        
        // Check if cache is still valid
        const now = Date.now();
        if (now - logo.timestamp > CACHE_DURATION) {
          resolve(null);
          return;
        }
        
        resolve(logo);
      };
      request.onerror = () => resolve(null);
    });
  } catch {
    return null;
  }
};

/**
 * Save logo to cache
 */
const saveCachedLogo = async (logo: CachedLogo): Promise<void> => {
  try {
    const db = await initDB();
    const tx = db.transaction(STORE_NAME, 'readwrite');
    const store = tx.objectStore(STORE_NAME);
    store.put(logo);
    await new Promise<void>((resolve, reject) => {
      tx.oncomplete = () => resolve();
      tx.onerror = () => reject(tx.error);
    });
  } catch (e) {
    console.warn('Failed to cache logo:', e);
  }
};

/**
 * Update last used timestamp
 */
const updateLastUsed = async (id: string): Promise<void> => {
  try {
    const cached = await getCachedLogo(id);
    if (cached) {
      cached.lastUsed = Date.now();
      await saveCachedLogo(cached);
    }
  } catch {}
};

/**
 * Clean up unused logos from cache
 */
export const cleanupUnusedLogos = async (): Promise<void> => {
  try {
    const db = await initDB();
    const tx = db.transaction(STORE_NAME, 'readwrite');
    const store = tx.objectStore(STORE_NAME);
    const index = store.index('lastUsed');
    
    const now = Date.now();
    const threshold = now - (30 * 24 * 60 * 60 * 1000); // 30 days
    
    const request = index.openCursor();
    request.onsuccess = (event) => {
      const cursor = (event.target as IDBRequest).result;
      if (cursor) {
        const logo = cursor.value as CachedLogo;
        if (logo.lastUsed < threshold) {
          cursor.delete();
        }
        cursor.continue();
      }
    };
  } catch (e) {
    console.warn('Failed to cleanup logos:', e);
  }
};

/**
 * Optimize SVG by removing whitespace and fixing viewBox
 * This aggressively removes padding/empty space around logos
 */
const optimizeSVG = async (svgUrl: string): Promise<string> => {
  try {
    const response = await fetch(svgUrl);
    if (!response.ok) return svgUrl;
    
    let svgText = await response.text();
    
    // Parse SVG to manipulate it
    const parser = new DOMParser();
    const doc = parser.parseFromString(svgText, 'image/svg+xml');
    const svg = doc.documentElement as unknown as SVGSVGElement;
    
    // Remove XML declarations and comments
    svgText = svgText.replace(/<\?xml[^?]*\?>/g, '');
    svgText = svgText.replace(/<!--[\s\S]*?-->/g, '');
    
    // Create a temporary SVG in the DOM to get proper bounding box
    if (typeof document !== 'undefined') {
      const tempSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      tempSvg.innerHTML = svg.innerHTML;
      tempSvg.style.position = 'absolute';
      tempSvg.style.visibility = 'hidden';
      tempSvg.style.width = '1000px';
      tempSvg.style.height = '1000px';
      document.body.appendChild(tempSvg);
      
      try {
        // Get bounding box of all content
        const bbox = tempSvg.getBBox();
        if (bbox && bbox.width > 0 && bbox.height > 0) {
          // Add minimal padding (2% of size) for visual comfort
          const padding = Math.max(bbox.width, bbox.height) * 0.02;
          const x = bbox.x - padding;
          const y = bbox.y - padding;
          const width = bbox.width + (padding * 2);
          const height = bbox.height + (padding * 2);
          
          // Set viewBox to the actual content bounds (removes empty space)
          svg.setAttribute('viewBox', `${x} ${y} ${width} ${height}`);
          svg.removeAttribute('width');
          svg.removeAttribute('height');
          
          // Ensure preserveAspectRatio is set correctly
          svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
        }
      } catch (e) {
        // getBBox can fail in some cases, try alternative approach
        console.warn('getBBox failed, using fallback optimization:', e);
        // Fallback: just ensure preserveAspectRatio is correct
        svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
        svg.removeAttribute('width');
        svg.removeAttribute('height');
      } finally {
        document.body.removeChild(tempSvg);
      }
      
      // Serialize back to string
      const serializer = new XMLSerializer();
      svgText = serializer.serializeToString(svg);
    }
    
    // Create a data URL from the optimized SVG
    const blob = new Blob([svgText], { type: 'image/svg+xml' });
    return URL.createObjectURL(blob);
  } catch (e) {
    console.warn('Failed to optimize SVG:', e);
    return svgUrl;
  }
};

/**
 * Fetch logo from logoapi.sportcreative.eu with optimization
 */
export const fetchLogoFromLogoAPI = async (teamId: string, teamName?: string): Promise<string | null> => {
  try {
    // Check cache first
    const cached = await getCachedLogo(teamId);
    if (cached?.url) {
      await updateLastUsed(teamId);
      return cached.url;
    }
    
    // Fetch from logoapi
    const res = await fetch(`https://logoapi.sportcreative.eu/logos/${teamId}/json`, {
      method: 'GET',
      headers: { 'Accept': 'application/json' },
    });
    
    if (!res.ok) return null;
    
    const data = await res.json();
    let url = data.logo_url_svg || data.logo_url_png || data.logo_url;
    
    if (!url) return null;
    
    // Optimize SVG if it's an SVG
    if (url.includes('.svg') || data.logo_url_svg) {
      url = await optimizeSVG(url);
    }
    
    // Cache the logo
    await saveCachedLogo({
      id: teamId,
      url,
      timestamp: Date.now(),
      source: 'logoapi',
      lastUsed: Date.now(),
    });
    
    return url;
  } catch (e) {
    console.warn(`Failed to fetch logo for team ${teamId}:`, e);
    return null;
  }
};

/**
 * Fetches team logos in bulk from logoapi.sportcreative.eu API
 * Note: No batch endpoint is used; this function fetches per team ID concurrently.
 * @param teamIds Array of team IDs to fetch logos for
 * @returns Promise that resolves to a map of teamId -> logo URL
 */
export const batchFetchLogosFromSportLogosAPI = async (teamIds: string[]): Promise<Record<string, string>> => {
  if (!teamIds.length) return {};
  
  try {
    const logos: Record<string, string> = {};
    await Promise.all(
      teamIds.map(async (id) => {
        const url = await fetchLogoFromLogoAPI(id);
        if (url) logos[id] = url;
      })
    );
    return logos;
  } catch (error) {
    console.error('Error in batchFetchLogosFromSportLogosAPI (logoapi.sportcreative.eu):', error);
    return {};
  }
};

/**
 * Get logo for a team by name or ID, with fallback chain:
 * 1. logoapi.sportcreative.eu (cached)
 * 2. FACR logo (if provided)
 * 3. Placeholder
 */
export const getTeamLogo = async (teamId?: string, teamName?: string, facrLogo?: string): Promise<string> => {
  const PLACEHOLDER = '/logo192.png';
  
  // Try logoapi first if we have an ID
  if (teamId) {
    const logoApiUrl = await fetchLogoFromLogoAPI(teamId, teamName);
    if (logoApiUrl) return logoApiUrl;
  }
  
  // Fallback to FACR logo
  if (facrLogo) return facrLogo;
  
  // Return placeholder
  return PLACEHOLDER;
};
