// 데이터 백업 — 가계부 전체 데이터를 엑셀(.xlsx)로 내보내기.
// 참조는 이름 기준(계좌명·분류명·태그명)으로 저장해 추후 '가져오기(복구)' 시 재매핑이 단순하도록 한다.
import { Capacitor } from '@capacitor/core'
import { accountApi } from '@/api/accountApi'
import { appLock } from '@/composables/appLock'

async function safe(promise) {
  try {
    return await promise
  } catch {
    return []
  }
}

function fileName() {
  const d = new Date()
  const p = (n) => String(n).padStart(2, '0')
  return `돈돼지가계부_백업_${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}.xlsx`
}

// 워크북을 플랫폼에 맞게 저장: 웹/PC=다운로드, 앱(네이티브)=파일 저장 후 공유
async function saveWorkbook(XLSX, wb, name) {
  if (Capacitor.isNativePlatform()) {
    const base64 = XLSX.write(wb, { type: 'base64', bookType: 'xlsx' })
    const { Filesystem, Directory } = await import('@capacitor/filesystem')
    const { Share } = await import('@capacitor/share')
    const res = await Filesystem.writeFile({ path: name, data: base64, directory: Directory.Cache })
    try {
      appLock.suppressLock() // 공유 시트 복귀 시 앱 잠금 오작동 방지
      await Share.share({ title: name, text: '가계부 백업 파일', url: res.uri })
    } catch {
      /* 공유 취소 — 파일은 캐시에 저장됨 */
    }
  } else {
    XLSX.writeFile(wb, name)
  }
}

export async function exportBackup() {
  const XLSX = await import('xlsx')

  const [entries, wallets, categories, recurrings, budgets, tags, quick] = await Promise.all([
    safe(accountApi.list({})),
    safe(accountApi.wallets()),
    safe(accountApi.categories()),
    safe(accountApi.recurrings()),
    // 예산은 월별 — 백업엔 현재 월 예산을 담는다
    safe(accountApi.budgets({ year: new Date().getFullYear(), month: new Date().getMonth() + 1 })),
    safe(accountApi.tags()),
    safe(accountApi.quickEntries()),
  ])

  const catNameById = {}
  categories.forEach((c) => (catNameById[c.id] = c.name))

  const wb = XLSX.utils.book_new()
  const add = (name, rows) => XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(rows), name)

  add('내역', entries.map((e) => ({
    날짜: e.entryDate, 구분: e.type, 분류: e.category, 금액: e.amount, 메모: e.memo,
    계좌: e.walletName, 계좌ID: e.walletId, 입금계좌: e.toWalletName, 입금계좌ID: e.toWalletId,
    할부개월: e.installmentMonths, 태그: (e.tags || []).join(','),
  })))
  add('계좌', wallets.map((w) => ({
    ID: w.id, 종류: w.type, 이름: w.name, '은행/카드사': w.issuer, 계좌번호: w.accountNumber,
    카드유형: w.cardType, 개시잔액: w.openingBalance, 개시일: w.openingDate, '평가액(수동)': w.currentValue,
  })))
  add('분류', categories.map((c) => ({
    구분: c.type, 이름: c.name, 대분류: c.parentId ? catNameById[c.parentId] || '' : '',
  })))
  add('고정지출', recurrings.map((r) => ({
    제목: r.title, 구분: r.type, 금액: r.amount, 분류: r.category, 메모: r.memo,
    계좌: r.walletName, 계좌ID: r.walletId, 입금계좌: r.toWalletName, 입금계좌ID: r.toWalletId, 주기: r.frequency,
    일: r.dayOfMonth, 요일: r.dayOfWeek, 월: r.monthOfYear,
    시작일: r.startDate, 종료일: r.endDate, 활성: r.active,
  })))
  add('예산', budgets.map((b) => ({
    분류: b.category, 고정: b.fixed, 기준단위: b.baseUnit, 기준금액: b.baseAmount,
    일: b.daily, 주: b.weekly, 월: b.monthly, 년: b.yearly,
  })))
  add('태그', tags.map((t) => ({ 이름: t.name })))
  add('자주쓰는내역', quick.map((q) => ({
    라벨: q.label, 구분: q.type, 분류: q.category, 금액: q.amount, 메모: q.memo, 계좌: q.walletName, 계좌ID: q.walletId,
  })))

  await saveWorkbook(XLSX, wb, fileName())
}

// ===== 가져오기(복구) — 엑셀 파싱 → 백엔드 복구 =====
export async function importBackup(file) {
  const XLSX = await import('xlsx')
  const buf = await file.arrayBuffer()
  const wb = XLSX.read(buf, { type: 'array' })

  const rows = (name) => {
    const ws = wb.Sheets[name]
    return ws ? XLSX.utils.sheet_to_json(ws, { defval: null }) : []
  }
  const str = (v) => (v === null || v === undefined || v === '' ? null : String(v).trim())
  const num = (v) => (v === null || v === undefined || v === '' ? null : Number(v))
  const bool = (v) => v === true || v === 1 || ['true', 'TRUE', '1', 'Y', '예'].includes(String(v))
  const date = (v) => {
    if (v === null || v === undefined || v === '') return null
    if (typeof v === 'number' && XLSX.SSF) {
      const d = XLSX.SSF.parse_date_code(v)
      if (d) return `${d.y}-${String(d.m).padStart(2, '0')}-${String(d.d).padStart(2, '0')}`
    }
    return String(v).trim().slice(0, 10) // 'YYYY-MM-DD'
  }

  const payload = {
    wallets: rows('계좌')
      .map((r) => ({
        oldId: num(r['ID']), type: str(r['종류']), name: str(r['이름']), issuer: str(r['은행/카드사']),
        accountNumber: str(r['계좌번호']), cardType: str(r['카드유형']),
        openingBalance: num(r['개시잔액']), openingDate: date(r['개시일']), currentValue: num(r['평가액(수동)']),
      }))
      .filter((w) => w.name && w.type),
    categories: rows('분류')
      .map((r) => ({ type: str(r['구분']), name: str(r['이름']), parent: str(r['대분류']) }))
      .filter((c) => c.name && c.type),
    tags: rows('태그').map((r) => str(r['이름'])).filter(Boolean),
    entries: rows('내역')
      .map((r) => ({
        entryDate: date(r['날짜']), type: str(r['구분']), category: str(r['분류']),
        amount: num(r['금액']), memo: str(r['메모']), walletId: num(r['계좌ID']), toWalletId: num(r['입금계좌ID']),
        installmentMonths: num(r['할부개월']),
        tags: str(r['태그']) ? String(r['태그']).split(',').map((s) => s.trim()).filter(Boolean) : [],
      }))
      .filter((e) => e.entryDate && e.type),
    recurrings: rows('고정지출')
      .map((r) => ({
        title: str(r['제목']), type: str(r['구분']), amount: num(r['금액']), category: str(r['분류']), memo: str(r['메모']),
        walletId: num(r['계좌ID']), toWalletId: num(r['입금계좌ID']), frequency: str(r['주기']),
        dayOfMonth: num(r['일']), dayOfWeek: num(r['요일']), monthOfYear: num(r['월']),
        startDate: date(r['시작일']), endDate: date(r['종료일']), active: bool(r['활성']),
      }))
      .filter((r) => r.title && r.type),
    budgets: rows('예산')
      .map((r) => ({
        category: str(r['분류']), fixed: bool(r['고정']), baseUnit: str(r['기준단위']), baseAmount: num(r['기준금액']),
        daily: num(r['일']), weekly: num(r['주']), monthly: num(r['월']), yearly: num(r['년']),
      }))
      .filter((b) => b.category),
    quickEntries: rows('자주쓰는내역')
      .map((r) => ({
        label: str(r['라벨']), type: str(r['구분']), category: str(r['분류']),
        amount: num(r['금액']), memo: str(r['메모']), walletId: num(r['계좌ID']),
      }))
      .filter((q) => q.type),
  }

  await accountApi.restore(payload)
}
