<template>
  <ScorecardDashboardPage title="포트폴리오 리스크 대시보드" subtitle="실시간 리스크 지표, 스트레스 시나리오, 알림을 확인합니다." :state="state" :warning="error ?? undefined" @retry="fetchDashboard">
    <template #actions>
      <div v-if="dashboard" class="health-score">
        <span class="score-label">포트폴리오 건전성</span>
        <div class="score-bar"><div class="score-fill" :style="{ width: dashboard.healthScore + '%' }" /></div>
        <span class="score-value">{{ dashboard.healthScore }}/100</span>
      </div>
    </template>

    <template v-if="dashboard" #kpis>
      <div class="metric">
        <span class="label">VAR (95%)</span>
        <span class="value">{{ formatCurrency(dashboard.riskMetrics.var95, 'USD') }}</span>
        <span class="note">{{ formatPercent(dashboard.riskMetrics.var95 / dashboard.portfolio.totalValue, 1) }}</span>
      </div>
      <div class="metric">
        <span class="label">Sharpe Ratio</span>
        <span class="value">{{ dashboard.riskMetrics.sharpeRatio.toFixed(2) }}</span>
        <span class="note">252일 이동</span>
      </div>
      <div class="metric">
        <span class="label">Sortino Ratio</span>
        <span class="value">{{ dashboard.riskMetrics.sortinoRatio.toFixed(2) }}</span>
        <span class="note">하방 리스크 중심</span>
      </div>
      <div class="metric">
        <span class="label">변동성</span>
        <span class="value">{{ formatPercent(dashboard.riskMetrics.volatilityPercent / 100, 1) }}</span>
        <span class="note">연환산</span>
      </div>
      <div class="metric">
        <span class="label">상위 5종목 비중</span>
        <span class="value">{{ formatPercent(dashboard.riskMetrics.topFivePercent / 100, 1) }}</span>
        <KsStatusTag :value="topFiveLabel" :severity="topFiveSeverity" />
      </div>
      <div class="metric">
        <span class="label">최대 보유 비중</span>
        <span class="value">{{ formatPercent(dashboard.riskMetrics.maxPositionPercent / 100, 1) }}</span>
        <span class="note">{{ dashboard.portfolio.positions[0]?.symbol ?? 'N/A' }}</span>
      </div>
    </template>

    <template v-if="dashboard" #primary>
      <h2>포트폴리오 구성</h2>
      <dl class="portfolio-summary">
        <div class="summary-item"><dt>총 평가액</dt><dd>{{ formatCurrency(dashboard.portfolio.totalValue, 'USD') }}</dd></div>
        <div class="summary-item"><dt>보유 종목 수</dt><dd>{{ formatQuantity(dashboard.portfolio.positions.length, 0) }}</dd></div>
      </dl>
      <DataGridShell :rows="dashboard.portfolio.positions.slice(0, 5)" :columns="positionColumns" empty-message="보유 종목이 없습니다." />
    </template>

    <template v-if="dashboard" #secondary>
      <h2>스트레스 테스트 시나리오</h2>
      <div class="scenarios">
        <button
          v-for="stress in dashboard.stressResults"
          :key="stress.scenario"
          type="button"
          class="scenario"
          @click="runStressTest(stress.scenario)"
        >
          <span class="name">{{ scenarioLabel(stress.scenario) }}</span>
          <span class="impact">{{ formatPercent(stress.portfolioLossPercent / 100, 1) }} 포트폴리오</span>
          <KsStatusTag :value="Math.abs(stress.portfolioLossPercent) > 15 ? '심각' : '보통'" :severity="Math.abs(stress.portfolioLossPercent) > 15 ? 'danger' : 'warning'" />
        </button>
      </div>

      <div v-if="stressResult" class="stress-result">
        <h3>결과: {{ stressResult.scenario }}</h3>
        <div class="result-row"><span>포트폴리오 손실</span><span :class="['value', stressResult.loss < 0 ? 'loss' : 'gain']">{{ formatPercent(stressResult.loss / 100, 2) }}</span></div>
        <div class="result-row"><span>스트레스 VAR</span><span class="value">{{ formatCurrency(stressResult.stressedVar, 'USD') }}</span></div>
      </div>
    </template>

    <template #alerts>
      <h2>활성 리스크 알림</h2>
      <div v-if="activeAlerts.length > 0" class="alerts-list">
        <div v-for="alert in activeAlerts" :key="alert.id" class="alert">
          <div class="alert-header">
            <span class="threshold">{{ alert.threshold }}</span>
            <KsStatusTag :value="alert.severity" :severity="alertSeverity(alert.severity)" />
          </div>
          <div class="alert-details">
            <span class="current">{{ formatPercent(alert.current / 100, 1) }}</span>
            <span class="message">{{ alert.message }}</span>
          </div>
        </div>
      </div>
      <p v-else class="no-alerts">현재 활성 알림이 없습니다 — 포트폴리오가 안전 범위 내에 있습니다.</p>
    </template>

    <template v-if="dashboard?.riskInsights.length" #metricDefinitions>
      <h2>리스크 인사이트</h2>
      <ul class="insights-list">
        <li v-for="(insight, idx) in dashboard.riskInsights" :key="idx">{{ insight }}</li>
      </ul>
    </template>
  </ScorecardDashboardPage>
</template>

<script setup lang="ts">
import { computed, ref, onMounted } from 'vue'
import ScorecardDashboardPage from '../../../shared/ui/screen-types/v2/ScorecardDashboardPage.vue'
import DataGridShell from '../../../shared/ui/DataGridShell.vue'
import { KsStatusTag } from '../../../shared/ui/components'
import type { UiGridColumn, UiSeverity } from '../../../shared/ui/adapter/contracts'
import type { StandardScreenState } from '../../../shared/ui/contracts/screenContract'
import { formatCurrency, formatPercent, formatQuantity } from '../../../shared/formatters/financial'

interface StressResult {
  scenario: string
  loss: number
  stressedVar: number
}

interface Alert {
  id: string
  threshold: string
  current: number
  severity: string
  message: string
}

interface DashboardData {
  portfolio: {
    totalValue: number
    positions: Array<{
      symbol: string
      quantity: number
      marketPrice: number
      marketValue: number
      weightPercent: number
    }>
  }
  riskMetrics: {
    var95: number
    sharpeRatio: number
    sortinoRatio: number
    volatilityPercent: number
    topFivePercent: number
    maxPositionPercent: number
  }
  stressResults: Array<{
    scenario: string
    portfolioLossPercent: number
    stressedVar: number
  }>
  activeAlerts: Array<{
    alertId: string
    threshold: string
    currentValue: number
    severity: string
    message: string
  }>
  healthScore: number
  riskInsights: string[]
  lastUpdate: string
}

const loading = ref(false)
const error = ref<string | null>(null)
const stressResult = ref<StressResult | null>(null)
const dashboard = ref<DashboardData | null>(null)
const portfolioId = ref('550e8400-e29b-41d4-a716-446655440001')

const activeAlerts = ref<Alert[]>([
  {
    id: '1',
    threshold: '집중도(상위 5종목)',
    current: 52.3,
    severity: 'Warning',
    message: '상위 5종목 비중 52.3% (임계값 60%)',
  },
])

const state = computed<StandardScreenState>(() => loading.value ? 'LOADING' : error.value ? 'WARN' : 'READY')

const positionColumns: UiGridColumn[] = [
  { field: 'symbol', header: '종목코드' },
  { field: 'quantity', header: '수량', formatter: value => formatQuantity(value as number, 0) },
  { field: 'marketPrice', header: '현재가', formatter: value => formatCurrency(value as number, 'USD') },
  { field: 'marketValue', header: '평가금액', formatter: value => formatCurrency(value as number, 'USD') },
  { field: 'weightPercent', header: '비중', formatter: value => formatPercent((value as number) / 100, 1) }
]

const topFiveLabel = computed(() => {
  const value = dashboard.value?.riskMetrics.topFivePercent ?? 0
  return value > 70 ? '높음' : value > 50 ? '중간' : '낮음'
})
const topFiveSeverity = computed<UiSeverity>(() => {
  const value = dashboard.value?.riskMetrics.topFivePercent ?? 0
  return value > 60 ? 'danger' : 'warning'
})

function scenarioLabel(scenario: string): string {
  return scenario.charAt(0).toUpperCase() + scenario.slice(1)
}

function alertSeverity(severity: string): UiSeverity {
  const normalized = severity.toLowerCase()
  if (normalized === 'critical') return 'danger'
  if (normalized === 'warning') return 'warning'
  return 'info'
}

onMounted(async () => {
  await fetchDashboard()
})

const fetchDashboard = async () => {
  loading.value = true
  error.value = null
  try {
    const response = await fetch(`/api/dashboard/risk?portfolioId=${portfolioId.value}`)
    if (response.ok) {
      dashboard.value = await response.json()
      activeAlerts.value = dashboard.value?.activeAlerts?.map(a => ({
        id: a.alertId,
        threshold: a.threshold,
        current: a.currentValue,
        severity: a.severity,
        message: a.message,
      })) || []
    } else {
      error.value = '대시보드를 불러오지 못했습니다.'
    }
  } catch (e) {
    error.value = e instanceof Error ? e.message : '알 수 없는 오류'
  } finally {
    loading.value = false
  }
}

const runStressTest = async (scenario: string) => {
  const result = dashboard.value?.stressResults.find(s => s.scenario.toLowerCase() === scenario.toLowerCase())

  if (result) {
    stressResult.value = {
      scenario: scenarioLabel(scenario),
      loss: result.portfolioLossPercent,
      stressedVar: result.stressedVar,
    }
  }
}
</script>

<style scoped>
.health-score { display: flex; gap: var(--ks-space-3); align-items: center; min-width: 20rem; }
.score-label { font-weight: 600; white-space: nowrap; }
.score-bar { flex: 1; height: 1.5rem; background: var(--ks-color-neutral-200); border-radius: var(--ks-radius-lg); overflow: hidden; }
.score-fill { height: 100%; background: linear-gradient(90deg, var(--ks-color-danger), var(--ks-color-warning), var(--ks-color-success)); }
.score-value { font-weight: 600; white-space: nowrap; }

.metric { display: flex; flex-direction: column; gap: var(--ks-space-1); padding: var(--ks-space-3); background: var(--ks-color-canvas); border-radius: var(--ks-radius-sm); text-align: center; }
.metric .label { font-size: var(--ks-font-caption); color: var(--ks-color-text-muted); font-weight: 500; }
.metric .value { font-size: var(--ks-font-page); font-weight: 600; }
.metric .note { font-size: var(--ks-font-caption); color: var(--ks-color-text-muted); }

.portfolio-summary { display: flex; gap: var(--ks-space-6); margin: 0 0 var(--ks-space-3); padding: var(--ks-space-3); background: var(--ks-color-canvas); border-radius: var(--ks-radius-sm); }
.summary-item { display: flex; flex-direction: column; gap: var(--ks-space-1); }
.summary-item dt { font-size: var(--ks-font-caption); color: var(--ks-color-text-muted); font-weight: 500; }
.summary-item dd { margin: 0; font-size: var(--ks-font-page); font-weight: 600; }

.scenarios { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--ks-space-3); margin-bottom: var(--ks-space-4); }
.scenario { display: flex; flex-direction: column; gap: var(--ks-space-1); padding: var(--ks-space-3); border: 1px solid var(--ks-color-border); border-radius: var(--ks-radius-sm); background: var(--ks-color-surface); text-align: left; cursor: pointer; }
.scenario:hover { border-color: var(--ks-color-action); }
.scenario .name { font-weight: 600; font-size: var(--ks-font-body); }
.scenario .impact { font-size: var(--ks-font-caption); color: var(--ks-color-text-muted); }
.stress-result { padding: var(--ks-space-3); background: color-mix(in srgb, var(--ks-color-warning) 12%, var(--ks-color-surface)); border-radius: var(--ks-radius-sm); }
.result-row { display: flex; justify-content: space-between; padding: var(--ks-space-1) 0; }
.result-row .value.loss { color: var(--ks-color-danger); font-weight: 600; }
.result-row .value.gain { color: var(--ks-color-success); font-weight: 600; }

.alerts-list { display: flex; flex-direction: column; gap: var(--ks-space-2); }
.alert { padding: var(--ks-space-3); border-radius: var(--ks-radius-sm); background: var(--ks-color-canvas); }
.alert-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--ks-space-2); }
.alert-header .threshold { font-weight: 600; }
.alert-details { display: flex; justify-content: space-between; font-size: var(--ks-font-body); }
.alert-details .current { font-weight: 600; }
.alert-details .message { color: var(--ks-color-text-muted); }
.no-alerts { padding: var(--ks-space-4); text-align: center; color: var(--ks-color-success); font-weight: 500; }

.insights-list { list-style: none; margin: 0; padding: 0; }
.insights-list li { padding: var(--ks-space-2) 0; border-bottom: 1px solid var(--ks-color-border); }
.insights-list li:last-child { border-bottom: 0; }
</style>
