/**
 * project-store.js
 * Project configuration store
 * Manages project list, current project selection, and project metadata
 * MVP3: Integrates with API backend while maintaining localStorage fallback
 */

import apiClient from '../services/api-client.js';

export class ProjectStore {
  constructor() {
    // Load projects from localStorage (fallback for MVP2)
    const stored = localStorage.getItem('projects_list');
    this.projects = stored ? JSON.parse(stored) : this.getDefaultProjects();

    // Load current project selection
    this.currentProjectId = localStorage.getItem('current_project_id') || (this.projects.length > 0 ? this.projects[0].id : null);

    this.listeners = new Set();
    this.isLoading = false;
    this.hasLoadedFromAPI = false;

    // Try to load from API on initialization
    this.syncWithAPI();
  }

  async syncWithAPI() {
    try {
      const projects = await apiClient.getProjects();
      this.projects = projects;
      this.hasLoadedFromAPI = true;
      this.persist();
      this.notifyListeners();
    } catch (error) {
      console.warn('[ProjectStore] Failed to sync with API, using localStorage:', error);
      // Continue using localStorage data
    }
  }

  getDefaultProjects() {
    return [
      {
        id: 'DEFAULT-DESIGN-SYSTEM',
        name: 'Default Design System',
        skinSelected: 'default',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString()
      }
    ];
  }

  /**
   * Get all projects
   * @returns {Array} Projects array
   */
  getProjects() {
    return [...this.projects];
  }

  /**
   * Get current project
   * @returns {Object|null} Current project or null
   */
  getCurrentProject() {
    return this.projects.find(p => p.id === this.currentProjectId) || null;
  }

  /**
   * Get project by ID
   * @param {string} id - Project ID
   * @returns {Object|null} Project or null
   */
  getProject(id) {
    return this.projects.find(p => p.id === id) || null;
  }

  /**
   * Create new project
   * @param {Object} projectData - {name, key, description, figmaFileKey, jiraProjectKey, storybookUrl}
   * @returns {Object} Created project
   */
  async createProject(projectData) {
    try {
      // Try API first if authenticated
      if (apiClient.accessToken) {
        const project = await apiClient.createProject(projectData);
        this.projects.push(project);
        this.persist();
        this.notifyListeners();
        return project;
      }
    } catch (error) {
      console.warn('[ProjectStore] API creation failed, using localStorage:', error);
    }

    // Fallback to localStorage
    const now = new Date().toISOString();
    const project = {
      id: projectData.id || `PROJECT-${Date.now()}`,
      name: projectData.name || 'Untitled Project',
      key: projectData.key || `KEY-${Date.now()}`,
      description: projectData.description || '',
      createdAt: now,
      updatedAt: now,
      ...projectData
    };

    this.projects.push(project);
    this.persist();
    this.notifyListeners();
    return project;
  }

  /**
   * Update project
   * @param {string} id - Project ID
   * @param {Object} updates - Partial project updates
   * @returns {Object|null} Updated project or null
   */
  async updateProject(id, updates) {
    const project = this.projects.find(p => p.id === id);
    if (!project) return null;

    try {
      // Try API first if authenticated
      if (apiClient.accessToken) {
        const updated = await apiClient.updateProject(id, updates);
        const index = this.projects.findIndex(p => p.id === id);
        if (index !== -1) {
          this.projects[index] = updated;
        }
        this.persist();
        this.notifyListeners();
        return updated;
      }
    } catch (error) {
      console.warn('[ProjectStore] API update failed, using localStorage:', error);
    }

    // Fallback to localStorage
    Object.assign(project, updates, {
      updatedAt: new Date().toISOString()
    });

    this.persist();
    this.notifyListeners();
    return project;
  }

  /**
   * Delete project
   * @param {string} id - Project ID
   * @returns {boolean} Success
   */
  async deleteProject(id) {
    try {
      // Try API first if authenticated
      if (apiClient.accessToken) {
        await apiClient.deleteProject(id);
      }
    } catch (error) {
      console.warn('[ProjectStore] API deletion failed, using localStorage:', error);
    }

    const index = this.projects.findIndex(p => p.id === id);
    if (index === -1) return false;

    this.projects.splice(index, 1);

    // If deleted project was selected, select first available
    if (this.currentProjectId === id) {
      this.currentProjectId = this.projects.length > 0 ? this.projects[0].id : null;
      localStorage.setItem('current_project_id', this.currentProjectId || '');
    }

    this.persist();
    this.notifyListeners();
    return true;
  }

  /**
   * Select/switch to different project
   * @param {string} id - Project ID
   * @returns {Object|null} Selected project or null
   */
  selectProject(id) {
    const project = this.projects.find(p => p.id === id);
    if (!project) return null;

    this.currentProjectId = id;
    localStorage.setItem('current_project_id', id);
    this.notifyListeners();
    return project;
  }

  /**
   * Update selected skin for current project
   * @param {string} skin - Skin name
   * @returns {Object|null} Updated project
   */
  setSkinForCurrentProject(skin) {
    if (!this.currentProjectId) return null;
    return this.updateProject(this.currentProjectId, { skinSelected: skin });
  }

  /**
   * Persist to localStorage
   */
  persist() {
    localStorage.setItem('projects_list', JSON.stringify(this.projects));
  }

  /**
   * Subscribe to changes
   * @param {Function} callback - Called on state changes
   * @returns {Function} Unsubscribe function
   */
  subscribe(callback) {
    this.listeners.add(callback);
    return () => this.listeners.delete(callback);
  }

  notifyListeners() {
    this.listeners.forEach(listener => listener({
      projects: this.getProjects(),
      currentProject: this.getCurrentProject()
    }));
  }

  /**
   * Reset to default project
   */
  reset() {
    localStorage.removeItem('projects_list');
    localStorage.removeItem('current_project_id');
    this.projects = this.getDefaultProjects();
    this.currentProjectId = this.projects[0].id;
    this.notifyListeners();
  }
}

// Singleton instance
let projectStoreInstance = null;

export function useProjectStore() {
  if (!projectStoreInstance) {
    projectStoreInstance = new ProjectStore();
  }
  return projectStoreInstance;
}
