<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { useChatStore } from '@/stores/chat'
import ChatMessage from '@/components/ChatMessage.vue'
import WeatherCard from '@/components/WeatherCard.vue'
import BriefingSetupWizard from '@/components/BriefingSetupWizard.vue'
import {
  getBriefingConfig,
  getBriefingConversations,
  getBriefingToday,
  getBriefingConvMessages,
  triggerBriefingSlot,
  postRssReaction,
  deleteRssReaction,
  type BriefingConversation,
  type BriefingMessage,
} from '@/api/client'
import type { Message } from '@/types/chat'

interface MessageMetadata {
  weather?: {
    location: string
    fetched_at: string
    current_temp: number
    condition: string
    today_high: number | null
    today_low: number | null
    yesterday_high: number | null
    yesterday_low: number | null
    forecast: { day: string; condition: string; high: number; low: number }[]
  } | null
  rss_item_ids?: number[]
}

const chatStore = useChatStore()

// Setup wizard
const showWizard = ref(false)
const wizardChecked = ref(false)

async function checkSetup() {
  const config = await getBriefingConfig()
  if (!config.enabled) showWizard.value = true
  wizardChecked.value = true
}

async function onWizardDone() {
  showWizard.value = false
  await loadAll()
}

// Conversations list for the dropdown
const conversations = ref<BriefingConversation[]>([])
const selectedConvId = ref<number | null>(null)
const todayConvId = ref<number | null>(null)

const isToday = computed(() => selectedConvId.value === todayConvId.value)

// Messages for selected conversation
const messages = ref<BriefingMessage[]>([])
const loadingMessages = ref(false)

async function loadAll() {
  const [convList, today] = await Promise.all([
    getBriefingConversations(),
    getBriefingToday().catch(() => null),
  ])
  conversations.value = convList
  if (today) {
    todayConvId.value = today.id
    // Ensure today is in the list
    if (!convList.find((c) => c.id === today.id)) {
      conversations.value = [
        { id: today.id, title: today.title ?? 'Today', briefing_date: null, message_count: 0, created_at: new Date().toISOString() },
        ...convList,
      ]
    }
    selectedConvId.value = today.id
    messages.value = today.messages
    // Load into chatStore so we can stream
    await chatStore.fetchConversation(today.id)
  }
}

watch(selectedConvId, async (id) => {
  if (!id) return
  if (id === todayConvId.value) {
    await chatStore.fetchConversation(id)
    messages.value = (chatStore.currentConversation?.messages ?? []) as unknown as BriefingMessage[]
    return
  }
  loadingMessages.value = true
  try {
    messages.value = await getBriefingConvMessages(id)
  } finally {
    loadingMessages.value = false
  }
})

// Refresh messages after streaming ends
watch(() => chatStore.streaming, async (streaming) => {
  if (!streaming && selectedConvId.value === todayConvId.value && todayConvId.value) {
    const today = await getBriefingToday().catch(() => null)
    if (today) messages.value = today.messages
  }
})

// Input
const input = ref('')
const sending = ref(false)

async function send() {
  const text = input.value.trim()
  if (!text || !todayConvId.value || chatStore.streaming || sending.value) return
  // Ensure today's conv is loaded in chatStore
  if (chatStore.currentConversation?.id !== todayConvId.value) {
    await chatStore.fetchConversation(todayConvId.value)
  }
  input.value = ''
  sending.value = true
  try {
    await chatStore.sendMessage(text)
  } finally {
    sending.value = false
  }
}

function onKeydown(e: KeyboardEvent) {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    send()
  }
}

// RSS reactions: map of rss_item_id -> 'up' | 'down' | null
const reactions = ref<Record<number, 'up' | 'down' | null>>({})

async function handleReaction(itemId: number, reaction: 'up' | 'down') {
  const current = reactions.value[itemId]
  reactions.value[itemId] = current === reaction ? null : reaction
  try {
    if (current === reaction) {
      await deleteRssReaction(itemId)
    } else {
      await postRssReaction(itemId, reaction)
    }
  } catch {
    reactions.value[itemId] = current ?? null
  }
}

function msgMetadata(msg: BriefingMessage): MessageMetadata | null {
  return (msg.metadata as MessageMetadata | null | undefined) ?? null
}

// Manual trigger
const triggering = ref(false)
async function triggerNow() {
  triggering.value = true
  try {
    await triggerBriefingSlot('compilation')
    // Reload
    await loadAll()
  } finally {
    triggering.value = false
  }
}

// Dropdown label
function convLabel(c: BriefingConversation): string {
  if (c.id === todayConvId.value) return 'Today'
  if (c.briefing_date) {
    const d = new Date(c.briefing_date)
    return d.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })
  }
  return c.title || 'Briefing'
}

// Convert BriefingMessage to Message for ChatMessage component
function toMsg(m: BriefingMessage): Message {
  return {
    id: m.id,
    conversation_id: -1,
    role: m.role,
    content: m.content,
    context_note_id: null,
    context_note_title: null,
    created_at: m.created_at,
  }
}

onMounted(async () => {
  await checkSetup()
  if (!showWizard.value) await loadAll()
})
</script>

<template>
  <div class="briefing-root">
    <!-- Setup wizard overlay -->
    <BriefingSetupWizard v-if="wizardChecked && showWizard" @done="onWizardDone" />

    <!-- Main view (shown after wizard check and only if not showing wizard) -->
    <div class="briefing-shell" v-if="wizardChecked && !showWizard">
      <!-- Header -->
      <header class="briefing-header">
        <div class="briefing-header-left">
          <h1 class="briefing-title">Briefing</h1>
          <span class="briefing-today-badge">{{ new Date().toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' }) }}</span>
        </div>
        <div class="briefing-header-right">
          <!-- Conversation history dropdown -->
          <select v-if="conversations.length" v-model="selectedConvId" class="briefing-conv-select">
            <option v-for="c in conversations" :key="c.id" :value="c.id">{{ convLabel(c) }}</option>
          </select>
          <button
            class="btn-trigger"
            @click="triggerNow"
            :disabled="triggering"
            title="Manually trigger morning briefing now"
          >{{ triggering ? '…' : 'Refresh' }}</button>
        </div>
      </header>

      <!-- Messages -->
      <div class="briefing-messages-wrap">
        <div v-if="loadingMessages" class="briefing-loading">Loading…</div>
        <template v-else>
          <div v-if="!messages.length" class="briefing-empty">
            <p>No briefing yet for today.</p>
            <p class="briefing-empty-hint">Click "Refresh" to generate a briefing now, or wait for the scheduled slot.</p>
          </div>
          <div v-else class="briefing-messages">
            <template v-for="msg in messages" :key="msg.id">
              <!-- Weather card above the first assistant message with weather metadata -->
              <WeatherCard
                v-if="msg.role === 'assistant' && msgMetadata(msg)?.weather !== undefined"
                :weather="msgMetadata(msg)?.weather ?? null"
              />
              <ChatMessage
                :message="toMsg(msg)"
                :is-streaming="false"
              />
              <!-- Reaction buttons below assistant messages with rss_item_ids -->
              <div
                v-if="msg.role === 'assistant' && (msgMetadata(msg)?.rss_item_ids?.length ?? 0) > 0"
                class="rss-reactions"
              >
                <div
                  v-for="(itemId, index) in msgMetadata(msg)!.rss_item_ids"
                  :key="itemId"
                  class="rss-reaction-row"
                >
                  <span class="reaction-label">Story {{ index + 1 }}</span>
                  <button
                    class="reaction-btn"
                    :class="{ active: reactions[itemId] === 'up' }"
                    @click="handleReaction(itemId, 'up')"
                    title="Interested"
                  >👍</button>
                  <button
                    class="reaction-btn"
                    :class="{ active: reactions[itemId] === 'down' }"
                    @click="handleReaction(itemId, 'down')"
                    title="Not interested"
                  >👎</button>
                </div>
              </div>
            </template>
            <!-- Live streaming bubble for today -->
            <ChatMessage
              v-if="isToday && chatStore.streaming && chatStore.streamingContent"
              :message="{
                id: -1,
                conversation_id: todayConvId ?? -1,
                role: 'assistant',
                content: chatStore.streamingContent,
                context_note_id: null,
                context_note_title: null,
                created_at: new Date().toISOString(),
              }"
              :is-streaming="true"
            />
          </div>
        </template>
      </div>

      <!-- Input bar (today only) -->
      <div v-if="isToday" class="briefing-input-bar">
        <textarea
          v-model="input"
          class="briefing-input"
          placeholder="Reply to your briefing…"
          rows="1"
          @keydown="onKeydown"
        ></textarea>
        <button
          class="btn-send"
          @click="send"
          :disabled="!input.trim() || chatStore.streaming || sending"
          aria-label="Send"
        >
          <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
            <path d="M2 21l21-9L2 3v7l15 2-15 2v7z"/>
          </svg>
        </button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.briefing-root {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

.briefing-shell {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  max-width: 760px;
  margin: 0 auto;
  width: 100%;
  padding: 0 1rem;
}

.briefing-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 0 1rem;
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
  gap: 1rem;
  flex-wrap: wrap;
}

.briefing-header-left {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

.briefing-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.3rem;
  font-weight: 700;
  margin: 0;
  color: var(--color-text);
}

.briefing-today-badge {
  font-size: 0.82rem;
  color: var(--color-text-muted);
}

.briefing-header-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.briefing-conv-select {
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-bg-card);
  color: var(--color-text);
  font-size: 0.82rem;
  cursor: pointer;
  font-family: inherit;
}

.btn-trigger {
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-bg-card);
  color: var(--color-text-muted);
  font-size: 0.8rem;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
  font-family: inherit;
}
.btn-trigger:hover:not(:disabled) {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.btn-trigger:disabled { opacity: 0.5; cursor: not-allowed; }

.briefing-messages-wrap {
  flex: 1;
  overflow-y: auto;
  padding: 1rem 0;
}

.briefing-loading,
.briefing-empty {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.briefing-empty-hint {
  font-size: 0.8rem;
  opacity: 0.7;
  margin-top: 0.5rem;
}

.briefing-messages {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.briefing-input-bar {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
  padding: 0.75rem 0 1rem;
  border-top: 1px solid var(--color-border);
  flex-shrink: 0;
}

.briefing-input {
  flex: 1;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-bg-card);
  color: var(--color-text);
  font-size: 0.9rem;
  resize: none;
  outline: none;
  font-family: inherit;
  line-height: 1.4;
  max-height: 120px;
  overflow-y: auto;
  transition: border-color 0.15s;
}
.briefing-input:focus { border-color: var(--color-primary); }

.btn-send {
  padding: 0.55rem 0.75rem;
  background: linear-gradient(135deg, #6366f1, #4f46e5);
  color: #fff;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.15s;
  flex-shrink: 0;
}
.btn-send:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-send:hover:not(:disabled) { opacity: 0.9; }

.rss-reactions {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.25rem;
}

.rss-reaction-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.reaction-label {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  min-width: 4rem;
}

.reaction-btn {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  padding: 0.15rem 0.4rem;
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1.4;
  opacity: 0.55;
  transition: opacity 0.15s, border-color 0.15s;
}

.reaction-btn:hover {
  opacity: 1;
  border-color: var(--color-primary);
}

.reaction-btn.active {
  opacity: 1;
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}
</style>
