bookwiz.io / lib / services / template-service.ts
template-service.ts
Raw
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { BookTemplate, TemplateStructure, TemplateFile, TemplateFolder } from '@/lib/types/database'

export class TemplateService {
  private supabase = createClientComponentClient()

  async getAvailableTemplates(): Promise<BookTemplate[]> {
    const { data, error } = await this.supabase
      .from('book_templates')
      .select('*')
      .eq('is_system', true)
      .order('is_default', { ascending: false })
      .order('created_at', { ascending: true })

    if (error) {
      console.error('Error fetching templates:', error)
      throw new Error('Failed to fetch templates')
    }

    return data || []
  }

  async getTemplateById(id: string): Promise<BookTemplate | null> {
    const { data, error } = await this.supabase
      .from('book_templates')
      .select('*')
      .eq('id', id)
      .single()

    if (error) {
      console.error('Error fetching template:', error)
      return null
    }

    return data
  }

  async getDefaultTemplate(): Promise<BookTemplate | null> {
    const { data, error } = await this.supabase
      .from('book_templates')
      .select('*')
      .eq('is_default', true)
      .eq('is_system', true)
      .single()

    if (error) {
      console.error('Error fetching default template:', error)
      return null
    }

    return data
  }

  async createBookFromTemplate(supabase: any, bookId: string, templateId?: string): Promise<void> {
    try {
      let template: BookTemplate | null = null

      if (templateId) {
        // Use the server supabase instance for template lookup
        const { data, error } = await supabase
          .from('book_templates')
          .select('*')
          .eq('id', templateId)
          .single()

        if (!error && data) {
          template = data
        }
      }

      if (!template) {
        // Get default template using server supabase
        const { data, error } = await supabase
          .from('book_templates')
          .select('*')
          .eq('is_default', true)
          .eq('is_system', true)
          .single()

        if (!error && data) {
          template = data
        }
      }

      if (!template) {
        throw new Error('No template found')
      }

      await this.applyTemplateStructure(supabase, bookId, template.structure)
    } catch (error) {
      console.error('Error creating book from template:', error)
      throw error
    }
  }

  private async applyTemplateStructure(supabase: any, bookId: string, structure: TemplateStructure): Promise<void> {
    // Create root level files first
    const rootFiles = structure.files.map(file => ({
      book_id: bookId,
      name: file.name,
      type: file.type,
      content: file.content,
      file_extension: file.file_extension,
      mime_type: file.mime_type,
      sort_order: file.sort_order,
      parent_id: null
    }))

    // Create root level folders
    const rootFolders = structure.folders.map(folder => ({
      book_id: bookId,
      name: folder.name,
      type: folder.type,
      expanded: folder.expanded,
      sort_order: folder.sort_order,
      parent_id: null
    }))

    // Insert root items
    const rootItems = [...rootFiles, ...rootFolders]
    const { data: createdRootItems, error: rootError } = await supabase
      .from('file_system_items')
      .insert(rootItems)
      .select()

    if (rootError) {
      console.error('Error creating root items:', rootError)
      throw new Error('Failed to create root structure')
    }

    // Create nested items for folders with children
    for (const folder of structure.folders) {
      if (folder.children && folder.children.length > 0) {
        const createdFolder = createdRootItems.find((item: any) => item.name === folder.name && item.type === 'folder')
        if (createdFolder) {
          await this.createFolderChildren(supabase, bookId, createdFolder.id, folder.children)
        }
      }
    }
  }

  private async createFolderChildren(supabase: any, bookId: string, parentId: string, children: (TemplateFile | TemplateFolder)[]): Promise<void> {
    const childItems = children.map(child => ({
      book_id: bookId,
      parent_id: parentId,
      name: child.name,
      type: child.type,
      sort_order: child.sort_order,
      ...(child.type === 'file' && {
        content: (child as TemplateFile).content,
        file_extension: (child as TemplateFile).file_extension,
        mime_type: (child as TemplateFile).mime_type
      }),
      ...(child.type === 'folder' && {
        expanded: (child as TemplateFolder).expanded
      })
    }))

    const { data: createdItems, error } = await supabase
      .from('file_system_items')
      .insert(childItems)
      .select()

    if (error) {
      console.error('Error creating child items:', error)
      throw new Error('Failed to create folder contents')
    }

    // Recursively create nested folder children
    for (const child of children) {
      if (child.type === 'folder' && (child as TemplateFolder).children) {
        const createdFolder = createdItems.find((item: any) => item.name === child.name && item.type === 'folder')
        if (createdFolder) {
          await this.createFolderChildren(supabase, bookId, createdFolder.id, (child as TemplateFolder).children!)
        }
      }
    }
  }
}

export const templateService = new TemplateService()