import Database from "better-sqlite3";
import { initSchema } from "./schema.js";
// Database initialization
export function initDatabase(dbPath) {
    const db = new Database(dbPath);
    db.pragma("journal_mode = WAL");
    initSchema(db);
    return db;
}
// Token operations
export function insertTokens(db, tokens) {
    const tokenStmt = db.prepare(`
    INSERT INTO tokens (
      category, subcategory, name, path, css_variable, scss_variable,
      value_raw, value_number, value_unit, value_computed,
      description, platform, source_file
    )
    VALUES (
      @category, @subcategory, @name, @path, @cssVariable, @scssVariable,
      @valueRaw, @valueNumber, @valueUnit, @valueComputed,
      @description, @platform, @sourceFile
    )
  `);
    const propertyStmt = db.prepare(`
    INSERT INTO token_properties (token_id, property, value, value_number, value_unit)
    VALUES (@tokenId, @property, @value, @valueNumber, @valueUnit)
  `);
    const insertMany = db.transaction((items) => {
        for (const item of items) {
            const result = tokenStmt.run({
                category: item.category,
                subcategory: item.subcategory ?? null,
                name: item.name,
                path: item.path,
                cssVariable: item.cssVariable ?? null,
                scssVariable: item.scssVariable ?? null,
                valueRaw: item.valueRaw,
                valueNumber: item.valueNumber ?? null,
                valueUnit: item.valueUnit ?? null,
                valueComputed: item.valueComputed ?? null,
                description: item.description ?? null,
                platform: item.platform ?? "all",
                sourceFile: item.sourceFile ?? null,
            });
            // Insert token properties if any (for composite tokens like shadows)
            if (item.properties && item.properties.length > 0) {
                const tokenId = result.lastInsertRowid;
                for (const prop of item.properties) {
                    propertyStmt.run({
                        tokenId,
                        property: prop.property,
                        value: prop.value,
                        valueNumber: prop.valueNumber ?? null,
                        valueUnit: prop.valueUnit ?? null,
                    });
                }
            }
        }
    });
    insertMany(tokens);
}
function rowToToken(row, properties) {
    const token = {
        category: row.category,
        subcategory: row.subcategory ?? undefined,
        name: row.name,
        path: row.path,
        cssVariable: row.css_variable ?? undefined,
        scssVariable: row.scss_variable ?? undefined,
        valueRaw: row.value_raw,
        valueNumber: row.value_number ?? undefined,
        valueUnit: row.value_unit ?? undefined,
        valueComputed: row.value_computed ?? undefined,
        description: row.description ?? undefined,
        platform: row.platform,
        sourceFile: row.source_file ?? undefined,
    };
    if (properties && properties.length > 0) {
        token.properties = properties.map((p) => ({
            property: p.property,
            value: p.value,
            valueNumber: p.value_number ?? undefined,
            valueUnit: p.value_unit ?? undefined,
        }));
    }
    return token;
}
export function getTokensByCategory(db, category) {
    const rows = category === "all"
        ? db.prepare("SELECT * FROM tokens").all()
        : db.prepare("SELECT * FROM tokens WHERE category = ?").all(category);
    return rows.map((row) => {
        const properties = db
            .prepare("SELECT property, value, value_number, value_unit FROM token_properties WHERE token_id = ?")
            .all(row.id);
        return rowToToken(row, properties);
    });
}
export function getTokensBySubcategory(db, category, subcategory) {
    const rows = db
        .prepare("SELECT * FROM tokens WHERE category = ? AND subcategory = ?")
        .all(category, subcategory);
    return rows.map((row) => {
        const properties = db
            .prepare("SELECT property, value, value_number, value_unit FROM token_properties WHERE token_id = ?")
            .all(row.id);
        return rowToToken(row, properties);
    });
}
export function getTokenByPath(db, path) {
    const row = db.prepare("SELECT * FROM tokens WHERE path = ?").get(path);
    if (!row)
        return undefined;
    const properties = db
        .prepare("SELECT property, value, value_number, value_unit FROM token_properties WHERE token_id = ?")
        .all(row.id);
    return rowToToken(row, properties);
}
export function searchTokens(db, query, limit = 20) {
    const rows = db
        .prepare(`
      SELECT t.*
      FROM tokens_fts
      JOIN tokens t ON tokens_fts.rowid = t.id
      WHERE tokens_fts MATCH ?
      ORDER BY rank
      LIMIT ?
    `)
        .all(query, limit);
    return rows.map((row) => {
        const properties = db
            .prepare("SELECT property, value, value_number, value_unit FROM token_properties WHERE token_id = ?")
            .all(row.id);
        return rowToToken(row, properties);
    });
}
// Component operations
export function insertComponent(db, component) {
    const result = db
        .prepare(`
    INSERT INTO components (name, slug, category, description, frameworks)
    VALUES (@name, @slug, @category, @description, @frameworks)
  `)
        .run({
        name: component.name,
        slug: component.slug,
        category: component.category ?? null,
        description: component.description ?? null,
        frameworks: component.frameworks ? JSON.stringify(component.frameworks) : null,
    });
    const componentId = result.lastInsertRowid;
    // Insert props
    if (component.props && component.props.length > 0) {
        const propStmt = db.prepare(`
      INSERT INTO component_props (component_id, name, type, default_value, required, options, description)
      VALUES (@componentId, @name, @type, @defaultValue, @required, @options, @description)
    `);
        for (const prop of component.props) {
            propStmt.run({
                componentId,
                name: prop.name,
                type: prop.type ?? null,
                defaultValue: prop.defaultValue ?? null,
                required: prop.required ? 1 : 0,
                options: prop.options ? JSON.stringify(prop.options) : null,
                description: prop.description ?? null,
            });
        }
    }
    // Insert slots
    if (component.slots && component.slots.length > 0) {
        const slotStmt = db.prepare(`
      INSERT INTO component_slots (component_id, name, description)
      VALUES (@componentId, @name, @description)
    `);
        for (const slot of component.slots) {
            slotStmt.run({
                componentId,
                name: slot.name,
                description: slot.description ?? null,
            });
        }
    }
    // Insert events
    if (component.events && component.events.length > 0) {
        const eventStmt = db.prepare(`
      INSERT INTO component_events (component_id, name, payload, description)
      VALUES (@componentId, @name, @payload, @description)
    `);
        for (const event of component.events) {
            eventStmt.run({
                componentId,
                name: event.name,
                payload: event.payload ?? null,
                description: event.description ?? null,
            });
        }
    }
    // Insert examples
    if (component.examples && component.examples.length > 0) {
        const exampleStmt = db.prepare(`
      INSERT INTO component_examples (component_id, framework, title, code, description)
      VALUES (@componentId, @framework, @title, @code, @description)
    `);
        for (const example of component.examples) {
            exampleStmt.run({
                componentId,
                framework: example.framework,
                title: example.title ?? null,
                code: example.code,
                description: example.description ?? null,
            });
        }
    }
    // Insert CSS classes
    if (component.cssClasses && component.cssClasses.length > 0) {
        const cssStmt = db.prepare(`
      INSERT INTO component_css_classes (component_id, class_name)
      VALUES (@componentId, @className)
    `);
        for (const className of component.cssClasses) {
            cssStmt.run({ componentId, className });
        }
    }
    return componentId;
}
export function insertComponents(db, components) {
    const transaction = db.transaction((items) => {
        for (const component of items) {
            insertComponent(db, component);
        }
    });
    transaction(components);
}
export function getComponentBySlug(db, slug) {
    const row = db.prepare("SELECT * FROM components WHERE slug = ? COLLATE NOCASE").get(slug);
    if (!row)
        return null;
    const props = db
        .prepare("SELECT * FROM component_props WHERE component_id = ?")
        .all(row.id);
    const slots = db
        .prepare("SELECT * FROM component_slots WHERE component_id = ?")
        .all(row.id);
    const events = db
        .prepare("SELECT * FROM component_events WHERE component_id = ?")
        .all(row.id);
    const examples = db
        .prepare("SELECT * FROM component_examples WHERE component_id = ?")
        .all(row.id);
    const cssClasses = db
        .prepare("SELECT class_name FROM component_css_classes WHERE component_id = ?")
        .all(row.id);
    return {
        name: row.name,
        slug: row.slug,
        category: row.category,
        description: row.description,
        frameworks: row.frameworks ? JSON.parse(row.frameworks) : [],
        props: props.map((p) => ({
            name: p.name,
            type: p.type,
            defaultValue: p.default_value,
            required: p.required === 1,
            options: p.options ? JSON.parse(p.options) : undefined,
            description: p.description,
        })),
        slots: slots.map((s) => ({
            name: s.name,
            description: s.description,
        })),
        events: events.map((e) => ({
            name: e.name,
            payload: e.payload,
            description: e.description,
        })),
        examples: examples.map((ex) => ({
            framework: ex.framework,
            title: ex.title,
            code: ex.code,
            description: ex.description,
        })),
        cssClasses: cssClasses.map((c) => c.class_name),
    };
}
export function listComponents(db, category) {
    if (category && category !== "all") {
        return db
            .prepare("SELECT name, slug, category, description FROM components WHERE category = ?")
            .all(category);
    }
    return db.prepare("SELECT name, slug, category, description FROM components").all();
}
// Documentation operations
export function insertDocs(db, docs) {
    const stmt = db.prepare(`
    INSERT INTO documentation (title, path, content, category, keywords)
    VALUES (@title, @path, @content, @category, @keywords)
  `);
    const insertMany = db.transaction((items) => {
        for (const item of items) {
            stmt.run({
                title: item.title,
                path: item.path,
                content: item.content,
                category: item.category ?? null,
                keywords: item.keywords ? JSON.stringify(item.keywords) : null,
            });
        }
    });
    insertMany(docs);
}
export function searchDocumentation(db, query, limit = 5) {
    const results = db
        .prepare(`
    SELECT
      d.title,
      d.path,
      d.category,
      snippet(docs_fts, 1, '<mark>', '</mark>', '...', 64) as snippet
    FROM docs_fts
    JOIN documentation d ON docs_fts.rowid = d.id
    WHERE docs_fts MATCH ?
    ORDER BY rank
    LIMIT ?
  `)
        .all(query, limit);
    return results;
}
export function getDocumentationByPath(db, path) {
    return db.prepare("SELECT * FROM documentation WHERE path = ?").get(path);
}
// CSS Utility operations
export function insertCssUtility(db, utility) {
    const result = db
        .prepare(`
      INSERT INTO css_utilities (name, slug, category, description)
      VALUES (@name, @slug, @category, @description)
    `)
        .run({
        name: utility.name,
        slug: utility.slug,
        category: utility.category,
        description: utility.description ?? null,
    });
    const utilityId = result.lastInsertRowid;
    // Insert CSS classes
    if (utility.classes && utility.classes.length > 0) {
        const classStmt = db.prepare(`
      INSERT INTO css_utility_classes (utility_id, class_name)
      VALUES (@utilityId, @className)
    `);
        for (const className of utility.classes) {
            classStmt.run({ utilityId, className });
        }
    }
    // Insert examples
    if (utility.examples && utility.examples.length > 0) {
        const exampleStmt = db.prepare(`
      INSERT INTO css_utility_examples (utility_id, title, code)
      VALUES (@utilityId, @title, @code)
    `);
        for (const example of utility.examples) {
            exampleStmt.run({
                utilityId,
                title: example.title ?? null,
                code: example.code,
            });
        }
    }
    return utilityId;
}
export function insertCssUtilities(db, utilities) {
    const transaction = db.transaction((items) => {
        for (const utility of items) {
            insertCssUtility(db, utility);
        }
    });
    transaction(utilities);
}
export function getCssUtility(db, name) {
    const row = db
        .prepare("SELECT * FROM css_utilities WHERE name = ? COLLATE NOCASE OR slug = ? COLLATE NOCASE")
        .get(name, name);
    if (!row)
        return null;
    const classes = db
        .prepare("SELECT class_name FROM css_utility_classes WHERE utility_id = ?")
        .all(row.id);
    const examples = db
        .prepare("SELECT title, code FROM css_utility_examples WHERE utility_id = ?")
        .all(row.id);
    return {
        name: row.name,
        slug: row.slug,
        category: row.category,
        description: row.description,
        classes: classes.map((c) => c.class_name),
        examples: examples.map((e) => ({
            title: e.title,
            code: e.code,
        })),
    };
}
export function listCssUtilities(db, category) {
    const query = category && category !== "all"
        ? `SELECT u.name, u.slug, u.category, u.description,
         (SELECT COUNT(*) FROM css_utility_classes WHERE utility_id = u.id) as classCount
       FROM css_utilities u WHERE u.category = ?`
        : `SELECT u.name, u.slug, u.category, u.description,
         (SELECT COUNT(*) FROM css_utility_classes WHERE utility_id = u.id) as classCount
       FROM css_utilities u`;
    if (category && category !== "all") {
        return db.prepare(query).all(category);
    }
    return db.prepare(query).all();
}
// Icon operations
export function insertIcons(db, icons) {
    const stmt = db.prepare(`
    INSERT INTO icons (name, icon_name, type, size, view_box, paths)
    VALUES (@name, @iconName, @type, @size, @viewBox, @paths)
  `);
    const insertMany = db.transaction((items) => {
        for (const item of items) {
            stmt.run({
                name: item.name,
                iconName: item.iconName,
                type: item.type,
                size: item.size,
                viewBox: item.viewBox,
                paths: item.paths,
            });
        }
    });
    insertMany(icons);
}
function rowToIcon(row) {
    return {
        name: row.name,
        iconName: row.icon_name,
        type: row.type,
        size: row.size,
        viewBox: row.view_box,
        paths: row.paths,
    };
}
export function searchIcons(db, query, options) {
    const limit = options?.limit ?? 20;
    let sql = `
    SELECT i.*
    FROM icons_fts
    JOIN icons i ON icons_fts.rowid = i.id
    WHERE icons_fts MATCH ?
  `;
    const params = [query];
    if (options?.type) {
        sql += " AND i.type = ?";
        params.push(options.type);
    }
    if (options?.size) {
        sql += " AND i.size = ?";
        params.push(options.size);
    }
    sql += " ORDER BY rank LIMIT ?";
    params.push(limit);
    const rows = db.prepare(sql).all(...params);
    return rows.map(rowToIcon);
}
export function getIconByName(db, name) {
    const row = db.prepare("SELECT * FROM icons WHERE name = ? COLLATE NOCASE").get(name);
    if (!row)
        return null;
    return rowToIcon(row);
}
export function getIconsByType(db, type, limit = 50) {
    const rows = db
        .prepare("SELECT * FROM icons WHERE type = ? ORDER BY icon_name, size LIMIT ?")
        .all(type, limit);
    return rows.map(rowToIcon);
}
export function listIconTypes(db) {
    return db
        .prepare("SELECT type, COUNT(*) as count FROM icons GROUP BY type ORDER BY count DESC")
        .all();
}
export function listIcons(db, options) {
    const limit = options?.limit ?? 100;
    let sql = "SELECT * FROM icons WHERE 1=1";
    const params = [];
    if (options?.type) {
        sql += " AND type = ?";
        params.push(options.type);
    }
    if (options?.size) {
        sql += " AND size = ?";
        params.push(options.size);
    }
    sql += " ORDER BY icon_name, size LIMIT ?";
    params.push(limit);
    const rows = db.prepare(sql).all(...params);
    return rows.map(rowToIcon);
}
// Utility functions
export function clearDatabase(db) {
    db.exec(`
    DELETE FROM token_properties;
    DELETE FROM tokens;
    DELETE FROM component_css_classes;
    DELETE FROM component_examples;
    DELETE FROM component_events;
    DELETE FROM component_slots;
    DELETE FROM component_props;
    DELETE FROM components;
    DELETE FROM css_utility_classes;
    DELETE FROM css_utility_examples;
    DELETE FROM css_utilities;
    DELETE FROM documentation;
    DELETE FROM icons;
  `);
}
export function getDatabaseStats(db) {
    const tokens = db.prepare("SELECT COUNT(*) as count FROM tokens").get();
    const components = db.prepare("SELECT COUNT(*) as count FROM components").get();
    const cssUtilities = db.prepare("SELECT COUNT(*) as count FROM css_utilities").get();
    const documentation = db.prepare("SELECT COUNT(*) as count FROM documentation").get();
    const icons = db.prepare("SELECT COUNT(*) as count FROM icons").get();
    return {
        tokens: tokens.count,
        components: components.count,
        cssUtilities: cssUtilities.count,
        documentation: documentation.count,
        icons: icons.count,
    };
}
//# sourceMappingURL=queries.js.map