/**
 * link command - Link dependency projects
 *
 * Allows cross-project queries by linking other AiDex instances.
 */

import { existsSync } from 'fs';
import { join, basename } from 'path';
import { INDEX_DIR } from '../constants.js';
import { openDatabase } from '../db/index.js';
import { validateIndex, noIndexError, withProjectDb, withDatabase } from './shared.js';

// ============================================================
// Types
// ============================================================

export interface LinkParams {
    path: string;           // Current project path
    dependency: string;     // Path to dependency project (with index dir)
    name?: string;          // Optional display name
}

export interface LinkResult {
    success: boolean;
    dependencyId?: number;
    name: string;
    filesAvailable: number;
    error?: string;
}

export interface UnlinkParams {
    path: string;           // Current project path
    dependency: string;     // Path to dependency to remove
}

export interface UnlinkResult {
    success: boolean;
    removed: boolean;
    error?: string;
}

export interface ListLinksParams {
    path: string;           // Project path
}

export interface LinkedProject {
    id: number;
    path: string;
    name: string | null;
    filesAvailable: number;
    available: boolean;
}

export interface ListLinksResult {
    success: boolean;
    dependencies: LinkedProject[];
    error?: string;
}

// ============================================================
// Link implementation
// ============================================================

export function link(params: LinkParams): LinkResult {
    const { path: projectPath, dependency: dependencyPath, name } = params;

    // Validate project path
    const dbPath = validateIndex(projectPath);
    if (!dbPath) {
        return {
            success: false,
            name: '',
            filesAvailable: 0,
            error: noIndexError(projectPath),
        };
    }

    // Validate dependency path
    const depDbPath = validateIndex(dependencyPath);
    if (!depDbPath) {
        return {
            success: false,
            name: '',
            filesAvailable: 0,
            error: `No AiDex index found at ${dependencyPath}. Run aidex_init on dependency first.`,
        };
    }

    return withDatabase(dbPath, false, (db) => {
        try {
            // Get dependency info
            const depDb = openDatabase(depDbPath, true);
            const depStats = depDb.getStats();
            const depName = name ?? depDb.getMetadata('project_name') ?? basename(dependencyPath);
            depDb.close();

            // Check if already linked
            const existingDep = db.getDb().prepare(
                'SELECT * FROM dependencies WHERE path = ?'
            ).get(dependencyPath) as { id: number } | undefined;

            let dependencyId: number;

            if (existingDep) {
                // Update existing
                db.getDb().prepare(
                    'UPDATE dependencies SET name = ?, last_checked = ? WHERE id = ?'
                ).run(depName, Date.now(), existingDep.id);
                dependencyId = existingDep.id;
            } else {
                // Insert new
                const result = db.getDb().prepare(
                    'INSERT INTO dependencies (path, name, last_checked) VALUES (?, ?, ?)'
                ).run(dependencyPath, depName, Date.now());
                dependencyId = result.lastInsertRowid as number;
            }

            return {
                success: true,
                dependencyId,
                name: depName,
                filesAvailable: depStats.files,
            };
        } catch (err) {
            return {
                success: false,
                name: '',
                filesAvailable: 0,
                error: err instanceof Error ? err.message : String(err),
            };
        }
    });
}

// ============================================================
// Unlink implementation
// ============================================================

export function unlink(params: UnlinkParams): UnlinkResult {
    const { path: projectPath, dependency: dependencyPath } = params;

    return withProjectDb(
        projectPath, false,
        (error) => ({ success: false, removed: false, error }),
        (db) => {
            try {
                const result = db.getDb().prepare(
                    'DELETE FROM dependencies WHERE path = ?'
                ).run(dependencyPath);

                return {
                    success: true,
                    removed: result.changes > 0,
                };
            } catch (err) {
                return {
                    success: false,
                    removed: false,
                    error: err instanceof Error ? err.message : String(err),
                };
            }
        }
    );
}

// ============================================================
// List links implementation
// ============================================================

export function listLinks(params: ListLinksParams): ListLinksResult {
    const { path: projectPath } = params;

    return withProjectDb(
        projectPath, true,
        (error) => ({ success: false, dependencies: [], error }),
        (db) => {
            try {
                const deps = db.getDb().prepare(
                    'SELECT * FROM dependencies ORDER BY name'
                ).all() as Array<{ id: number; path: string; name: string | null; last_checked: number | null }>;

                const dependencies: LinkedProject[] = [];

                for (const dep of deps) {
                    const depDbPath = join(dep.path, INDEX_DIR, 'index.db');
                    const available = existsSync(depDbPath);

                    let filesAvailable = 0;
                    if (available) {
                        try {
                            const depDb = openDatabase(depDbPath, true);
                            filesAvailable = depDb.getStats().files;
                            depDb.close();
                        } catch {
                            // Ignore errors reading dependency
                        }
                    }

                    dependencies.push({
                        id: dep.id,
                        path: dep.path,
                        name: dep.name,
                        filesAvailable,
                        available,
                    });
                }

                return {
                    success: true,
                    dependencies,
                };
            } catch (err) {
                return {
                    success: false,
                    dependencies: [],
                    error: err instanceof Error ? err.message : String(err),
                };
            }
        }
    );
}
