import prisma from './prisma';

/**
 * Collection of utility functions for working with organizations
 */
export const OrganizationUtils = {
  /**
   * Create a new organization
   * 
   * @param {Object} data Organization data
   * @returns {Promise<Object>} Created organization
   */
  async create(data) {
    if (!data.org_name) {
      throw new Error('Organization name is required');
    }
    
    // Check if organization already exists
    const existingOrg = await prisma.organization.findUnique({
      where: {
        org_name: data.org_name
      }
    });
    
    if (existingOrg) {
      throw new Error('Organization with this name already exists');
    }
    
    return prisma.organization.create({
      data: {
        org_name: data.org_name,
        org_address1: data.org_address1 || null,
        org_address2: data.org_address2 || null,
        org_postcode: data.org_postcode ? parseInt(data.org_postcode) : null,
        org_state: data.org_state || null,
        org_country: data.org_country || null,
        org_active: data.org_active !== undefined ? parseInt(data.org_active) : 1
      }
    });
  },
  
  /**
   * Get all organizations with pagination
   * 
   * @param {Object} options Query options
   * @param {number} options.page Page number
   * @param {number} options.limit Items per page
   * @param {string} options.search Search term
   * @returns {Promise<Object>} Organizations and pagination metadata
   */
  async getAll({ page = 1, limit = 10, search = '' }) {
    const skip = (page - 1) * limit;
    
    // Define filters
    const filters = {
      where: {}
    };
    
    // Add search filter if provided
    if (search) {
      filters.where = {
        OR: [
          { org_name: { contains: search } },
          { org_address1: { contains: search } },
          { org_state: { contains: search } },
          { org_country: { contains: search } }
        ]
      };
    }
    
    // Get organizations with pagination
    const [organizations, total] = await Promise.all([
      prisma.organization.findMany({
        ...filters,
        skip,
        take: limit,
        orderBy: {
          org_name: 'asc'
        },
        include: {
          _count: {
            select: {
              departments: true
            }
          }
        }
      }),
      prisma.organization.count(filters)
    ]);
    
    // Calculate pagination metadata
    const totalPages = Math.ceil(total / limit);
    
    return {
      organizations,
      pagination: {
        page,
        limit,
        total,
        totalPages,
        hasNextPage: page < totalPages,
        hasPrevPage: page > 1
      }
    };
  },
  
  /**
   * Get organization by ID
   * 
   * @param {number} id Organization ID
   * @returns {Promise<Object|null>} Organization or null if not found
   */
  async getById(id) {
    if (isNaN(parseInt(id))) {
      throw new Error('Invalid organization ID');
    }
    
    return prisma.organization.findUnique({
      where: {
        org_id: parseInt(id)
      },
      include: {
        departments: {
          select: {
            dp_id: true,
            dp_name: true,
            _count: {
              select: {
                users: true,
                cabinets: true
              }
            }
          }
        }
      }
    });
  },
  
  /**
   * Update an organization
   * 
   * @param {number} id Organization ID
   * @param {Object} data Organization data
   * @returns {Promise<Object>} Updated organization
   */
  async update(id, data) {
    if (isNaN(parseInt(id))) {
      throw new Error('Invalid organization ID');
    }
    
    if (!data.org_name) {
      throw new Error('Organization name is required');
    }
    
    // Check if organization exists
    const existingOrg = await prisma.organization.findUnique({
      where: {
        org_id: parseInt(id)
      }
    });
    
    if (!existingOrg) {
      throw new Error('Organization not found');
    }
    
    // Check if name is already taken by another organization
    if (data.org_name !== existingOrg.org_name) {
      const nameExists = await prisma.organization.findFirst({
        where: {
          org_name: data.org_name,
          org_id: {
            not: parseInt(id)
          }
        }
      });
      
      if (nameExists) {
        throw new Error('Organization with this name already exists');
      }
    }
    
    return prisma.organization.update({
      where: {
        org_id: parseInt(id)
      },
      data: {
        org_name: data.org_name,
        org_address1: data.org_address1 || null,
        org_address2: data.org_address2 || null,
        org_postcode: data.org_postcode ? parseInt(data.org_postcode) : null,
        org_state: data.org_state || null,
        org_country: data.org_country || null,
        org_active: data.org_active !== undefined ? parseInt(data.org_active) : existingOrg.org_active
      }
    });
  },
  
  /**
   * Delete an organization
   * 
   * @param {number} id Organization ID
   * @returns {Promise<Object>} Deleted organization
   */
  async delete(id) {
    if (isNaN(parseInt(id))) {
      throw new Error('Invalid organization ID');
    }
    
    // Check if organization exists
    const existingOrg = await prisma.organization.findUnique({
      where: {
        org_id: parseInt(id)
      },
      include: {
        departments: {
          select: {
            dp_id: true
          }
        }
      }
    });
    
    if (!existingOrg) {
      throw new Error('Organization not found');
    }
    
    // Check if organization has departments
    if (existingOrg.departments.length > 0) {
      throw new Error('Cannot delete organization with existing departments. Remove all departments first.');
    }
    
    return prisma.organization.delete({
      where: {
        org_id: parseInt(id)
      }
    });
  }
};

export default OrganizationUtils; 