import { db } from '../config/database.js';
import { companies, projects, todos, notes, companyReminders } from '../db/schema.js';
import { eq, desc, ilike, or, and } from 'drizzle-orm';
import { NotFoundError, ConflictError } from '../utils/errors.js';

/**
 * Get all companies
 * Optionally filter by search term
 */
export const getAllCompanies = async (searchTerm = null) => {
  let query = db.select().from(companies);

  if (searchTerm) {
    query = query.where(
      or(
        ilike(companies.name, `%${searchTerm}%`),
        ilike(companies.email, `%${searchTerm}%`),
        ilike(companies.city, `%${searchTerm}%`)
      )
    );
  }

  const result = await query.orderBy(desc(companies.createdAt));
  return result;
};

/**
 * Get company by ID
 */
export const getCompanyById = async (companyId) => {
  const [company] = await db
    .select()
    .from(companies)
    .where(eq(companies.id, companyId))
    .limit(1);

  if (!company) {
    throw new NotFoundError('Firma nenájdená');
  }

  return company;
};

/**
 * Create new company
 */
export const createCompany = async (userId, data) => {
  const { name, description, address, city, country, phone, email, website } = data;

  // Check if company with same name already exists
  const [existing] = await db
    .select()
    .from(companies)
    .where(eq(companies.name, name))
    .limit(1);

  if (existing) {
    throw new ConflictError('Firma s týmto názvom už existuje');
  }

  const [newCompany] = await db
    .insert(companies)
    .values({
      name,
      description: description || null,
      address: address || null,
      city: city || null,
      country: country || null,
      phone: phone || null,
      email: email || null,
      website: website || null,
      createdBy: userId,
    })
    .returning();

  return newCompany;
};

/**
 * Update company
 */
export const updateCompany = async (companyId, data) => {
  const company = await getCompanyById(companyId);

  const { name, description, address, city, country, phone, email, website, isActive } = data;

  // If name is being changed, check for duplicates
  if (name && name !== company.name) {
    const [existing] = await db
      .select()
      .from(companies)
      .where(and(eq(companies.name, name), eq(companies.id, companyId)))
      .limit(1);

    if (existing && existing.id !== companyId) {
      throw new ConflictError('Firma s týmto názvom už existuje');
    }
  }

  const [updated] = await db
    .update(companies)
    .set({
      name: name !== undefined ? name : company.name,
      description: description !== undefined ? description : company.description,
      address: address !== undefined ? address : company.address,
      city: city !== undefined ? city : company.city,
      country: country !== undefined ? country : company.country,
      phone: phone !== undefined ? phone : company.phone,
      email: email !== undefined ? email : company.email,
      website: website !== undefined ? website : company.website,
      isActive: isActive !== undefined ? isActive : company.isActive,
      updatedAt: new Date(),
    })
    .where(eq(companies.id, companyId))
    .returning();

  return updated;
};

/**
 * Delete company
 */
export const deleteCompany = async (companyId) => {
  await getCompanyById(companyId); // Check if exists

  await db.delete(companies).where(eq(companies.id, companyId));

  return { success: true, message: 'Firma bola odstránená' };
};

/**
 * Get company with related data (projects, todos, notes)
 */
export const getCompanyWithRelations = async (companyId) => {
  const company = await getCompanyById(companyId);

  // Get related projects
  const companyProjects = await db
    .select()
    .from(projects)
    .where(eq(projects.companyId, companyId))
    .orderBy(desc(projects.createdAt));

  // Get related todos
  const companyTodos = await db
    .select()
    .from(todos)
    .where(eq(todos.companyId, companyId))
    .orderBy(desc(todos.createdAt));

  // Get related notes
  const companyNotes = await db
    .select()
    .from(notes)
    .where(eq(notes.companyId, companyId))
    .orderBy(desc(notes.createdAt));

  const companyReminderList = await db
    .select()
    .from(companyReminders)
    .where(eq(companyReminders.companyId, companyId))
    .orderBy(desc(companyReminders.createdAt));

  return {
    ...company,
    projects: companyProjects,
    todos: companyTodos,
    notes: companyNotes,
    reminders: companyReminderList,
  };
};
