import * as vscode from 'vscode';
import { clearSheetRange, ensureSheetTab, readSheetRange, writeSheetRange, type SheetValues } from '../sheets';
import { logError, logInfo } from '../../utils';
import { onStocksStoreChanged, readStocksStore, writeStocksStore } from './stocksStore';
import type { Stock } from './types';

/**
 * stocks.json 원본 클라우드 백업 — Google Sheets `_backup` 탭 (v2.2.297).
 *
 * 문제: 목록의 source of truth 가 로컬 `.astra/stocks.json` 뿐이라 컴퓨터를 바꾸면
 * 데이터가 사라진다. Sheet1~3 sync 는 분류 *표시용* 이라 복원 불가.
 *
 * 해결: 같은 spreadsheet(`g1nation.stocks.spreadsheetId`)에 `_backup` 탭을 자동
 * 생성하고, 종목당 한 행으로 **원본 JSON 그대로** 백업. 새 컴퓨터에서는
 * `/stocks restore` 한 번으로 복원.
 *
 * 백업 시점: writeStocksStore 성공 → onStocksStoreChanged → 디바운스 30초 후 1회.
 * (add/remove/check/discover 자동편입/워처 가격갱신 전부 이 경로를 지남.)
 *
 * 레이아웃:
 *   A1: BACKUP_MARKER  B1: ISO timestamp  C1: 종목 수
 *   A2~: 심볼          B2~: 이름          C2~: JSON.stringify(stock)
 * 심볼/이름 컬럼은 사람이 시트에서 훑어보기용 — 복원은 C열 JSON 만 사용.
 */

const BACKUP_TAB = '_backup';
const BACKUP_MARKER = 'ASTRA_STOCKS_BACKUP_V1';
const DEBOUNCE_MS = 30_000;

function getSpreadsheetId(): string {
    return (vscode.workspace.getConfiguration('g1nation').get<string>('stocks.spreadsheetId') || '').trim();
}

function autoBackupEnabled(): boolean {
    return vscode.workspace.getConfiguration('g1nation').get<boolean>('stocks.autoBackup', true) !== false;
}

/** 지금 즉시 백업 1회. spreadsheetId 미설정이면 skip (ok:false + reason). */
export async function backupToSheet(
    context: vscode.ExtensionContext,
): Promise<{ ok: boolean; reason?: string; count?: number }> {
    const spreadsheetId = getSpreadsheetId();
    if (!spreadsheetId) {
        return { ok: false, reason: 'g1nation.stocks.spreadsheetId 미설정 — Settings 에서 spreadsheet ID 를 넣어주세요.' };
    }
    const store = readStocksStore();

    const ensured = await ensureSheetTab(context, spreadsheetId, BACKUP_TAB);
    if (!ensured.ok) return { ok: false, reason: `백업 탭 확인 실패: ${ensured.error}` };
    if (ensured.created) logInfo(`Stocks backup: '${BACKUP_TAB}' 탭 생성.`);

    // 목록이 줄었을 때 잔여 행이 남지 않게 먼저 클리어. 클리어 실패는 치명적이지
    // 않으므로 (덮어쓰기는 어차피 진행) 로그만 남기고 계속.
    const cleared = await clearSheetRange(context, spreadsheetId, `${BACKUP_TAB}!A:C`);
    if (!cleared.ok) logError('Stocks backup: 기존 행 클리어 실패 — 덮어쓰기로 계속.', { error: cleared.error });

    const rows: SheetValues = [[BACKUP_MARKER, new Date().toISOString(), store.length]];
    for (const s of store) {
        rows.push([s.심볼, s.이름, JSON.stringify(s)]);
    }
    const wrote = await writeSheetRange(context, spreadsheetId, `${BACKUP_TAB}!A1`, rows);
    if (!wrote.ok) return { ok: false, reason: `백업 쓰기 실패: ${wrote.error}` };

    logInfo('Stocks backup: 완료.', { count: store.length });
    return { ok: true, count: store.length };
}

/**
 * `_backup` 탭에서 목록 복원 — 로컬 stocks.json 을 백업 내용으로 **교체**.
 * silent write — 복원 직후 같은 내용을 되백업하는 루프 방지.
 */
export async function restoreFromSheet(
    context: vscode.ExtensionContext,
): Promise<{ ok: boolean; reason?: string; count?: number; backedUpAt?: string; previousCount?: number }> {
    const spreadsheetId = getSpreadsheetId();
    if (!spreadsheetId) {
        return { ok: false, reason: 'g1nation.stocks.spreadsheetId 미설정 — Settings 에서 spreadsheet ID 를 넣어주세요.' };
    }
    const read = await readSheetRange(context, spreadsheetId, `${BACKUP_TAB}!A1:C`);
    if (!read.ok) return { ok: false, reason: `백업 탭 읽기 실패: ${read.error} — 아직 백업한 적이 없다면 /stocks backup 먼저.` };

    const values = read.values;
    const header = values[0] ?? [];
    if (String(header[0] ?? '') !== BACKUP_MARKER) {
        return { ok: false, reason: `'${BACKUP_TAB}' 탭이 백업 형식이 아닙니다 (헤더 마커 불일치).` };
    }
    const backedUpAt = String(header[1] ?? '');

    const restored: Stock[] = [];
    for (const row of values.slice(1)) {
        const raw = String(row[2] ?? '').trim();
        if (!raw) continue;
        try {
            const s = JSON.parse(raw);
            if (s && typeof s === 'object' && typeof s.심볼 === 'string' && typeof s.이름 === 'string') {
                restored.push(s as Stock);
            }
        } catch { /* 손상 행은 skip — 나머지는 살린다 */ }
    }
    if (restored.length === 0) {
        return { ok: false, reason: '백업에 유효한 종목이 없습니다 — 로컬 목록을 건드리지 않았습니다.' };
    }

    const previousCount = readStocksStore().length;
    if (!writeStocksStore(restored, { silent: true })) {
        return { ok: false, reason: 'stocks.json 쓰기 실패 (워크스페이스 확인).' };
    }
    logInfo('Stocks restore: 완료.', { count: restored.length, backedUpAt, previousCount });
    return { ok: true, count: restored.length, backedUpAt, previousCount };
}

/**
 * 자동 백업 배선 — extension activate 에서 1회 호출.
 * store 변경 → 30초 디바운스 → backupToSheet. spreadsheetId 미설정/설정 OFF 면 조용히 skip.
 */
export function registerStocksAutoBackup(context: vscode.ExtensionContext): vscode.Disposable {
    let timer: NodeJS.Timeout | undefined;
    const sub = onStocksStoreChanged(() => {
        if (!autoBackupEnabled() || !getSpreadsheetId()) return;
        if (timer) clearTimeout(timer);
        timer = setTimeout(async () => {
            timer = undefined;
            const r = await backupToSheet(context);
            if (!r.ok) logError('Stocks 자동 백업 실패.', { reason: r.reason });
        }, DEBOUNCE_MS);
    });
    return {
        dispose: () => {
            sub.dispose();
            if (timer) { clearTimeout(timer); timer = undefined; }
        },
    };
}
