using System.Text.Json;
namespace VideoDownloader.App.Browser;
/// 즐겨찾기/히스토리 JSON 영속화 (%AppData%/VideoDownloader).
/// #5 저장/로드 실패를 조용 삼킴하지 않고 browserstore.log 에 기록하며,
/// 손상 파일은 백업 후 빈 목록을 반환(다음 저장이 원본을 덮어쓰는 데이터 손실 방지).
public static class BrowserStore
{
private static string Dir => AppPaths.DataDir;
private static string BookmarksPath => Path.Combine(Dir, "bookmarks.json");
private static string HistoryPath => Path.Combine(Dir, "history.json");
private static readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true };
public static List LoadBookmarks()
{
try { if (File.Exists(BookmarksPath)) return JsonSerializer.Deserialize>(File.ReadAllText(BookmarksPath)) ?? new(); }
catch (Exception e) { LogLoadFail(BookmarksPath, e); }
return new();
}
public static void SaveBookmarks(List bookmarks)
{
try { Directory.CreateDirectory(Dir); File.WriteAllText(BookmarksPath, JsonSerializer.Serialize(bookmarks, JsonOpts)); }
catch (Exception e) { LogFail("저장", BookmarksPath, e); } // 디스크 가득/권한/잠금 → UI 스레드 전파 대신 로그
}
public static List LoadHistory()
{
try { if (File.Exists(HistoryPath)) return JsonSerializer.Deserialize>(File.ReadAllText(HistoryPath)) ?? new(); }
catch (Exception e) { LogLoadFail(HistoryPath, e); }
return new();
}
public static void SaveHistory(List history)
{
try { Directory.CreateDirectory(Dir); File.WriteAllText(HistoryPath, JsonSerializer.Serialize(history, JsonOpts)); }
catch (Exception e) { LogFail("저장", HistoryPath, e); }
}
/// 로드 실패(손상/권한/잠금) 시 원본을 .corrupt 백업한 뒤 로그.
/// 빈 목록을 반환하더라도 원본이 남아 다음 저장이 사용자 데이터를 덮어쓰지 않게 한다.
private static void LogLoadFail(string path, Exception e)
{
try
{
if (File.Exists(path))
File.Move(path, $"{path}.corrupt.{DateTime.Now:yyyyMMddHHmmss}.bak", overwrite: true);
}
catch { /* best-effort 백업 — 실패해도 계속 진행 */ }
LogFail("로드", path, e);
}
private static void LogFail(string op, string path, Exception e)
=> Log($"{op} 실패({Path.GetFileName(path)}): {e.GetType().Name}: {e.Message}");
private static void Log(string msg)
{
try
{
Directory.CreateDirectory(Dir);
File.AppendAllText(Path.Combine(Dir, "browserstore.log"),
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {msg}{Environment.NewLine}");
}
catch { /* 로그마저 실패하면 조용히 */ }
}
}