import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

export class CategoriesService {
  // Find all categories (tree structure)
  async findAll() {
    const categories = await prisma.contactCategory.findMany({
      where: {
        isActive: true
      },
      include: {
        parent: true,
        children: true,
        _count: {
          select: {
            contacts: true
          }
        }
      },
      orderBy: {
        name: 'asc'
      }
    })

    return categories
  }

  // Find category by ID
  async findById(id: string) {
    const category = await prisma.contactCategory.findUnique({
      where: { id },
      include: {
        parent: true,
        children: true,
        _count: {
          select: {
            contacts: true
          }
        }
      }
    })

    if (!category) {
      throw new Error('Category not found')
    }

    return category
  }

  // Create category
  async create(data: {
    name: string
    nameAr?: string
    parentId?: string
    description?: string
  }) {
    // Validate parent exists if provided
    if (data.parentId) {
      const parent = await prisma.contactCategory.findUnique({
        where: { id: data.parentId }
      })
      if (!parent) {
        throw new Error('Parent category not found')
      }
    }

    const category = await prisma.contactCategory.create({
      data: {
        name: data.name,
        nameAr: data.nameAr,
        parentId: data.parentId,
        description: data.description
      },
      include: {
        parent: true,
        children: true
      }
    })

    return category
  }

  // Update category
  async update(id: string, data: {
    name?: string
    nameAr?: string
    parentId?: string
    description?: string
    isActive?: boolean
  }) {
    // Check if category exists
    const existing = await prisma.contactCategory.findUnique({
      where: { id }
    })

    if (!existing) {
      throw new Error('Category not found')
    }

    // Validate parent exists if provided and prevent circular reference
    if (data.parentId) {
      if (data.parentId === id) {
        throw new Error('Category cannot be its own parent')
      }

      const parent = await prisma.contactCategory.findUnique({
        where: { id: data.parentId }
      })
      if (!parent) {
        throw new Error('Parent category not found')
      }

      // Check for circular reference
      let currentParent = parent
      while (currentParent.parentId) {
        if (currentParent.parentId === id) {
          throw new Error('Circular reference detected')
        }
        const nextParent = await prisma.contactCategory.findUnique({
          where: { id: currentParent.parentId }
        })
        if (!nextParent) break
        currentParent = nextParent
      }
    }

    const category = await prisma.contactCategory.update({
      where: { id },
      data,
      include: {
        parent: true,
        children: true
      }
    })

    return category
  }

  // Delete category (soft delete)
  async delete(id: string) {
    // Check if category exists
    const existing = await prisma.contactCategory.findUnique({
      where: { id },
      include: {
        children: true,
        _count: {
          select: {
            contacts: true
          }
        }
      }
    })

    if (!existing) {
      throw new Error('Category not found')
    }

    // Check if category has children
    if (existing.children.length > 0) {
      throw new Error('Cannot delete category with subcategories')
    }

    // Check if category is in use
    if (existing._count.contacts > 0) {
      // Soft delete by setting isActive to false
      const category = await prisma.contactCategory.update({
        where: { id },
        data: { isActive: false }
      })
      return category
    }

    // Hard delete if no contacts use it
    await prisma.contactCategory.delete({
      where: { id }
    })

    return { id, deleted: true }
  }

  // Get category tree (hierarchical structure)
  async getTree() {
    const categories = await prisma.contactCategory.findMany({
      where: {
        isActive: true,
        parentId: null // Only root categories
      },
      include: {
        children: {
          include: {
            children: {
              include: {
                children: true
              }
            }
          }
        },
        _count: {
          select: {
            contacts: true
          }
        }
      },
      orderBy: {
        name: 'asc'
      }
    })

    return categories
  }
}

export const categoriesService = new CategoriesService()
