import { create } from 'zustand';
import { Asset, Storyboard, Episode, ModuleType, AssetType, AssetId, StoryboardId, EpisodeId, ProjectData, GeneralCanvas, CanvasMetadata } from '@/types';

interface ProjectState {
  // Project Metadata
  id: string | null;
  name: string;
  description: string;
  type: 'comic' | 'video' | 'canvas' | 'script';
  status: string;
  created_at: string | null;
  updated_at: string | null;
  resolution: string | null;
  ratio: string | null;
  styleId: string | null;
  styleParams: Record<string, any> | null;
  
  // Project-level model overrides (higher priority than system defaults)
  defaultImageModel?: string;
  defaultVideoModel?: string;
  defaultAudioModel?: string;
  defaultLLMModel?: string;

  assets: Asset[];
  storyboards: Storyboard[];
  episodes: Episode[];
  
  /**
   * @deprecated Use canvasMetadata instead. This field is kept for backward compatibility.
   */
  generalCanvases: GeneralCanvas[];
  
  // Unified canvas metadata management
  canvasMetadata: CanvasMetadata[];
  
  activeModule: ModuleType;
  selectedStoryboardId: StoryboardId | null;
  selectedAssetId: AssetId | null;
  selectedCharacterId: AssetId | null; // For character tab selection in RightPanel
  activeEpisodeId: EpisodeId | null;
  
  // UI State
  hasParsedStoryboard: boolean;
  isCreatingShot: boolean;
  creatingAssetType: AssetType | null;

  // Actions
  setProject: (data: ProjectData) => void;
  updateProjectMeta: (updates: Partial<ProjectData>) => void;

  setAssets: (assets: Asset[]) => void;
  addAsset: (asset: Asset) => void;
  addAssets: (assets: Asset[]) => void;
  updateAsset: (id: AssetId, updates: Partial<Asset>) => void;
  deleteAsset: (id: AssetId) => void;
  
  setStoryboards: (storyboards: Storyboard[]) => void;
  addStoryboard: (storyboard: Storyboard) => void;
  updateStoryboard: (id: StoryboardId, updates: Partial<Storyboard>) => void;
  deleteStoryboard: (id: StoryboardId) => void;

  /**
   * @deprecated Use canvasMetadata actions instead
   */
  setGeneralCanvases: (canvases: GeneralCanvas[]) => void;
  /**
   * @deprecated Use addCanvasMetadata instead
   */
  addGeneralCanvas: (canvas: GeneralCanvas) => void;
  /**
   * @deprecated Use updateCanvasMetadata instead
   */
  updateGeneralCanvas: (id: string, updates: Partial<GeneralCanvas>) => void;
  /**
   * @deprecated Use deleteCanvasMetadata instead
   */
  deleteGeneralCanvas: (id: string) => void;
  
  // Canvas Metadata Actions
  setCanvasMetadata: (metadata: CanvasMetadata[]) => void;
  addCanvasMetadata: (metadata: CanvasMetadata) => void;
  updateCanvasMetadata: (id: string, updates: Partial<CanvasMetadata>) => void;
  deleteCanvasMetadata: (id: string) => void;
  
  setEpisodes: (episodes: Episode[]) => void;
  addEpisode: (episode: Episode) => void;
  updateEpisode: (id: EpisodeId, updates: Partial<Episode>) => void;
  deleteEpisode: (id: EpisodeId) => void;
  setActiveEpisodeId: (id: EpisodeId | null) => void;

  setActiveModule: (module: ModuleType) => void;
  setSelectedStoryboardId: (id: StoryboardId | null) => void;
  setSelectedAssetId: (id: AssetId | null) => void;
  setSelectedCharacterId: (id: AssetId | null) => void;
  
  setHasParsedStoryboard: (hasParsed: boolean) => void;
  setIsCreatingShot: (isCreating: boolean) => void;
  setCreatingAssetType: (type: AssetType | null) => void;
}

export const useProjectStore = create<ProjectState>((set, get) => ({
  // Project Metadata
  id: null,
  name: '',
  description: '',
  type: 'canvas',
  status: 'active',
  created_at: null,
  updated_at: null,
  resolution: null,
  ratio: null,
  styleId: null,
  styleParams: null,

  assets: [],
  storyboards: [],
  episodes: [],
  generalCanvases: [],
  canvasMetadata: [],
  activeModule: 'overview',
  selectedStoryboardId: null,
  selectedAssetId: null,
  selectedCharacterId: null,
  activeEpisodeId: null,
  
  hasParsedStoryboard: false,
  isCreatingShot: false,
  creatingAssetType: null,

  setProject: (data) => set((state) => {
    // Merge generalCanvases: prefer backend data, but preserve client-side canvases if backend is empty
    let mergedGeneralCanvases = data.generalCanvases || [];
    
    // If backend has no canvases but we have client-side canvases, keep them
    if ((!data.generalCanvases || data.generalCanvases.length === 0) && state.generalCanvases && state.generalCanvases.length > 0) {
      console.log('[ProjectStore] Preserving client-side generalCanvases:', state.generalCanvases);
      mergedGeneralCanvases = state.generalCanvases;
    }
    
    // Handle canvasMetadata - prefer backend data if available
    let canvasMetadata = state.canvasMetadata;
    if (data.canvasMetadata && Array.isArray(data.canvasMetadata)) {
      canvasMetadata = data.canvasMetadata;
    }
    
    return {
      id: data.id,
      name: data.name,
      description: data.description || '',
      type: data.type as 'comic' | 'video' | 'canvas' | 'script',
      status: data.status,
      created_at: data.created_at,
      updated_at: data.updated_at,
      resolution: data.resolution || null,
      ratio: data.ratio || null,
      styleId: data.styleId || null,
      styleParams: data.styleParams || null,
      defaultImageModel: data.defaultImageModel,
      defaultVideoModel: data.defaultVideoModel,
      defaultAudioModel: data.defaultAudioModel,
      defaultLLMModel: data.defaultLLMModel,
      assets: data.assets || [],
      episodes: data.episodes || [],
      storyboards: data.storyboards || [],
      generalCanvases: mergedGeneralCanvases,
      canvasMetadata: canvasMetadata
    };
  }),
  updateProjectMeta: (updates) => set((state) => ({ ...state, ...updates })),

  setAssets: (assets) => set({ assets }),
  addAsset: (asset) => set((state) => ({ assets: [...state.assets, asset] })),
  addAssets: (newAssets) => set((state) => {
    const existingIds = new Set(state.assets.map(a => a.id));
    const uniqueNewAssets = newAssets.filter(a => !existingIds.has(a.id));
    if (uniqueNewAssets.length === 0) return {}; 
    return { assets: [...state.assets, ...uniqueNewAssets] };
  }),
  updateAsset: (id, updates) => set((state) => ({
    assets: state.assets.map((a) => (a.id === id ? { ...a, ...updates } : a)),
  })),
  deleteAsset: (id) => set((state) => {
    // 1. Remove asset from assets list
    const newAssets = state.assets.filter((a) => a.id !== id);
    
    // 2. Remove references from storyboards
    const newStoryboards = state.storyboards.map((s) => ({
      ...s,
      sceneId: s.sceneId === id ? '' : s.sceneId,
      characterIds: s.characterIds.filter((charId) => charId !== id),
      propIds: s.propIds.filter((propId) => propId !== id),
    }));

    // 3. Handle selection state
    const newSelectedAssetId = state.selectedAssetId === id ? null : state.selectedAssetId;
    const newSelectedCharacterId = state.selectedCharacterId === id ? null : state.selectedCharacterId;

    // 4. Cleanup asset references (Centralized cleanup logic)
    // Remove references from canvas metadata
    const newCanvasMetadata = state.canvasMetadata.filter(
        (c) => !(c.canvasType === 'asset' && c.relatedEntityId === id)
    );

    return {
      assets: newAssets,
      storyboards: newStoryboards,
      canvasMetadata: newCanvasMetadata,
      selectedAssetId: newSelectedAssetId,
      selectedCharacterId: newSelectedCharacterId,
    };
  }),

  setStoryboards: (storyboards) => set({ storyboards }),
  addStoryboard: (storyboard) => set((state) => ({ storyboards: [...state.storyboards, storyboard] })),
  updateStoryboard: (id, updates) => set((state) => ({
    storyboards: state.storyboards.map((s) => (s.id === id ? { ...s, ...updates } : s)),
  })),
  deleteStoryboard: (id) => set((state) => {
    const newStoryboards = state.storyboards.filter((s) => s.id !== id);
    const newSelectedStoryboardId = state.selectedStoryboardId === id ? null : state.selectedStoryboardId;
    
    // Cleanup canvas metadata
    const newCanvasMetadata = state.canvasMetadata.filter(
      (c) => !(c.canvasType === 'storyboard' && c.relatedEntityId === id)
    );

    return {
      storyboards: newStoryboards,
      selectedStoryboardId: newSelectedStoryboardId,
      canvasMetadata: newCanvasMetadata,
    };
  }),

  setGeneralCanvases: (generalCanvases) => set({ generalCanvases }),
  addGeneralCanvas: (canvas) => set((state) => ({ generalCanvases: [...state.generalCanvases, canvas] })),
  updateGeneralCanvas: (id, updates) => set((state) => ({
    generalCanvases: state.generalCanvases.map((c) => (c.id === id ? { ...c, ...updates } : c)),
  })),
  deleteGeneralCanvas: (id) => set((state) => ({
    generalCanvases: state.generalCanvases.filter((c) => c.id !== id),
  })),

  // Canvas Metadata Actions
  setCanvasMetadata: (metadata) => set({ canvasMetadata: metadata }),
  
  addCanvasMetadata: (metadata) => set((state) => ({
    canvasMetadata: [...state.canvasMetadata, metadata]
  })),
  
  updateCanvasMetadata: (id, updates) => set((state) => ({
    canvasMetadata: state.canvasMetadata.map((c) =>
      c.id === id ? { ...c, ...updates, updatedAt: new Date().toISOString() } : c
    )
  })),
  
  deleteCanvasMetadata: (id) => set((state) => ({
    canvasMetadata: state.canvasMetadata.filter((c) => c.id !== id)
  })),

  setEpisodes: (episodes) => set({ episodes }),
  addEpisode: (episode) => set((state) => ({ episodes: [...state.episodes, episode] })),
  updateEpisode: (id, updates) => set((state) => ({
    episodes: state.episodes.map((e) => (e.id === id ? { ...e, ...updates } : e)),
  })),
  deleteEpisode: (id) => set((state) => {
    // 1. Delete the episode
    const newEpisodes = state.episodes.filter((e) => e.id !== id);
    
    // 2. Delete associated storyboards (Cascade delete)
    const deletedStoryboards = state.storyboards.filter((s) => s.episodeId === id);
    const deletedStoryboardIds = new Set(deletedStoryboards.map(s => s.id));
    const newStoryboards = state.storyboards.filter((s) => s.episodeId !== id);
    
    // 3. Handle active episode state
    let newActiveEpisodeId = state.activeEpisodeId;
    if (state.activeEpisodeId === id) {
      newActiveEpisodeId = newEpisodes.length > 0 ? newEpisodes[0].id : null;
    }

    // 4. Cleanup canvas metadata for deleted storyboards
    const newCanvasMetadata = state.canvasMetadata.filter(
      (c) => !(c.canvasType === 'storyboard' && c.relatedEntityId && deletedStoryboardIds.has(c.relatedEntityId))
    );

    return {
      episodes: newEpisodes,
      storyboards: newStoryboards,
      activeEpisodeId: newActiveEpisodeId,
      canvasMetadata: newCanvasMetadata,
    };
  }),
  setActiveEpisodeId: (id) => set({ activeEpisodeId: id }),

  setActiveModule: (module) => set({ activeModule: module }),
  setSelectedStoryboardId: (id) => set({ selectedStoryboardId: id }),
  setSelectedAssetId: (id) => set({ selectedAssetId: id }),
  setSelectedCharacterId: (id) => set({ selectedCharacterId: id }),
  
  setHasParsedStoryboard: (hasParsed) => set({ hasParsedStoryboard: hasParsed }),
  setIsCreatingShot: (isCreating) => set({ isCreatingShot: isCreating }),
  setCreatingAssetType: (type) => set({ creatingAssetType: type }),
}));

// Selectors
export const selectScenes = (state: ProjectState) => state.assets.filter(a => a.type === 'scene');
export const selectCharacters = (state: ProjectState) => state.assets.filter(a => a.type === 'character');
export const selectProps = (state: ProjectState) => state.assets.filter(a => a.type === 'prop');
export const selectStoryboardById = (id: StoryboardId) => (state: ProjectState) => state.storyboards.find(s => s.id === id);
export const selectAssetById = (id: AssetId) => (state: ProjectState) => state.assets.find(a => a.id === id);

// Canvas Metadata Selectors
export const selectGeneralCanvases = (state: ProjectState) => 
  state.canvasMetadata
    .filter((c) => c.canvasType === 'general' && !c.deletedAt)
    .sort((a, b) => a.orderIndex - b.orderIndex);

export const selectAssetCanvas = (assetId: string) => (state: ProjectState) =>
  state.canvasMetadata.find(
    (c) => c.canvasType === 'asset' && c.relatedEntityId === assetId && !c.deletedAt
  );

export const selectStoryboardCanvas = (storyboardId: string) => (state: ProjectState) =>
  state.canvasMetadata.find(
    (c) => c.canvasType === 'storyboard' && c.relatedEntityId === storyboardId && !c.deletedAt
  );
