<script setup>
import { computed, onMounted, ref } from 'vue'
import { accountApi } from '@/api/accountApi'
import { loanSchedule, cardInstallmentSchedule, currentYm } from '@/utils/repayment'

const loading = ref(false)
const error = ref(null)
const items = ref([]) // { id, kind, name, sub, rows, partial }
const expanded = ref(new Set())

const now = currentYm()
const nowLabel = `${now.y}.${String(now.m).padStart(2, '0')}`

function won(n) {
  return n == null ? '-' : Number(n).toLocaleString('ko-KR')
}
function loanMethodLabel(v) {
  return v === 'EQUAL_PAYMENT'
    ? '원리금균등'
    : v === 'EQUAL_PRINCIPAL'
      ? '원금균등'
      : v === 'BULLET'
        ? '만기일시'
        : '상환'
}
function loanSub(w) {
  const parts = [loanMethodLabel(w.loanMethod)]
  if (w.loanRate) parts.push(`${w.loanRate}%`)
  if (w.loanMonths) parts.push(`${w.loanMonths}개월`)
  return parts.join(' · ')
}

async function load() {
  loading.value = true
  error.value = null
  try {
    const ws = await accountApi.wallets()
    const list = []

    // 대출: 금리가 설정된 대출만 상각 스케줄 계산
    for (const w of ws.filter((x) => x.type === 'LOAN' && x.loanRate)) {
      const { rows, partial } = loanSchedule(w, now)
      if (!rows.length) continue
      list.push({ id: `loan-${w.id}`, kind: 'LOAN', name: w.name, sub: loanSub(w), rows, partial })
    }

    // 카드 할부(무이자): 진행 중인 할부 건별로
    const cards = ws.filter((x) => x.type === 'CARD')
    const entryLists = await Promise.all(
      cards.map((c) => accountApi.walletEntries(c.id).catch(() => [])),
    )
    cards.forEach((c, i) => {
      const purchases = (entryLists[i] || []).filter(
        (e) => e.type === 'EXPENSE' && Number(e.installmentMonths) >= 2,
      )
      for (const e of purchases) {
        const sch = cardInstallmentSchedule(e, now)
        if (!sch) continue
        const desc = e.category || e.memo || '할부'
        list.push({
          id: `card-${e.id}`,
          kind: 'CARD',
          name: c.name,
          sub: `${desc} · ${e.installmentMonths}개월 무이자 · ${String(e.entryDate || '').slice(0, 10)}`,
          rows: sch.rows,
          partial: false,
        })
      }
    })

    items.value = list
  } catch (e) {
    error.value = e.response?.data?.message || '불러오지 못했습니다.'
  } finally {
    loading.value = false
  }
}
onMounted(load)

// 이번 달 상환 합계 (이번 달 회차만)
const thisMonth = computed(() => {
  let p = 0, i = 0, t = 0
  for (const it of items.value) {
    for (const r of it.rows) {
      if (r.label !== nowLabel) continue
      p += r.principal || 0
      i += r.interest || 0
      t += r.total ?? (r.principal || 0) + (r.interest || 0)
    }
  }
  return { p, i, t }
})
// 남은 상환 총액
const remainTotal = computed(() => {
  let p = 0, i = 0, t = 0
  for (const it of items.value) {
    for (const r of it.rows) {
      p += r.principal || 0
      i += r.interest || 0
      t += r.total ?? (r.principal || 0) + (r.interest || 0)
    }
  }
  return { p, i, t }
})

function itemThisMonth(it) {
  const r = it.rows.find((x) => x.label === nowLabel)
  return r ? (r.total ?? (r.principal || 0) + (r.interest || 0)) : null
}
function itemRemain(it) {
  return it.rows.reduce((s, r) => s + (r.total ?? (r.principal || 0) + (r.interest || 0)), 0)
}
function toggle(id) {
  const s = new Set(expanded.value)
  s.has(id) ? s.delete(id) : s.add(id)
  expanded.value = s
}
</script>

<template>
  <section class="repay">
    <h1 class="title">대출·할부 상환</h1>
    <p class="lead">대출 월 상환금과 카드 할부금을 원금·이자로 나눠, 남은 회차까지 한눈에 봅니다.</p>

    <p v-if="error" class="msg error">{{ error }}</p>
    <p v-else-if="loading" class="msg">불러오는 중...</p>

    <template v-else>
      <!-- 합계 요약 -->
      <div class="summary">
        <div class="sum-card accent">
          <span class="k">이번 달 상환 예정금액</span>
          <span class="v">{{ won(thisMonth.t) }}</span>
          <span class="split">원금 {{ won(thisMonth.p) }} · 이자 {{ won(thisMonth.i) }}</span>
        </div>
        <div class="sum-card">
          <span class="k">남은 상환 총액</span>
          <span class="v">{{ won(remainTotal.t) }}</span>
          <span class="split">원금 {{ won(remainTotal.p) }} · 이자 {{ won(remainTotal.i) }}</span>
        </div>
      </div>

      <div v-if="!items.length" class="empty-state">
        <p class="empty-emoji">💳</p>
        <p class="empty-title">상환 중인 대출·할부가 없어요</p>
        <p class="empty-desc">대출 계좌(금리 입력)나 카드 할부 결제가 있으면 여기에 표시됩니다.</p>
      </div>

      <!-- 항목별 -->
      <div v-for="it in items" :key="it.id" class="item">
        <button type="button" class="item-head" @click="toggle(it.id)">
          <span class="kind" :class="it.kind === 'LOAN' ? 'k-loan' : 'k-card'">
            {{ it.kind === 'LOAN' ? '대출' : '카드' }}
          </span>
          <span class="info">
            <span class="name">{{ it.name }}</span>
            <span class="sub">{{ it.sub }}</span>
          </span>
          <span class="amt">
            <span class="amt-now">{{ won(itemThisMonth(it)) }}</span>
            <span class="amt-rem">남은 회차 {{ it.rows.length }}회 · {{ won(itemRemain(it)) }}</span>
          </span>
          <span class="chev">{{ expanded.has(it.id) ? '▾' : '▸' }}</span>
        </button>

        <div v-if="expanded.has(it.id)" class="sched-wrap">
          <p v-if="it.partial" class="partial-note">상환 개월(기간) 정보가 없어 이번 달 이자만 표시합니다. 계좌 관리에서 대출 개월수를 입력하면 전체 스케줄이 계산됩니다.</p>
          <table class="sched">
            <thead>
              <tr>
                <th>회차</th>
                <th class="num">원금</th>
                <th class="num">이자</th>
                <th class="num">합계</th>
                <th class="num">남은 잔액</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(r, idx) in it.rows" :key="idx" :class="{ current: r.label === nowLabel }">
                <td>{{ r.label }}</td>
                <td class="num">{{ won(r.principal) }}</td>
                <td class="num">{{ won(r.interest) }}</td>
                <td class="num strong">{{ won(r.total) }}</td>
                <td class="num muted">{{ won(r.balance) }}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </template>
  </section>
</template>

<style scoped>
.repay {
  max-width: 820px;
  margin: 0 auto;
}
.title {
  font-size: 1.3rem;
  font-weight: 800;
  margin: 0 0 0.25rem;
}
.lead {
  font-size: 0.9rem;
  opacity: 0.7;
  margin: 0 0 1.1rem;
}
.msg {
  margin: 0.75rem 0;
  opacity: 0.8;
}
.msg.error {
  color: #c0392b;
}
.summary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem;
  margin-bottom: 1.2rem;
}
.sum-card {
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  background: var(--color-background-soft);
}
.sum-card.accent {
  border-color: hsla(160, 100%, 37%, 0.6);
  background: hsla(160, 100%, 37%, 0.06);
}
.sum-card .k {
  font-size: 0.82rem;
  opacity: 0.7;
}
.sum-card .v {
  font-size: 1.35rem;
  font-weight: 800;
}
.sum-card .split {
  font-size: 0.78rem;
  opacity: 0.65;
}
.item {
  border: 1px solid var(--color-border);
  border-radius: 12px;
  margin-bottom: 0.7rem;
  overflow: hidden;
}
.item-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.75rem 0.85rem;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--color-text);
  text-align: left;
}
.kind {
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.15rem 0.45rem;
  border-radius: 6px;
}
.k-loan {
  background: hsla(215, 90%, 55%, 0.15);
  color: hsla(215, 90%, 55%, 1);
}
.k-card {
  background: hsla(280, 60%, 55%, 0.15);
  color: hsla(280, 60%, 60%, 1);
}
.info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.info .name {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.info .sub {
  font-size: 0.78rem;
  opacity: 0.6;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.amt {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
}
.amt-now {
  font-weight: 700;
  font-size: 0.92rem;
}
.amt-rem {
  font-size: 0.75rem;
  opacity: 0.6;
}
.chev {
  flex: 0 0 auto;
  opacity: 0.5;
  font-size: 0.8rem;
}
.sched-wrap {
  padding: 0 0.5rem 0.6rem;
  overflow-x: auto;
}
.partial-note {
  font-size: 0.8rem;
  opacity: 0.75;
  padding: 0.4rem 0.4rem 0.6rem;
}
.sched {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.sched th,
.sched td {
  padding: 0.45rem 0.5rem;
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
.sched th {
  font-size: 0.76rem;
  opacity: 0.6;
  text-align: left;
  font-weight: 600;
}
.sched .num {
  text-align: right;
}
.sched td.strong {
  font-weight: 700;
}
.sched td.muted {
  opacity: 0.6;
}
.sched tr.current td {
  background: hsla(160, 100%, 37%, 0.08);
}
.empty-state {
  text-align: center;
  padding: 2.5rem 1rem;
  opacity: 0.85;
}
.empty-emoji {
  font-size: 2rem;
}
.empty-title {
  font-weight: 700;
  margin-top: 0.4rem;
}
.empty-desc {
  font-size: 0.85rem;
  opacity: 0.7;
  margin-top: 0.2rem;
}
@media (max-width: 560px) {
  .summary {
    grid-template-columns: 1fr;
  }
}
</style>
