/*
 *  ChatView.tsx
 *  Zyquo Cloud Web
 *
 *  Author: Simon-Pierre Boucher
 *  Mail: contact@spboucher.ai
 *
 *  The chat area: header (editable title, centered model chip, actions),
 *  transcript with scroll-lock + "jump to latest" pill, input bar, and the
 *  parameters popover. Suggestions grid when the conversation is empty.
 */

import { useEffect, useMemo, useRef, useState } from 'react'
import { findModel } from '../features/catalogHelpers'
import { useStore } from '../state/store'
import type { AIModel, Conversation } from '../types'
import InputBar from './InputBar'
import { MessageBubble } from './MessageBubble'
import ModelMenu from './ModelMenu'
import ParamsPanel from './ParamsPanel'
import SuggestionGrid from './SuggestionGrid'
import {
  IconArrowDown,
  IconChevronDown,
  IconColumns,
  IconDownload,
  IconInfo,
  IconMenu,
  ProviderGlyph,
} from './icons'
import { exportConversationMarkdown } from '../features/exporters'

export default function ChatView({ conversation }: { conversation: Conversation }) {
  const updateConversation = useStore((s) => s.updateConversation)
  const streaming = useStore((s) => s.streaming[conversation.id])
  const setSidebarOpen = useStore((s) => s.setSidebarOpen)
  const setCompareOpen = useStore((s) => s.setCompareOpen)
  const updateSettings = useStore((s) => s.updateSettings)
  const modelMenuOpen = useStore((s) => s.modelMenuOpen)
  const setModelMenuOpen = useStore((s) => s.setModelMenuOpen)
  const density = useStore((s) => s.settings.density)

  const [editingTitle, setEditingTitle] = useState(false)
  const [titleDraft, setTitleDraft] = useState(conversation.title)
  const [paramsOpen, setParamsOpen] = useState(false)
  const [infoOpen, setInfoOpen] = useState(false)
  const draftSeed = useStore((s) => s.draftSeed)
  const setDraftSeed = useStore((s) => s.setDraftSeed)
  const [draft, setDraft] = useState('')
  const [pinnedToBottom, setPinnedToBottom] = useState(true)

  // Pick up a prompt seeded from the root empty state's suggestion cards.
  useEffect(() => {
    if (draftSeed !== null) {
      setDraft(draftSeed)
      setDraftSeed(null)
      document.querySelector<HTMLTextAreaElement>('[data-input-editor]')?.focus()
    }
  }, [draftSeed, setDraftSeed])
  const scrollRef = useRef<HTMLDivElement>(null)

  const model = findModel(conversation.provider, conversation.modelID)

  // Auto-scroll while pinned to bottom.
  const lastMessage = conversation.messages[conversation.messages.length - 1]
  const scrollFingerprint = `${conversation.messages.length}:${lastMessage?.text.length ?? 0}:${
    lastMessage?.reasoning?.length ?? 0
  }`
  useEffect(() => {
    if (pinnedToBottom && scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight
    }
  }, [scrollFingerprint, pinnedToBottom])

  const onScroll = () => {
    const el = scrollRef.current
    if (!el) return
    setPinnedToBottom(el.scrollHeight - el.scrollTop - el.clientHeight < 60)
  }

  const totals = useMemo(() => {
    let input = 0
    let output = 0
    let cost = 0
    for (const message of conversation.messages) {
      input += message.usage?.inputTokens ?? 0
      output += message.usage?.outputTokens ?? 0
      cost += message.estimatedCost ?? 0
    }
    return { input, output, cost }
  }, [conversation])

  const pickModel = (picked: AIModel, scope: 'conversation' | 'default' | 'message') => {
    if (scope === 'default') {
      updateSettings({ defaultModelID: picked.id, defaultProvider: picked.provider })
    }
    updateConversation(conversation.id, { modelID: picked.id, provider: picked.provider })
  }

  const quote = (text: string) => {
    const quoted = text
      .split('\n')
      .map((line) => `> ${line}`)
      .join('\n')
    setDraft((d) => `${quoted}\n\n${d}`)
  }

  return (
    <div className={`chat-area density-${density}`}>
      <header className="chat-header">
        <div className="chat-header-left">
          <button
            className="icon-button menu-button"
            title="Conversations"
            onClick={() => setSidebarOpen(true)}
          >
            <IconMenu />
          </button>
          {editingTitle ? (
            <input
              className="chat-title-input"
              value={titleDraft}
              autoFocus
              onChange={(e) => setTitleDraft(e.target.value)}
              onBlur={() => {
                setEditingTitle(false)
                if (titleDraft.trim() !== '') {
                  updateConversation(conversation.id, {
                    title: titleDraft.trim(),
                    hasAutoTitle: false,
                  })
                }
              }}
              onKeyDown={(e) => {
                if (e.key === 'Enter') (e.target as HTMLInputElement).blur()
                if (e.key === 'Escape') setEditingTitle(false)
              }}
            />
          ) : (
            <span
              className="chat-title"
              title="Double-click to rename"
              onDoubleClick={() => {
                setTitleDraft(conversation.title)
                setEditingTitle(true)
              }}
            >
              {conversation.title}
            </span>
          )}
        </div>
        <button className="model-chip" onClick={() => setModelMenuOpen(true)} data-model-chip>
          <span className="glyph">
            <ProviderGlyph provider={conversation.provider} />
          </span>
          {model?.displayName ?? conversation.modelID}
          <span className="chevron">
            <IconChevronDown />
          </span>
        </button>
        <div className="chat-header-right">
          <button className="icon-button" title="Compare models" onClick={() => setCompareOpen(true)}>
            <IconColumns />
          </button>
          <button
            className="icon-button"
            title="Export conversation (⌘⇧E)"
            onClick={() => exportConversationMarkdown(conversation)}
          >
            <IconDownload />
          </button>
          <button className="icon-button" title="Conversation info" onClick={() => setInfoOpen(true)}>
            <IconInfo />
          </button>
        </div>
      </header>

      {conversation.messages.length === 0 ? (
        <SuggestionGrid
          onPick={(prompt) => setDraft(prompt)}
          modelChip={
            <button className="model-chip" onClick={() => setModelMenuOpen(true)}>
              <span className="glyph">
                <ProviderGlyph provider={conversation.provider} />
              </span>
              {model?.displayName ?? conversation.modelID}
              <span className="chevron">
                <IconChevronDown />
              </span>
            </button>
          }
        />
      ) : (
        <div className="transcript" ref={scrollRef} onScroll={onScroll}>
          <div className="transcript-column">
            {conversation.messages.map((message, index) => (
              <MessageBubble
                key={message.id}
                conversationID={conversation.id}
                message={message}
                streaming={streaming?.messageID === message.id}
                isLast={index === conversation.messages.length - 1 && !streaming}
                onQuote={quote}
              />
            ))}
          </div>
          {!pinnedToBottom && streaming && (
            <button
              className="jump-pill"
              onClick={() => {
                setPinnedToBottom(true)
                scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight })
              }}
            >
              <IconArrowDown /> Jump to latest
            </button>
          )}
        </div>
      )}

      <InputBar
        conversation={conversation}
        draft={draft}
        setDraft={setDraft}
        onOpenParams={() => setParamsOpen(true)}
      />

      {modelMenuOpen && (
        <ModelMenu
          currentID={conversation.modelID}
          onPick={pickModel}
          onClose={() => setModelMenuOpen(false)}
        />
      )}
      {paramsOpen && (
        <ParamsPanel conversation={conversation} onClose={() => setParamsOpen(false)} />
      )}
      {infoOpen && (
        <div className="overlay" onMouseDown={(e) => e.target === e.currentTarget && setInfoOpen(false)}>
          <div className="panel" style={{ width: 400 }}>
            <div className="settings-content">
              <h3>Conversation</h3>
              <div className="settings-row">
                <span>Tokens</span>
                <span style={{ marginLeft: 'auto', color: 'var(--z-text-secondary)' }}>
                  {totals.input.toLocaleString()} in · {totals.output.toLocaleString()} out
                </span>
              </div>
              <div className="settings-row">
                <span>Estimated cost</span>
                <span style={{ marginLeft: 'auto', color: 'var(--z-text-secondary)' }}>
                  ~${totals.cost.toFixed(4)}
                </span>
              </div>
              <div className="settings-section" style={{ marginTop: 12 }}>
                <h3>System prompt</h3>
                <textarea
                  className="text-input"
                  rows={5}
                  placeholder="No system prompt"
                  value={conversation.systemPrompt ?? ''}
                  onChange={(e) =>
                    updateConversation(conversation.id, { systemPrompt: e.target.value })
                  }
                />
              </div>
              <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
                <button className="button" onClick={() => setInfoOpen(false)}>
                  Done
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}
