/**
 * files command - List project files and directories
 *
 * Supports time-based filtering via modified_since parameter to find
 * files that were recently indexed (useful for "what changed this session?")
 */

import { withProjectDb } from './shared.js';
import { parseTimeOffset } from './query.js';
import type { ProjectFileRow, FileRow } from '../db/queries.js';
import { globToRegex } from '../utils/glob.js';

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

export interface FilesParams {
    path: string;
    type?: string;           // Filter by type: dir, code, config, doc, asset, test, other
    pattern?: string;        // Glob pattern filter
    modifiedSince?: string;  // Only files indexed after this time (2h, 30m, 1d, 1w, or ISO date)
}

export interface ProjectFile {
    path: string;
    type: string;
    extension: string | null;
    indexed: boolean;
    lastIndexed?: number;  // Timestamp when file was last indexed (only for code files)
}

export interface FilesResult {
    success: boolean;
    files: ProjectFile[];
    totalFiles: number;
    byType: Record<string, number>;
    error?: string;
}

// ============================================================
// Implementation
// ============================================================

export function files(params: FilesParams): FilesResult {
    const { path: projectPath, type, pattern, modifiedSince } = params;

    return withProjectDb(
        projectPath, true,
        (error) => ({ success: false, files: [], totalFiles: 0, byType: {}, error }),
        (db, queries) => {
            try {
                // Parse time filter
                const modifiedSinceTs = modifiedSince ? parseTimeOffset(modifiedSince) : null;

                // If time filter is specified, get recently indexed files from the files table
                let recentlyIndexedPaths: Set<string> | null = null;
                let indexedFilesMap: Map<string, FileRow> | null = null;

                if (modifiedSinceTs !== null) {
                    // Get all indexed files and filter by last_indexed
                    const allIndexedFiles = queries.getAllFiles();
                    recentlyIndexedPaths = new Set<string>();
                    indexedFilesMap = new Map<string, FileRow>();

                    for (const file of allIndexedFiles) {
                        indexedFilesMap.set(file.path, file);
                        if (file.last_indexed >= modifiedSinceTs) {
                            recentlyIndexedPaths.add(file.path);
                        }
                    }
                }

                // Get files, optionally filtered by type
                let projectFiles: ProjectFileRow[];

                if (type && isValidType(type)) {
                    projectFiles = queries.getProjectFilesByType(type as ProjectFileRow['type']);
                } else {
                    projectFiles = queries.getProjectFiles();
                }

                // Apply glob pattern filter if specified
                if (pattern) {
                    const regex = globToRegex(pattern);
                    projectFiles = projectFiles.filter(f => regex.test(f.path));
                }

                // Apply time filter if specified (only show files indexed after the timestamp)
                if (recentlyIndexedPaths !== null) {
                    projectFiles = projectFiles.filter(f => recentlyIndexedPaths!.has(f.path));
                }

                // Build type statistics
                const byType: Record<string, number> = {};
                for (const file of projectFiles) {
                    byType[file.type] = (byType[file.type] || 0) + 1;
                }

                // Convert to output format
                const result: ProjectFile[] = projectFiles.map(f => {
                    const indexed = f.indexed === 1;
                    const indexedFile = indexedFilesMap?.get(f.path);
                    return {
                        path: f.path,
                        type: f.type,
                        extension: f.extension,
                        indexed,
                        lastIndexed: indexedFile?.last_indexed,
                    };
                });

                return {
                    success: true,
                    files: result,
                    totalFiles: result.length,
                    byType,
                };

            } catch (error) {
                return {
                    success: false,
                    files: [],
                    totalFiles: 0,
                    byType: {},
                    error: error instanceof Error ? error.message : String(error),
                };
            }
        }
    );
}

// ============================================================
// Helper functions
// ============================================================

const VALID_TYPES = new Set(['dir', 'code', 'config', 'doc', 'asset', 'test', 'other']);

function isValidType(type: string): boolean {
    return VALID_TYPES.has(type);
}

