import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import { logError, logInfo } from '../../utils';
import type { Stock, StocksStore } from './types';

/**
 * 워크스페이스 루트의 `.astra/stocks.json` 을 source of truth 로 사용.
 *
 * 결정 근거 (q1=A): 사용자가 워크스페이스 단위로 다른 종목 리스트를 가질 수 있게.
 * 워크스페이스가 없으면 (= VS Code 가 폴더 열지 않고 시작) 빈 store 반환 — 이 경우
 * watcher / slash 명령 모두 silent skip.
 *
 * Atomic write: tmp 파일에 쓰고 rename — 동시 read 또는 SIGKILL 중간에도 partial JSON
 * 으로 안 깨지게.
 */

const STORE_REL_PATH = '.astra/stocks.json';

export function getStocksFilePath(): string | null {
    const folders = vscode.workspace.workspaceFolders;
    if (!folders || folders.length === 0) return null;
    return path.join(folders[0].uri.fsPath, STORE_REL_PATH);
}

/** 파일 없으면 빈 배열 반환. 파일 파싱 실패해도 빈 배열 + 에러 로그. */
export function readStocksStore(): StocksStore {
    const filePath = getStocksFilePath();
    if (!filePath || !fs.existsSync(filePath)) return [];
    try {
        const raw = fs.readFileSync(filePath, 'utf-8');
        const parsed = JSON.parse(raw);
        if (!Array.isArray(parsed)) {
            logError('stocks.json 가 배열이 아닙니다 — 빈 store 반환.', { filePath });
            return [];
        }
        return parsed as StocksStore;
    } catch (e: any) {
        logError('stocks.json 읽기 실패.', { filePath, error: e?.message ?? String(e) });
        return [];
    }
}

/** Atomic write — tmp + rename. 워크스페이스 없으면 false 반환 (caller 가 안내). */
export function writeStocksStore(store: StocksStore): boolean {
    const filePath = getStocksFilePath();
    if (!filePath) {
        logError('워크스페이스 폴더가 없어 stocks.json 쓰기 불가.');
        return false;
    }
    try {
        const dir = path.dirname(filePath);
        if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
        const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
        fs.writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf-8');
        fs.renameSync(tmp, filePath);
        return true;
    } catch (e: any) {
        logError('stocks.json 쓰기 실패.', { filePath, error: e?.message ?? String(e) });
        return false;
    }
}

/** 한 종목 추가. 같은 심볼이 이미 있으면 false (caller 가 안내). */
export function addStock(stock: Stock): { ok: boolean; reason?: string } {
    const store = readStocksStore();
    if (store.some(s => s.심볼 === stock.심볼)) {
        return { ok: false, reason: `심볼 ${stock.심볼} 이미 존재` };
    }
    store.push(stock);
    const wrote = writeStocksStore(store);
    if (!wrote) return { ok: false, reason: '쓰기 실패 (워크스페이스 없음 또는 권한)' };
    logInfo('Stocks: 종목 추가.', { symbol: stock.심볼, name: stock.이름 });
    return { ok: true };
}

/** 한 종목 제거. 못 찾으면 false. */
export function removeStock(symbol: string): { ok: boolean; reason?: string } {
    const store = readStocksStore();
    const idx = store.findIndex(s => s.심볼 === symbol);
    if (idx < 0) return { ok: false, reason: `심볼 ${symbol} 못 찾음` };
    const removed = store.splice(idx, 1)[0];
    const wrote = writeStocksStore(store);
    if (!wrote) return { ok: false, reason: '쓰기 실패' };
    logInfo('Stocks: 종목 제거.', { symbol, name: removed.이름 });
    return { ok: true };
}

/** 한 종목의 필드 patch — 현재가 갱신 / 필터 업데이트 등. */
export function updateStock(symbol: string, patch: Partial<Stock>): boolean {
    const store = readStocksStore();
    const idx = store.findIndex(s => s.심볼 === symbol);
    if (idx < 0) return false;
    store[idx] = { ...store[idx], ...patch };
    return writeStocksStore(store);
}
