import { getDatabase } from '../index';
import { Glaze } from '../../../types';
import { generateUUID } from '../../utils/uuid';
import { now } from '../../utils/datetime';
import seedGlazes from '../../../../assets/seed/glazes.json';

export async function seedGlazeCatalog(): Promise<void> {
  const db = getDatabase();

  // Check if glazes are already seeded (seed glazes have no user_id)
  const count = await db.getFirstAsync<{ count: number }>(
    'SELECT COUNT(*) as count FROM glazes WHERE is_custom = 0 AND user_id IS NULL'
  );

  if (count && count.count > 0) {
    return; // Already seeded
  }

  // Insert seed glazes (with NULL user_id to indicate they're shared)
  for (const seedGlaze of seedGlazes) {
    await db.runAsync(
      `INSERT INTO glazes (id, user_id, brand, name, code, color, finish, notes, is_custom, created_at)
       VALUES (?, NULL, ?, ?, ?, ?, ?, ?, 0, ?)`,
      [
        generateUUID(),
        seedGlaze.brand,
        seedGlaze.name,
        seedGlaze.code || null,
        (seedGlaze as any).color || null,
        seedGlaze.finish || 'unknown',
        seedGlaze.notes || null,
        now(),
      ]
    );
  }
}

export async function createCustomGlaze(
  userId: string,
  brand: string,
  name: string,
  code?: string,
  finish?: Glaze['finish'],
  notes?: string
): Promise<Glaze> {
  const db = getDatabase();
  const glaze: Glaze = {
    id: generateUUID(),
    brand,
    name,
    code,
    finish,
    notes,
    isCustom: true,
  };

  await db.runAsync(
    `INSERT INTO glazes (id, user_id, brand, name, code, finish, notes, is_custom, created_at)
     VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?)`,
    [
      glaze.id,
      userId,
      glaze.brand,
      glaze.name,
      glaze.code || null,
      glaze.finish || 'unknown',
      glaze.notes || null,
      now(),
    ]
  );

  return glaze;
}

export async function createMixedGlaze(
  userId: string,
  glazes: Glaze[],
  mixedColor: string,
  mixRatio?: string
): Promise<Glaze> {
  const db = getDatabase();

  // Generate a name for the mix
  const mixName = glazes.map(g => g.name).join(' + ');
  const mixBrand = 'Mixed';

  const glaze: Glaze = {
    id: generateUUID(),
    brand: mixBrand,
    name: mixName,
    color: mixedColor,
    finish: 'unknown',
    notes: mixRatio || undefined,
    isCustom: true,
    isMix: true,
    mixedGlazeIds: glazes.map(g => g.id),
    mixRatio: mixRatio || undefined,
  };

  await db.runAsync(
    `INSERT INTO glazes (id, user_id, brand, name, code, color, finish, notes, is_custom, is_mix, mixed_glaze_ids, mix_ratio, created_at)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?, ?)`,
    [
      glaze.id,
      userId,
      glaze.brand,
      glaze.name,
      null, // no code for mixed glazes
      glaze.color || null,
      glaze.finish || null,
      glaze.notes || null,
      JSON.stringify(glaze.mixedGlazeIds),
      glaze.mixRatio || null,
      now(),
    ]
  );

  return glaze;
}

export async function getGlaze(id: string): Promise<Glaze | null> {
  const db = getDatabase();
  const row = await db.getFirstAsync<any>(
    'SELECT * FROM glazes WHERE id = ?',
    [id]
  );

  if (!row) return null;

  return {
    id: row.id,
    brand: row.brand,
    name: row.name,
    code: row.code || undefined,
    color: row.color || undefined,
    finish: row.finish || undefined,
    notes: row.notes || undefined,
    isCustom: row.is_custom === 1,
    isMix: row.is_mix === 1,
    mixedGlazeIds: row.mixed_glaze_ids ? JSON.parse(row.mixed_glaze_ids) : undefined,
    mixRatio: row.mix_ratio || undefined,
  };
}

export async function getAllGlazes(userId?: string): Promise<Glaze[]> {
  const db = getDatabase();

  // Get seed glazes (user_id IS NULL) and user's custom glazes
  const rows = await db.getAllAsync<any>(
    userId
      ? 'SELECT * FROM glazes WHERE user_id IS NULL OR user_id = ? ORDER BY brand, name'
      : 'SELECT * FROM glazes WHERE user_id IS NULL ORDER BY brand, name',
    userId ? [userId] : []
  );

  return rows.map(row => ({
    id: row.id,
    brand: row.brand,
    name: row.name,
    code: row.code || undefined,
    color: row.color || undefined,
    finish: row.finish || undefined,
    notes: row.notes || undefined,
    isCustom: row.is_custom === 1,
    isMix: row.is_mix === 1,
    mixedGlazeIds: row.mixed_glaze_ids ? JSON.parse(row.mixed_glaze_ids) : undefined,
    mixRatio: row.mix_ratio || undefined,
  }));
}

export async function searchGlazes(query: string, userId?: string): Promise<Glaze[]> {
  const db = getDatabase();
  const searchTerm = `%${query}%`;

  const rows = await db.getAllAsync<any>(
    userId
      ? `SELECT * FROM glazes
         WHERE (user_id IS NULL OR user_id = ?)
         AND (brand LIKE ? OR name LIKE ? OR code LIKE ?)
         ORDER BY brand, name`
      : `SELECT * FROM glazes
         WHERE user_id IS NULL
         AND (brand LIKE ? OR name LIKE ? OR code LIKE ?)
         ORDER BY brand, name`,
    userId
      ? [userId, searchTerm, searchTerm, searchTerm]
      : [searchTerm, searchTerm, searchTerm]
  );

  return rows.map(row => ({
    id: row.id,
    brand: row.brand,
    name: row.name,
    code: row.code || undefined,
    color: row.color || undefined,
    finish: row.finish || undefined,
    notes: row.notes || undefined,
    isCustom: row.is_custom === 1,
    isMix: row.is_mix === 1,
    mixedGlazeIds: row.mixed_glaze_ids ? JSON.parse(row.mixed_glaze_ids) : undefined,
    mixRatio: row.mix_ratio || undefined,
  }));
}

export async function updateGlaze(
  id: string,
  updates: Partial<Omit<Glaze, 'id' | 'isCustom'>>
): Promise<void> {
  const db = getDatabase();
  const glaze = await getGlaze(id);
  if (!glaze) throw new Error('Glaze not found');
  if (!glaze.isCustom) throw new Error('Cannot update seed glazes');

  const updated = { ...glaze, ...updates };

  await db.runAsync(
    `UPDATE glazes
     SET brand = ?, name = ?, code = ?, finish = ?, notes = ?
     WHERE id = ?`,
    [
      updated.brand,
      updated.name,
      updated.code || null,
      updated.finish || 'unknown',
      updated.notes || null,
      id,
    ]
  );
}

export async function deleteGlaze(id: string): Promise<void> {
  const db = getDatabase();
  const glaze = await getGlaze(id);
  if (!glaze) return;
  if (!glaze.isCustom) throw new Error('Cannot delete seed glazes');

  await db.runAsync('DELETE FROM glazes WHERE id = ?', [id]);
}

export async function getGlazesByIds(ids: string[]): Promise<Glaze[]> {
  if (ids.length === 0) return [];

  const glazes: Glaze[] = [];
  for (const id of ids) {
    const glaze = await getGlaze(id);
    if (glaze) glazes.push(glaze);
  }

  return glazes;
}
