import fs from 'fs/promises';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';

const DATA_DIR = path.join(process.cwd(), 'data');

// Ensure data directory exists
const initDataDir = async () => {
    try {
        await fs.access(DATA_DIR);
    } catch {
        await fs.mkdir(DATA_DIR, { recursive: true });
    }
};

initDataDir();

export class FileStorageService<T extends { id: string }> {
    private filePath: string;

    constructor(filename: string) {
        this.filePath = path.join(DATA_DIR, filename);
    }

    private async readFile(): Promise<T[]> {
        try {
            await initDataDir();
            const data = await fs.readFile(this.filePath, 'utf-8');
            return JSON.parse(data);
        } catch (error: unknown) {
            const err = error as { code?: string };
            if (err.code === 'ENOENT') {
                return []; // File doesn't exist yet, return empty array
            }
            throw error;
        }
    }

    private async writeFile(data: T[]): Promise<void> {
        await initDataDir();
        await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
    }

    async getAll(): Promise<T[]> {
        return this.readFile();
    }

    async getById(id: string): Promise<T | null> {
        const items = await this.readFile();
        return items.find(item => item.id === id) || null;
    }

    async create(data: Omit<T, 'id'>): Promise<T> {
        const items = await this.readFile();
        const newItem = { ...data, id: uuidv4() } as T;
        items.push(newItem);
        await this.writeFile(items);
        return newItem;
    }

    async update(id: string, data: Partial<T>): Promise<T | null> {
        const items = await this.readFile();
        const index = items.findIndex(item => item.id === id);
        if (index === -1) return null;

        items[index] = { ...items[index], ...data };
        await this.writeFile(items);
        return items[index];
    }

    async delete(id: string): Promise<boolean> {
        const items = await this.readFile();
        const filtered = items.filter(item => item.id !== id);
        if (filtered.length === items.length) return false;

        await this.writeFile(filtered);
        return true;
    }

    // Helper for filtering by foreign keys (e.g., get parts by projectId)
    async getByField(field: keyof T, value: T[keyof T]): Promise<T[]> {
        const items = await this.readFile();
        return items.filter(item => item[field] === value);
    }
}
