// Capacitor Bridge for Plugin Compass Mobile App
// Connects to backend at plugincompass.com

const BACKEND_BASE_URL = window.BACKEND_BASE_URL || 'https://plugincompass.com';

// Storage keys
const STORAGE_KEYS = {
  USER: 'plugin_compass_user',
  TOKEN: 'plugin_compass_token',
  REFRESH_TOKEN: 'plugin_compass_refresh_token',
  SESSION: 'plugin_compass_session'
};

let PreferencesImpl = null;

async function getPreferences() {
  if (PreferencesImpl) return PreferencesImpl;
  
  try {
    const module = await import('@capacitor/preferences');
    PreferencesImpl = module.Preferences;
    return PreferencesImpl;
  } catch {
    // Fallback to localStorage
    PreferencesImpl = {
      async get({ key }) {
        return { value: localStorage.getItem(key) };
      },
      async set({ key, value }) {
        localStorage.setItem(key, value);
        return;
      },
      async remove({ key }) {
        localStorage.removeItem(key);
        return;
      },
      async keys() {
        return { keys: Object.keys(localStorage) };
      },
      async clear() {
        localStorage.clear();
        return;
      }
    };
    return PreferencesImpl;
  }
}

export const Preferences = {
  async get(options) {
    const pref = await getPreferences();
    return pref.get(options);
  },
  async set(options) {
    const pref = await getPreferences();
    return pref.set(options);
  },
  async remove(options) {
    const pref = await getPreferences();
    return pref.remove(options);
  },
  async keys() {
    const pref = await getPreferences();
    return pref.keys();
  },
  async clear() {
    const pref = await getPreferences();
    return pref.clear();
  }
};

// Token management
async function getAuthToken() {
  try {
    const { value } = await Preferences.get({ key: STORAGE_KEYS.TOKEN });
    return value;
  } catch (e) {
    console.error('[AUTH] Failed to get token:', e);
    return null;
  }
}

async function setAuthToken(token) {
  try {
    await Preferences.set({ key: STORAGE_KEYS.TOKEN, value: token });
  } catch (e) {
    console.error('[AUTH] Failed to set token:', e);
  }
}

async function getRefreshToken() {
  try {
    const { value } = await Preferences.get({ key: STORAGE_KEYS.REFRESH_TOKEN });
    return value;
  } catch (e) {
    return null;
  }
}

async function setRefreshToken(token) {
  try {
    await Preferences.set({ key: STORAGE_KEYS.REFRESH_TOKEN, value: token });
  } catch (e) {
    console.error('[AUTH] Failed to set refresh token:', e);
  }
}

async function clearAuth() {
  try {
    await Preferences.remove({ key: STORAGE_KEYS.TOKEN });
    await Preferences.remove({ key: STORAGE_KEYS.REFRESH_TOKEN });
    await Preferences.remove({ key: STORAGE_KEYS.USER });
    await Preferences.remove({ key: STORAGE_KEYS.SESSION });
  } catch (e) {
    console.error('[AUTH] Failed to clear auth:', e);
  }
}

// API client with authentication and timeout
const REQUEST_TIMEOUT = 10000; // 10 second timeout

function fetchWithTimeout(url, options, timeout = REQUEST_TIMEOUT) {
  return Promise.race([
    fetch(url, options),
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error(`Request timeout after ${timeout}ms`)), timeout)
    )
  ]);
}

async function apiClient(endpoint, options = {}) {
  const url = endpoint.startsWith('http') ? endpoint : `${BACKEND_BASE_URL}${endpoint}`;
  const requestId = Math.random().toString(36).substring(7);
  
  console.log(`[API:${requestId}] Starting request to ${endpoint}`);
  console.log(`[API:${requestId}] Full URL: ${url}`);
  
  const token = await getAuthToken();
  const headers = {
    'Content-Type': 'application/json',
    ...(token ? { 'Authorization': `Bearer ${token}` } : {}),
    ...(options.headers || {})
  };

  try {
    console.log(`[API:${requestId}] Sending ${options.method || 'GET'} request...`);
    const startTime = Date.now();
    
    const response = await fetchWithTimeout(url, {
      ...options,
      headers,
      credentials: 'include'
    });
    
    const duration = Date.now() - startTime;
    console.log(`[API:${requestId}] Response received in ${duration}ms - Status: ${response.status}`);

    // Handle token expiration
    if (response.status === 401) {
      console.log(`[API:${requestId}] Token expired, attempting refresh...`);
      const refreshed = await refreshAccessToken();
      if (refreshed) {
        console.log(`[API:${requestId}] Token refreshed, retrying request...`);
        // Retry with new token
        const newToken = await getAuthToken();
        headers['Authorization'] = `Bearer ${newToken}`;
        const retryResponse = await fetchWithTimeout(url, {
          ...options,
          headers,
          credentials: 'include'
        });
        return handleResponse(retryResponse);
      } else {
        // Token refresh failed, clear auth
        console.error(`[API:${requestId}] Token refresh failed`);
        await clearAuth();
        throw new Error('Session expired. Please sign in again.');
      }
    }

    return handleResponse(response);
  } catch (error) {
    console.error(`[API:${requestId}] Request failed: ${endpoint}`, error);
    console.error(`[API:${requestId}] Error details:`, {
      message: error.message,
      name: error.name,
      stack: error.stack
    });
    throw error;
  }
}

async function handleResponse(response) {
  const text = await response.text();
  let json;
  try {
    json = text ? JSON.parse(text) : {};
  } catch (parseErr) {
    throw new Error(`Invalid JSON response: ${parseErr.message}`);
  }
  
  if (!response.ok) {
    const err = new Error(json.error || json.message || `HTTP ${response.status}`);
    err.status = response.status;
    err.data = json;
    throw err;
  }
  
  return json;
}

async function refreshAccessToken() {
  try {
    const refreshToken = await getRefreshToken();
    if (!refreshToken) return false;

    const response = await fetch(`${BACKEND_BASE_URL}/api/auth/refresh`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ refreshToken })
    });

    if (!response.ok) {
      return false;
    }

    const data = await response.json();
    if (data.token) {
      await setAuthToken(data.token);
      if (data.refreshToken) {
        await setRefreshToken(data.refreshToken);
      }
      return true;
    }
    return false;
  } catch (e) {
    console.error('[AUTH] Token refresh failed:', e);
    return false;
  }
}

// Authentication functions
export async function loginWithEmail(email, password, remember = false) {
  try {
    const response = await apiClient('/api/login', {
      method: 'POST',
      body: JSON.stringify({ email, password, remember })
    });

    if (response.ok && response.user && response.token) {
      // Store tokens
      await setAuthToken(response.token);
      if (response.refreshToken) {
        await setRefreshToken(response.refreshToken);
      }
      
      // Store user info
      await Preferences.set({ 
        key: STORAGE_KEYS.USER, 
        value: JSON.stringify(response.user) 
      });
      
      return { success: true, user: response.user };
    } else {
      return { success: false, error: response.error || 'Login failed' };
    }
  } catch (error) {
    console.error('[AUTH] Login error:', error);
    return { success: false, error: error.message || 'Login failed' };
  }
}

export async function signupWithEmail(email, password) {
  try {
    const response = await apiClient('/api/signup', {
      method: 'POST',
      body: JSON.stringify({ email, password })
    });

    if (response.ok && response.user && response.token) {
      await setAuthToken(response.token);
      if (response.refreshToken) {
        await setRefreshToken(response.refreshToken);
      }
      
      await Preferences.set({ 
        key: STORAGE_KEYS.USER, 
        value: JSON.stringify(response.user) 
      });
      
      return { success: true, user: response.user };
    } else {
      return { success: false, error: response.error || 'Signup failed' };
    }
  } catch (error) {
    console.error('[AUTH] Signup error:', error);
    return { success: false, error: error.message || 'Signup failed' };
  }
}

export async function logout() {
  try {
    // Call logout endpoint if available
    await apiClient('/api/logout', { 
      method: 'POST',
      headers: {}
    }).catch(() => {});
  } finally {
    await clearAuth();
  }
}

export async function getCurrentUser() {
  console.log('[AUTH] Getting current user...');
  try {
    // First check stored user
    console.log('[AUTH] Checking stored user...');
    const { value } = await Preferences.get({ key: STORAGE_KEYS.USER });
    if (value) {
      const user = JSON.parse(value);
      console.log('[AUTH] Found stored user:', user.email || user.id);
      
      // Verify token is still valid by fetching fresh user data
      try {
        console.log('[AUTH] Fetching fresh user data from /api/me...');
        const freshUser = await apiClient('/api/me');
        if (freshUser) {
          console.log('[AUTH] Fresh user data received:', freshUser.email || freshUser.id);
          await Preferences.set({ 
            key: STORAGE_KEYS.USER, 
            value: JSON.stringify(freshUser) 
          });
          return freshUser;
        }
      } catch (e) {
        console.warn('[AUTH] Could not refresh user data:', e.message);
        console.log('[AUTH] Falling back to cached user data');
      }
      
      return user;
    }
    console.log('[AUTH] No stored user found');
    return null;
  } catch (e) {
    console.error('[AUTH] Failed to get current user:', e);
    console.error('[AUTH] Error details:', {
      message: e.message,
      name: e.name,
      stack: e.stack
    });
    return null;
  }
}

export async function isAuthenticated() {
  console.log('[AUTH] Checking authentication status...');
  const token = await getAuthToken();
  console.log('[AUTH] Token exists:', !!token);
  
  if (!token) {
    console.log('[AUTH] No token found, user is not authenticated');
    return false;
  }
  
  console.log('[AUTH] Token found, fetching current user...');
  const user = await getCurrentUser();
  const isAuth = !!user;
  console.log('[AUTH] Authentication result:', isAuth, user ? `(User: ${user.email || user.id})` : '');
  return isAuth;
}

// OAuth helpers
export function getOAuthUrl(provider, redirectUri = null) {
  const params = new URLSearchParams();
  if (redirectUri) {
    params.set('redirect_uri', redirectUri);
  }
  params.set('mobile', 'true');
  return `${BACKEND_BASE_URL}/auth/${provider}?${params.toString()}`;
}

export async function handleOAuthCallback(provider, code, state) {
  try {
    const response = await apiClient(`/auth/${provider}/callback`, {
      method: 'POST',
      body: JSON.stringify({ code, state })
    });

    if (response.token) {
      await setAuthToken(response.token);
      if (response.refreshToken) {
        await setRefreshToken(response.refreshToken);
      }
      
      if (response.user) {
        await Preferences.set({ 
          key: STORAGE_KEYS.USER, 
          value: JSON.stringify(response.user) 
        });
      }
      
      return { success: true, user: response.user };
    } else {
      return { success: false, error: response.error || 'OAuth failed' };
    }
  } catch (error) {
    console.error('[AUTH] OAuth error:', error);
    return { success: false, error: error.message || 'OAuth failed' };
  }
}

// Plugin/App management
export async function getUserApps() {
  try {
    const apps = await apiClient('/api/apps');
    return { success: true, apps: apps || [] };
  } catch (error) {
    console.error('[APPS] Failed to load apps:', error);
    return { success: false, error: error.message, apps: [] };
  }
}

export async function getApp(appId) {
  try {
    const app = await apiClient(`/api/apps/${appId}`);
    return { success: true, app };
  } catch (error) {
    console.error('[APPS] Failed to load app:', error);
    return { success: false, error: error.message };
  }
}

export async function createApp(appData) {
  try {
    const app = await apiClient('/api/apps', {
      method: 'POST',
      body: JSON.stringify(appData)
    });
    return { success: true, app };
  } catch (error) {
    console.error('[APPS] Failed to create app:', error);
    return { success: false, error: error.message };
  }
}

export async function updateApp(appId, appData) {
  try {
    const app = await apiClient(`/api/apps/${appId}`, {
      method: 'PUT',
      body: JSON.stringify(appData)
    });
    return { success: true, app };
  } catch (error) {
    console.error('[APPS] Failed to update app:', error);
    return { success: false, error: error.message };
  }
}

export async function deleteApp(appId) {
  try {
    await apiClient(`/api/apps/${appId}`, {
      method: 'DELETE'
    });
    return { success: true };
  } catch (error) {
    console.error('[APPS] Failed to delete app:', error);
    return { success: false, error: error.message };
  }
}

export async function syncApp(appId) {
  if (!appId || appId.trim() === '') {
    throw new Error('appId is required');
  }
  
  try {
    // Get app from backend instead of local storage
    const result = await getApp(appId);
    if (!result.success || !result.app) {
      throw new Error(`App not found: ${appId}`);
    }
    
    // Sync with backend
    const response = await apiClient('/desktop/apps/sync', {
      method: 'POST',
      body: JSON.stringify(result.app)
    });
    
    return response;
  } catch (error) {
    console.error('[SYNC] Failed to sync app:', error);
    throw error;
  }
}

export async function runOpencodeTask(appId, taskName, args = []) {
  if (!appId || appId.trim() === '') {
    throw new Error('appId is required');
  }
  if (!taskName || taskName.trim() === '') {
    throw new Error('taskName is required');
  }
  
  throw new Error('OpenCode execution is not supported on mobile devices. Please use the desktop app for this feature.');
}

// Session management
export async function getSessions() {
  try {
    const sessions = await apiClient('/api/sessions');
    return { success: true, sessions: sessions || [] };
  } catch (error) {
    console.error('[SESSIONS] Failed to load sessions:', error);
    return { success: false, error: error.message, sessions: [] };
  }
}

export async function getSession(sessionId) {
  try {
    const session = await apiClient(`/api/sessions/${sessionId}`);
    return { success: true, session };
  } catch (error) {
    console.error('[SESSIONS] Failed to load session:', error);
    return { success: false, error: error.message };
  }
}

export async function createSession(sessionData) {
  try {
    const session = await apiClient('/api/sessions', {
      method: 'POST',
      body: JSON.stringify(sessionData)
    });
    return { success: true, session };
  } catch (error) {
    console.error('[SESSIONS] Failed to create session:', error);
    return { success: false, error: error.message };
  }
}

export async function sendMessage(sessionId, messageData) {
  try {
    const result = await apiClient(`/api/sessions/${sessionId}/messages`, {
      method: 'POST',
      body: JSON.stringify(messageData)
    });
    return { success: true, ...result };
  } catch (error) {
    console.error('[MESSAGES] Failed to send message:', error);
    return { success: false, error: error.message };
  }
}

// User account
export async function getUserAccount() {
  try {
    const account = await apiClient('/api/account');
    return { success: true, account };
  } catch (error) {
    console.error('[ACCOUNT] Failed to load account:', error);
    return { success: false, error: error.message };
  }
}

export async function updateUserAccount(accountData) {
  try {
    const account = await apiClient('/api/account', {
      method: 'PUT',
      body: JSON.stringify(accountData)
    });
    return { success: true, account };
  } catch (error) {
    console.error('[ACCOUNT] Failed to update account:', error);
    return { success: false, error: error.message };
  }
}

export async function getUsageSummary() {
  try {
    const usage = await apiClient('/api/account/usage');
    return { success: true, usage };
  } catch (error) {
    console.error('[USAGE] Failed to load usage:', error);
    return { success: false, error: error.message };
  }
}

// Legacy exports for backward compatibility
window.nativeBridge = {
  Preferences,
  syncApp,
  runOpencodeTask,
  loginWithEmail,
  signupWithEmail,
  logout,
  getCurrentUser,
  isAuthenticated,
  getUserApps,
  getApp,
  createApp,
  updateApp,
  deleteApp,
  getSessions,
  createSession,
  sendMessage,
  getOAuthUrl,
  handleOAuthCallback,
  getUserAccount,
  updateUserAccount,
  getUsageSummary,
  apiClient
};

// Expose all functions globally for the web UI
Object.assign(window, {
  loginWithEmail,
  signupWithEmail,
  logout,
  getCurrentUser,
  isAuthenticated,
  getUserApps,
  getApp,
  createApp,
  updateApp,
  deleteApp,
  getSessions,
  getSession,
  createSession,
  sendMessage,
  getOAuthUrl,
  handleOAuthCallback,
  getUserAccount,
  updateUserAccount,
  getUsageSummary,
  apiClient
});

export {
  loginWithEmail,
  signupWithEmail,
  logout,
  getCurrentUser,
  isAuthenticated,
  getUserApps,
  getApp,
  createApp,
  updateApp,
  deleteApp,
  getSessions,
  getSession,
  createSession,
  sendMessage,
  getOAuthUrl,
  handleOAuthCallback,
  getUserAccount,
  updateUserAccount,
  getUsageSummary,
  apiClient,
  BACKEND_BASE_URL,
  STORAGE_KEYS
};
