<script setup>
import { onMounted, reactive, ref } from 'vue'
import { accountApi } from '@/api/accountApi'
import IconBtn from '@/components/ui/IconBtn.vue'

const props = defineProps({ walletId: { type: [Number, String], required: true } })
const emit = defineEmits(['changed'])

const holdings = ref([])
const loading = ref(false)

// 종목 추가/수정 모달
const holdingModal = ref(false)
const holdingEditId = ref(null)
const hForm = reactive({ name: '', ticker: '', currentPrice: null })
const hSubmitting = ref(false)
const hError = ref(null)

// 매매 모달
const tradeModal = ref(false)
const tradeHolding = ref(null)
const tForm = reactive({ tradeType: 'BUY', tradeDate: '', quantity: null, price: null, fee: null })
const tSubmitting = ref(false)
const tError = ref(null)

// 매매이력 드롭다운
const openTradesId = ref(null)
const tradesByHolding = reactive({})

function won(n) {
  return (n ?? 0).toLocaleString('ko-KR')
}
function todayStr() {
  const d = new Date()
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}
function tDate(v) {
  if (!v) return '-'
  const d = new Date(v)
  return Number.isNaN(d.getTime()) ? v : `${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')}`
}

async function load() {
  loading.value = true
  try {
    holdings.value = await accountApi.investHoldings(props.walletId)
  } catch {
    holdings.value = []
  } finally {
    loading.value = false
  }
}

/* ===== 종목 ===== */
function openAddHolding() {
  holdingEditId.value = null
  Object.assign(hForm, { name: '', ticker: '', currentPrice: null })
  hError.value = null
  holdingModal.value = true
}
function openEditHolding(h) {
  holdingEditId.value = h.id
  Object.assign(hForm, { name: h.name, ticker: h.ticker || '', currentPrice: h.currentPrice ?? null })
  hError.value = null
  holdingModal.value = true
}
async function submitHolding() {
  hError.value = null
  if (!hForm.name.trim()) {
    hError.value = '종목명을 입력하세요.'
    return
  }
  hSubmitting.value = true
  const payload = {
    walletId: Number(props.walletId),
    name: hForm.name.trim(),
    ticker: hForm.ticker || null,
    currentPrice: hForm.currentPrice !== '' && hForm.currentPrice != null ? Number(hForm.currentPrice) : null,
  }
  try {
    if (holdingEditId.value) await accountApi.updateHolding(holdingEditId.value, payload)
    else await accountApi.createHolding(payload)
    holdingModal.value = false
    await load()
    emit('changed')
  } catch (e) {
    hError.value = e.response?.data?.message || '저장에 실패했습니다.'
  } finally {
    hSubmitting.value = false
  }
}
async function removeHolding(h) {
  if (!confirm(`'${h.name}' 종목과 매매이력을 모두 삭제할까요?`)) return
  try {
    await accountApi.removeHolding(h.id)
    await load()
    emit('changed')
  } catch (e) {
    alert(e.response?.data?.message || '삭제에 실패했습니다.')
  }
}

/* ===== 매매 ===== */
function openTrade(h, type) {
  tradeHolding.value = h
  Object.assign(tForm, { tradeType: type, tradeDate: todayStr(), quantity: null, price: h.currentPrice ?? null, fee: null })
  tError.value = null
  tradeModal.value = true
}
async function submitTrade() {
  tError.value = null
  if (!tForm.quantity || tForm.quantity <= 0) {
    tError.value = '수량을 입력하세요.'
    return
  }
  if (tForm.price == null || tForm.price < 0) {
    tError.value = '단가를 입력하세요.'
    return
  }
  tSubmitting.value = true
  const payload = {
    tradeType: tForm.tradeType,
    tradeDate: tForm.tradeDate,
    quantity: Number(tForm.quantity),
    price: Number(tForm.price),
    fee: tForm.fee ? Number(tForm.fee) : 0,
  }
  try {
    await accountApi.addTrade(tradeHolding.value.id, payload)
    tradeModal.value = false
    if (openTradesId.value === tradeHolding.value.id) await loadTrades(tradeHolding.value.id)
    await load()
    emit('changed')
  } catch (e) {
    tError.value = e.response?.data?.message || '저장에 실패했습니다.'
  } finally {
    tSubmitting.value = false
  }
}

async function loadTrades(holdingId) {
  try {
    tradesByHolding[holdingId] = await accountApi.holdingTrades(holdingId)
  } catch {
    tradesByHolding[holdingId] = []
  }
}
async function toggleTrades(h) {
  if (openTradesId.value === h.id) {
    openTradesId.value = null
    return
  }
  openTradesId.value = h.id
  await loadTrades(h.id)
}
async function removeTrade(t, holdingId) {
  if (!confirm('이 매매 내역을 삭제할까요?')) return
  try {
    await accountApi.removeTrade(t.id)
    await loadTrades(holdingId)
    await load()
    emit('changed')
  } catch (e) {
    alert(e.response?.data?.message || '삭제에 실패했습니다.')
  }
}

onMounted(load)
</script>

<template>
  <div class="portfolio">
    <div class="pf-head">
      <span class="pf-title">보유 종목</span>
      <IconBtn icon="plus" title="종목 추가" variant="primary" size="sm" @click="openAddHolding" />
    </div>

    <p v-if="loading" class="pf-msg">불러오는 중...</p>
    <p v-else-if="!holdings.length" class="pf-msg">보유 종목이 없습니다. 종목을 추가하고 매수를 기록하세요.</p>

    <ul v-else class="hold-list">
      <li v-for="h in holdings" :key="h.id" class="hold-item">
        <div class="hold-row">
          <div class="h-info" @click="toggleTrades(h)">
            <span class="chev">{{ openTradesId === h.id ? '▾' : '▸' }}</span>
            <div>
              <div class="h-name">{{ h.name }}<span v-if="h.ticker" class="h-ticker">{{ h.ticker }}</span></div>
              <div class="h-sub">
                {{ won(h.quantity) }}주 · 평단 {{ won(h.avgPrice) }}
                <template v-if="h.currentPrice != null"> · 현재가 {{ won(h.currentPrice) }}</template>
                <span v-else class="noprice"> · 현재가 미입력</span>
              </div>
            </div>
          </div>
          <div class="h-val">
            <div class="h-eval">{{ won(h.evalValue) }}</div>
            <div class="h-gain" :class="h.evalGain < 0 ? 'neg' : 'pos'">
              {{ h.evalGain >= 0 ? '+' : '' }}{{ won(h.evalGain) }}<span v-if="h.returnPct != null"> ({{ h.returnPct }}%)</span>
            </div>
            <div v-if="h.realizedPL" class="h-realized">실현 {{ h.realizedPL >= 0 ? '+' : '' }}{{ won(h.realizedPL) }}</div>
          </div>
          <div class="h-actions">
            <IconBtn icon="plus" title="매수" variant="buy" size="sm" @click="openTrade(h, 'BUY')" />
            <IconBtn icon="minus" title="매도" variant="sell" size="sm" :disabled="h.quantity <= 0" @click="openTrade(h, 'SELL')" />
            <IconBtn icon="edit" title="현재가 수정" size="sm" @click="openEditHolding(h)" />
            <IconBtn icon="trash" title="삭제" variant="danger" size="sm" @click="removeHolding(h)" />
          </div>
        </div>

        <!-- 매매이력 -->
        <div v-if="openTradesId === h.id" class="trade-drop">
          <ul v-if="(tradesByHolding[h.id] || []).length" class="trade-list">
            <li v-for="t in tradesByHolding[h.id]" :key="t.id" class="trade-row">
              <span class="t-date">{{ tDate(t.tradeDate) }}</span>
              <span class="t-type" :class="t.tradeType === 'SELL' ? 'sell' : 'buy'">{{ t.tradeType === 'SELL' ? '매도' : '매수' }}</span>
              <span class="t-qty">{{ won(t.quantity) }}주 × {{ won(t.price) }}</span>
              <span class="t-fee" v-if="t.fee">수수료 {{ won(t.fee) }}</span>
              <span class="t-amt">{{ won(t.amount) }}</span>
              <IconBtn class="t-del" icon="trash" title="매매 삭제" variant="danger" size="sm" @click="removeTrade(t, h.id)" />
            </li>
          </ul>
          <p v-else class="pf-msg sm">매매 내역이 없습니다.</p>
        </div>
      </li>
    </ul>

    <!-- 종목 추가/수정 모달 -->
    <Teleport to="body">
      <Transition name="fade">
        <div v-if="holdingModal" class="modal-backdrop" @click.self="holdingModal = false">
          <div class="modal" role="dialog" aria-modal="true">
            <button class="close" type="button" @click="holdingModal = false">×</button>
            <h2>종목 {{ holdingEditId ? '수정' : '추가' }}</h2>
            <form class="pf-form" @submit.prevent="submitHolding">
              <label>종목명<input v-model="hForm.name" type="text" placeholder="예: 삼성전자" :disabled="hSubmitting" /></label>
              <label>종목코드<input v-model="hForm.ticker" type="text" placeholder="(선택) 예: 005930" :disabled="hSubmitting" /></label>
              <label>현재가<input v-model.number="hForm.currentPrice" type="number" min="0" placeholder="(수동 갱신)" :disabled="hSubmitting" /></label>
              <p v-if="hError" class="pf-msg err">{{ hError }}</p>
              <div class="pf-buttons">
                <IconBtn icon="close" title="취소" @click="holdingModal = false" />
                <IconBtn icon="save" title="저장" variant="primary" type="submit" :disabled="hSubmitting" />
              </div>
            </form>
          </div>
        </div>
      </Transition>
    </Teleport>

    <!-- 매매 모달 -->
    <Teleport to="body">
      <Transition name="fade">
        <div v-if="tradeModal" class="modal-backdrop" @click.self="tradeModal = false">
          <div class="modal" role="dialog" aria-modal="true">
            <button class="close" type="button" @click="tradeModal = false">×</button>
            <h2>{{ tradeHolding?.name }} {{ tForm.tradeType === 'SELL' ? '매도' : '매수' }}</h2>
            <form class="pf-form" @submit.prevent="submitTrade">
              <label>구분
                <select v-model="tForm.tradeType" :disabled="tSubmitting">
                  <option value="BUY">매수</option>
                  <option value="SELL" :disabled="(tradeHolding?.quantity || 0) <= 0">매도</option>
                </select>
              </label>
              <label>거래일<input v-model="tForm.tradeDate" type="date" :disabled="tSubmitting" /></label>
              <label>수량(주)<input v-model.number="tForm.quantity" type="number" min="1" :disabled="tSubmitting" /></label>
              <label>단가(원)<input v-model.number="tForm.price" type="number" min="0" :disabled="tSubmitting" /></label>
              <label>수수료/세금<input v-model.number="tForm.fee" type="number" min="0" placeholder="(선택)" :disabled="tSubmitting" /></label>
              <p v-if="tForm.tradeType === 'SELL'" class="pf-hint">보유 {{ won(tradeHolding?.quantity) }}주 · 평단 {{ won(tradeHolding?.avgPrice) }}</p>
              <p v-if="tError" class="pf-msg err">{{ tError }}</p>
              <div class="pf-buttons">
                <IconBtn icon="close" title="취소" @click="tradeModal = false" />
                <IconBtn icon="save" title="등록" variant="primary" type="submit" :disabled="tSubmitting" />
              </div>
            </form>
          </div>
        </div>
      </Transition>
    </Teleport>
  </div>
</template>

<style scoped>
.portfolio {
  padding: 0.25rem 0 0.5rem;
}
.pf-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}
.pf-title {
  font-size: 0.85rem;
  font-weight: 600;
  opacity: 0.8;
}
.pf-add {
  padding: 0.25rem 0.6rem;
  font-size: 0.8rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
  cursor: pointer;
}
.pf-msg {
  font-size: 0.85rem;
  opacity: 0.65;
  padding: 0.5rem 0;
}
.pf-msg.sm {
  padding: 0.3rem 0;
}
.pf-msg.err {
  color: #c0392b;
  opacity: 1;
}
.hold-list {
  list-style: none;
}
.hold-item {
  border-top: 1px dashed var(--color-border);
}
.hold-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0;
  flex-wrap: wrap;
}
.h-info {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1;
  min-width: 9rem;
  cursor: pointer;
}
.chev {
  opacity: 0.5;
  font-size: 0.75rem;
}
.h-name {
  font-weight: 600;
  font-size: 0.9rem;
}
.h-ticker {
  margin-left: 0.35rem;
  font-size: 0.72rem;
  opacity: 0.6;
}
.h-sub {
  font-size: 0.76rem;
  opacity: 0.7;
}
.noprice {
  color: #e67e22;
}
.h-val {
  text-align: right;
  white-space: nowrap;
}
.h-eval {
  font-weight: 700;
  font-size: 0.9rem;
}
.h-gain {
  font-size: 0.76rem;
  font-weight: 600;
}
.h-gain.pos {
  color: #2e7d32;
}
.h-gain.neg {
  color: #c0392b;
}
.h-realized {
  font-size: 0.7rem;
  opacity: 0.7;
}
.h-actions {
  display: flex;
  gap: 0.25rem;
}
.h-actions button {
  padding: 0.18rem 0.45rem;
  font-size: 0.76rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
  cursor: pointer;
}
.h-actions button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.h-actions .buy {
  border-color: #2e7d32;
  color: #2e7d32;
}
.h-actions .sell {
  border-color: #c0392b;
  color: #c0392b;
}
.h-actions .danger {
  border-color: #c0392b;
  color: #c0392b;
}
.trade-drop {
  padding: 0.1rem 0 0.5rem 1.4rem;
}
.trade-list {
  list-style: none;
}
.trade-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0;
  font-size: 0.78rem;
}
.t-date {
  opacity: 0.7;
  width: 3rem;
}
.t-type {
  font-weight: 600;
}
.t-type.buy {
  color: #2e7d32;
}
.t-type.sell {
  color: #c0392b;
}
.t-qty {
  flex: 1;
}
.t-fee {
  opacity: 0.6;
  font-size: 0.72rem;
}
.t-amt {
  font-weight: 600;
}
.t-del {
  border: 0;
  background: transparent;
  color: #c0392b;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
}

/* 모달 (계좌 관리와 동일 톤) */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.5);
  padding: 1rem;
}
.modal {
  position: relative;
  width: 100%;
  max-width: 340px;
  padding: 1.75rem 1.5rem 1.5rem;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
}
.modal .close {
  position: absolute;
  top: 0.5rem;
  right: 0.6rem;
  width: 2rem;
  height: 2rem;
  border: 0;
  background: transparent;
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}
.modal h2 {
  margin-bottom: 1rem;
  font-size: 1.1rem;
  text-align: center;
}
.pf-form {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.pf-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
}
.pf-form input,
.pf-form select {
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
}
.pf-hint {
  font-size: 0.78rem;
  opacity: 0.7;
}
.pf-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.pf-buttons button {
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
  cursor: pointer;
}
.pf-buttons .primary {
  border-color: hsla(160, 100%, 37%, 1);
  color: hsla(160, 100%, 37%, 1);
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.18s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* ===== 모바일: 매매이력 2줄, 글자 세로쪼개짐 방지 ===== */
@media (max-width: 768px) {
  .hold-row {
    column-gap: 0.4rem;
  }
  .h-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  .trade-drop {
    padding-left: 0.8rem;
  }
  .trade-row {
    flex-wrap: wrap;
    column-gap: 0.4rem;
    row-gap: 0.1rem;
  }
  .t-date,
  .t-type,
  .t-qty,
  .t-fee,
  .t-amt {
    white-space: nowrap;
  }
  .t-date {
    order: 0;
    width: auto;
  }
  .t-type {
    order: 1;
  }
  .t-amt {
    order: 2;
    margin-left: auto;
  }
  .t-del {
    order: 3;
  }
  .t-qty {
    order: 4;
    flex: 0 1 auto;
  }
  .t-fee {
    order: 5;
  }
}
</style>
