<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import { accountApi } from '@/api/accountApi'
import IconBtn from '@/components/ui/IconBtn.vue'
import AppModal from '@/components/ui/AppModal.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 tradeEditId = ref(null) // null=추가, 값=해당 매매 수정
// inputMode: 'PRICE'(수량×단가) | 'AMOUNT'(수량+총금액 → 단가 자동계산, 소수점 매수용)
const tForm = reactive({ tradeType: 'BUY', tradeDate: '', quantity: null, price: null, amount: null, fee: null, inputMode: 'PRICE' })
const tSubmitting = ref(false)
const tError = ref(null)

const tradeQty = computed(() => Number(tForm.quantity) || 0)
// 실제 저장에 쓰는 단가(원/주). 금액 모드면 총금액÷수량을 반올림.
const tradePrice = computed(() => {
  if (tForm.inputMode === 'AMOUNT') {
    return tradeQty.value > 0 ? Math.round((Number(tForm.amount) || 0) / tradeQty.value) : 0
  }
  return Number(tForm.price) || 0
})
// 표시용 총 거래금액
const tradeAmount = computed(() => {
  if (tForm.inputMode === 'AMOUNT') return Number(tForm.amount) || 0
  return Math.round(tradeQty.value * (Number(tForm.price) || 0))
})

// 매매이력 드롭다운 — 인라인은 최근 N건, 전체는 모달
const openTradesId = ref(null)
const tradesByHolding = reactive({})
const RECENT_N = 5
const allTradesModal = ref(false)
const allTradesHolding = ref(null)
function tradesOf(h) {
  return tradesByHolding[h.id] || []
}
function recentTrades(h) {
  return [...tradesOf(h)].reverse().slice(0, RECENT_N) // 최신순 N건
}
const allTradesList = computed(() => {
  const id = allTradesHolding.value?.id
  return id ? [...(tradesByHolding[id] || [])].reverse() : []
})
function openAllTrades(h) {
  allTradesHolding.value = h
  allTradesModal.value = true
}

function won(n) {
  return (n ?? 0).toLocaleString('ko-KR')
}
// 수량(소수점 매매 지원): 최대 6자리, 불필요한 0 제거
function shares(n) {
  return Number(n ?? 0).toLocaleString('ko-KR', { maximumFractionDigits: 6 })
}
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')}`
}
// 날짜 input(yyyy-mm-dd) 용 변환 (수정 진입 시 프리필)
function toDateInput(v) {
  if (!v) return todayStr()
  const d = new Date(v)
  if (Number.isNaN(d.getTime())) return String(v).slice(0, 10)
  return `${d.getFullYear()}-${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
  }
}

// 종목코드로 현재가 시세 일괄 갱신
const refreshing = ref(false)
const refreshMsg = ref('')
async function refreshPrices() {
  if (refreshing.value) return
  refreshing.value = true
  refreshMsg.value = ''
  try {
    holdings.value = await accountApi.refreshPrices(props.walletId)
    emit('changed')
    const noTicker = holdings.value.filter((h) => !h.ticker).length
    refreshMsg.value = noTicker
      ? `시세 갱신 완료 · 종목코드 없는 ${noTicker}개는 제외`
      : '시세 갱신 완료'
  } catch {
    refreshMsg.value = '시세 갱신에 실패했습니다.'
  } finally {
    refreshing.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
  tradeEditId.value = null
  Object.assign(tForm, { tradeType: type, tradeDate: todayStr(), quantity: null, price: h.currentPrice ?? null, amount: null, fee: null, inputMode: 'PRICE' })
  tError.value = null
  tradeModal.value = true
}
// 기존 매매 수정 진입 — 단가 모드로 프리필
function openEditTrade(h, t) {
  tradeHolding.value = h
  tradeEditId.value = t.id
  Object.assign(tForm, {
    tradeType: t.tradeType,
    tradeDate: toDateInput(t.tradeDate),
    quantity: Number(t.quantity),
    price: t.price,
    amount: null,
    fee: t.fee || null,
    inputMode: 'PRICE',
  })
  tError.value = null
  tradeModal.value = true
}
async function submitTrade() {
  tError.value = null
  if (!tForm.quantity || tForm.quantity <= 0) {
    tError.value = '수량을 입력하세요.'
    return
  }
  if (tForm.inputMode === 'AMOUNT') {
    if (!tForm.amount || tForm.amount <= 0) {
      tError.value = '금액을 입력하세요.'
      return
    }
  } else 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: tradePrice.value,
    fee: tForm.fee ? Number(tForm.fee) : 0,
  }
  try {
    if (tradeEditId.value) {
      await accountApi.updateTrade(tradeEditId.value, payload)
    } else {
      await accountApi.addTrade(tradeHolding.value.id, payload)
    }
    tradeModal.value = false
    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(async () => {
  await load()
  // 투자 계좌를 펼치면 종목코드 있는 종목 현재가를 자동으로 시세 갱신
  if (holdings.value.some((h) => h.ticker)) {
    refreshPrices()
  }
})
</script>

<template>
  <div class="portfolio">
    <div class="pf-head">
      <span class="pf-title">보유 종목</span>
      <div class="pf-head-btns">
        <button
          type="button" class="refresh-btn"
          :disabled="refreshing || !holdings.length"
          @click="refreshPrices"
        >{{ refreshing ? '갱신 중…' : '↻ 시세 갱신' }}</button>
        <IconBtn icon="plus" title="종목 추가" variant="primary" size="sm" @click="openAddHolding" />
      </div>
    </div>
    <p v-if="refreshMsg" class="pf-refresh-msg">{{ refreshMsg }}</p>

    <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">
                <div class="h-sub-qty">{{ shares(h.quantity) }}주</div>
                <div class="h-sub-price">
                  평단 {{ won(h.avgPrice) }}
                  <template v-if="h.currentPrice != null"> · 현재가 {{ won(h.currentPrice) }}</template>
                  <span v-else class="noprice"> · 현재가 미입력</span>
                </div>
              </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>

        <!-- 매매이력 (최근 N건, 전체는 모달) -->
        <div v-if="openTradesId === h.id" class="trade-drop">
          <template v-if="tradesOf(h).length">
            <ul class="trade-list">
              <li v-for="t in recentTrades(h)" :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">{{ shares(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 icon="edit" title="매매 수정" size="sm" @click="openEditTrade(h, t)" />
                <IconBtn class="t-del" icon="trash" title="매매 삭제" variant="danger" size="sm" @click="removeTrade(t, h.id)" />
              </li>
            </ul>
            <button v-if="tradesOf(h).length > RECENT_N" type="button" class="more-trades" @click="openAllTrades(h)">
              전체 {{ tradesOf(h).length }}건 보기
            </button>
          </template>
          <p v-else class="pf-msg sm">매매 내역이 없습니다.</p>
        </div>
      </li>
    </ul>

    <!-- 종목 추가/수정 모달 -->
    <AppModal v-model="holdingModal" :title="`종목 ${holdingEditId ? '수정' : '추가'}`">
      <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 class="pf-form-hint">종목코드(6자리)를 입력하면 <b>시세 갱신</b> 버튼으로 현재가를 자동으로 불러옵니다.</p>
        <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>
    </AppModal>

    <!-- 매매 모달 (매매내역 위에 표시되도록 z-index 높게) -->
    <AppModal v-model="tradeModal" :title="`${tradeHolding?.name} ${tradeEditId ? '매매 수정' : (tForm.tradeType === 'SELL' ? '매도' : '매수')}`" :zIndex="1100">
      <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="0" step="any" inputmode="decimal" placeholder="예: 0.5 / 1.25 (소수점 가능)" :disabled="tSubmitting" /></label>
        <label>입력 방식
          <select v-model="tForm.inputMode" :disabled="tSubmitting">
            <option value="PRICE">단가로 입력</option>
            <option value="AMOUNT">금액으로 입력 (소수점 매수)</option>
          </select>
        </label>
        <label v-if="tForm.inputMode === 'PRICE'">단가(원)
          <input v-model.number="tForm.price" type="number" min="0" :disabled="tSubmitting" />
          <small v-if="tradeQty > 0 && tForm.price" class="pf-hint">총 약 {{ won(tradeAmount) }}원</small>
        </label>
        <label v-else>금액(총, 원)
          <input v-model.number="tForm.amount" type="number" min="0" placeholder="이 금액어치 매매" :disabled="tSubmitting" />
          <small v-if="tradeQty > 0 && tForm.amount" class="pf-hint">단가 약 {{ won(tradePrice) }}원</small>
        </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">보유 {{ shares(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="tradeEditId ? '수정' : '등록'" variant="primary" type="submit" :disabled="tSubmitting" />
        </div>
      </form>
    </AppModal>

    <!-- 전체 매매내역 모달 -->
    <AppModal v-model="allTradesModal" :title="`${allTradesHolding?.name} 매매내역`" :zIndex="1050">
      <ul class="trade-list modal-trades">
        <li v-for="t in allTradesList" :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">{{ shares(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 icon="edit" title="매매 수정" size="sm" @click="openEditTrade(allTradesHolding, t)" />
          <IconBtn class="t-del" icon="trash" title="매매 삭제" variant="danger" size="sm" @click="removeTrade(t, allTradesHolding.id)" />
        </li>
      </ul>
    </AppModal>
  </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-head-btns {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.refresh-btn {
  padding: 0.25rem 0.6rem;
  font-size: 0.78rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
  cursor: pointer;
  white-space: nowrap;
}
.refresh-btn:disabled {
  opacity: 0.5;
  cursor: default;
}
.pf-refresh-msg {
  font-size: 0.78rem;
  opacity: 0.7;
  margin: 0 0 0.4rem;
}
.pf-form-hint {
  font-size: 0.76rem;
  opacity: 0.6;
  margin: -0.2rem 0 0;
}
.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;
}
.h-sub-qty {
  font-weight: 600;
}
.h-sub-price {
  margin-top: 1px;
}
.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;
}
.more-trades {
  margin-top: 0.2rem;
  padding: 0.25rem 0.6rem;
  font-size: 0.76rem;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-background-soft);
  color: var(--color-text);
  cursor: pointer;
}
.more-trades:hover {
  border-color: var(--color-border-hover);
}
.modal-trades {
  margin-top: 0.5rem;
}
.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;
}

.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);
}
/* ===== 모바일: 매매이력 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>
