<script setup lang="ts">
import { ref, watch, computed, onUnmounted } from 'vue'
import Dialog from 'primevue/dialog'
import Button from 'primevue/button'
import { useEditor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import { Markdown } from 'tiptap-markdown'
import { wsManager, type WebSocketMessage } from '../composables/useWebSocket'

const props = defineProps<{
  visible: boolean
  category: 'indicator' | 'strategy' | 'research'
  name: string
}>()

const emit = defineEmits<{
  'update:visible': [value: boolean]
  'updated': [payload: { category: string; name: string; success: boolean; error?: string }]
}>()

type LoadState = 'idle' | 'loading' | 'ready' | 'error'

const loadState = ref<LoadState>('idle')
const loadError = ref('')
const saving = ref(false)
const showConfirmCancel = ref(false)

const editor = useEditor({
  extensions: [
    StarterKit,
    Markdown.configure({ html: false, transformPastedText: true }),
  ],
  content: '',
})

const originalContent = ref('')

const isDirty = computed(() => {
  if (!editor.value || loadState.value !== 'ready') return false
  return (editor.value.storage as any).markdown.getMarkdown() !== originalContent.value
})

watch(() => props.visible, (v) => {
  if (v) {
    loadState.value = 'loading'
    loadError.value = ''
    saving.value = false
    showConfirmCancel.value = false
    wsManager.send({ type: 'read_details', category: props.category, name: props.name })
  } else {
    loadState.value = 'idle'
    originalContent.value = ''
    editor.value?.commands.setContent('')
  }
})

const messageHandler = (msg: WebSocketMessage) => {
  if (msg.category !== props.category || msg.name !== props.name) return

  if (msg.type === 'details_data') {
    originalContent.value = msg.details ?? ''
    editor.value?.commands.setContent(msg.details ?? '')
    loadState.value = 'ready'
  } else if (msg.type === 'details_error') {
    loadError.value = msg.error ?? 'Failed to load details'
    loadState.value = 'error'
  } else if (msg.type === 'details_updated') {
    saving.value = false
    emit('updated', {
      category: props.category,
      name: props.name,
      success: msg.success,
      error: msg.error,
    })
    if (msg.success) {
      close()
    } else {
      loadError.value = msg.error ?? 'Update failed'
    }
  }
}

wsManager.addHandler(messageHandler)
onUnmounted(() => wsManager.removeHandler(messageHandler))

function save() {
  if (!editor.value || saving.value) return
  saving.value = true
  loadError.value = ''
  wsManager.send({
    type: 'update_details',
    category: props.category,
    name: props.name,
    details: (editor.value.storage as any).markdown.getMarkdown(),
  })
}

function requestClose() {
  if (isDirty.value) {
    showConfirmCancel.value = true
  } else {
    close()
  }
}

function close() {
  showConfirmCancel.value = false
  emit('update:visible', false)
}
</script>

<template>
  <Dialog
    :visible="visible"
    :header="`Edit Details — ${name}`"
    :modal="true"
    :closable="true"
    :style="{ width: '720px', maxWidth: '95vw' }"
    class="details-dialog"
    @update:visible="requestClose"
  >
    <div class="dialog-body">
      <div v-if="loadState === 'loading'" class="state-msg">
        <i class="pi pi-spin pi-spinner" /> Loading details…
      </div>
      <div v-else-if="loadState === 'error'" class="state-msg error">
        <i class="pi pi-exclamation-triangle" /> {{ loadError }}
      </div>
      <template v-else>
        <div v-if="loadError" class="save-error">
          <i class="pi pi-exclamation-triangle" /> {{ loadError }}
        </div>
        <div class="editor-wrap">
          <div v-if="editor" class="toolbar">
            <div class="toolbar-group">
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('bold') }"
                title="Bold"
                @click="editor.chain().focus().toggleBold().run()"
              ><b>B</b></button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('italic') }"
                title="Italic"
                @click="editor.chain().focus().toggleItalic().run()"
              ><i>I</i></button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('strike') }"
                title="Strikethrough"
                @click="editor.chain().focus().toggleStrike().run()"
              ><s>S</s></button>
            </div>
            <div class="toolbar-sep" />
            <div class="toolbar-group">
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('heading', { level: 1 }) }"
                title="Heading 1"
                @click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
              >H1</button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('heading', { level: 2 }) }"
                title="Heading 2"
                @click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
              >H2</button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('heading', { level: 3 }) }"
                title="Heading 3"
                @click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
              >H3</button>
            </div>
            <div class="toolbar-sep" />
            <div class="toolbar-group">
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('bulletList') }"
                title="Bullet list"
                @click="editor.chain().focus().toggleBulletList().run()"
              ><i class="pi pi-list" /></button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('orderedList') }"
                title="Ordered list"
                @click="editor.chain().focus().toggleOrderedList().run()"
              ><i class="pi pi-sort-amount-down" /></button>
            </div>
            <div class="toolbar-sep" />
            <div class="toolbar-group">
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('code') }"
                title="Inline code"
                @click="editor.chain().focus().toggleCode().run()"
              ><code style="font-size:11px">`c`</code></button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('codeBlock') }"
                title="Code block"
                @click="editor.chain().focus().toggleCodeBlock().run()"
              ><i class="pi pi-code" /></button>
              <button
                class="tb-btn"
                :class="{ active: editor.isActive('blockquote') }"
                title="Blockquote"
                @click="editor.chain().focus().toggleBlockquote().run()"
              >&ldquo;&rdquo;</button>
            </div>
            <div class="toolbar-sep" />
            <div class="toolbar-group">
              <button
                class="tb-btn"
                title="Horizontal rule"
                @click="editor.chain().focus().setHorizontalRule().run()"
              >—</button>
            </div>
          </div>
          <EditorContent :editor="editor" class="tiptap-editor" />
        </div>
      </template>
    </div>

    <!-- Saving overlay -->
    <div v-if="saving" class="confirm-overlay saving-overlay">
      <div class="confirm-box">
        <i class="pi pi-spin pi-spinner" style="font-size: 1.4rem; color: #89d4e0;" />
        <p>The AI assistant is programming your changes. Please wait…</p>
      </div>
    </div>

    <!-- Confirm-cancel overlay -->
    <div v-if="showConfirmCancel" class="confirm-overlay">
      <div class="confirm-box">
        <p>Discard unsaved changes?</p>
        <div class="confirm-actions">
          <Button label="Keep editing" size="small" outlined @click="showConfirmCancel = false" />
          <Button label="Discard" size="small" severity="danger" @click="close" />
        </div>
      </div>
    </div>

    <template #footer>
      <Button label="Cancel" size="small" outlined :disabled="saving" @click="requestClose" />
      <Button
        label="Save"
        size="small"
        :loading="saving"
        :disabled="loadState !== 'ready'"
        @click="save"
      />
    </template>
  </Dialog>
</template>

<style scoped>
.dialog-body {
  min-height: 300px;
  display: flex;
  flex-direction: column;
  position: relative;
}

.state-msg {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #8a8a8a;
  font-size: 13px;
}

.state-msg.error {
  color: #e06c6c;
}

.save-error {
  color: #e06c6c;
  font-size: 12px;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.editor-wrap {
  flex: 1;
  border: 1px solid #2e2e2e;
  border-radius: 4px;
  overflow: auto;
  background: #0d0d0d;
  min-height: 300px;
  display: flex;
  flex-direction: column;
}

.toolbar {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 5px 8px;
  border-bottom: 1px solid #2e2e2e;
  background: #111;
  flex-shrink: 0;
  flex-wrap: wrap;
}

.toolbar-group {
  display: flex;
  align-items: center;
  gap: 1px;
}

.toolbar-sep {
  width: 1px;
  height: 16px;
  background: #2e2e2e;
  margin: 0 4px;
}

.tb-btn {
  background: none;
  border: none;
  color: #8a8a8a;
  cursor: pointer;
  padding: 3px 7px;
  border-radius: 3px;
  font-size: 12px;
  font-family: inherit;
  line-height: 1;
  min-width: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s, color 0.1s;
}

.tb-btn:hover {
  background: #1e1e1e;
  color: #dbdbdb;
}

.tb-btn.active {
  background: #1e3a3f;
  color: #89d4e0;
}

.confirm-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  z-index: 1;
}

.confirm-box {
  background: #1a1a1a;
  border: 1px solid #3d3d3d;
  border-radius: 6px;
  padding: 20px 24px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.confirm-box p {
  color: #dbdbdb;
  font-size: 13px;
  margin: 0;
}

.confirm-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
}
</style>

<style>
/* Global (unscoped) so TipTap's .ProseMirror gets styled */
.details-dialog .tiptap-editor {
  flex: 1;
  overflow: auto;
}

.details-dialog .tiptap-editor .ProseMirror {
  padding: 12px 14px;
  outline: none;
  min-height: 280px;
  font-size: 13px;
  line-height: 1.6;
  color: #dbdbdb;
  font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
}

.details-dialog .tiptap-editor .ProseMirror h1,
.details-dialog .tiptap-editor .ProseMirror h2,
.details-dialog .tiptap-editor .ProseMirror h3 {
  color: #dbdbdb;
  margin: 0.8em 0 0.4em;
}

.details-dialog .tiptap-editor .ProseMirror p { margin: 0 0 0.6em; }

.details-dialog .tiptap-editor .ProseMirror code {
  background: #1a1a1a;
  border-radius: 3px;
  padding: 1px 5px;
  font-size: 0.9em;
  color: #89d4e0;
}

.details-dialog .tiptap-editor .ProseMirror pre {
  background: #141414;
  border: 1px solid #2e2e2e;
  border-radius: 4px;
  padding: 10px 14px;
  overflow-x: auto;
  margin: 0.6em 0;
}

.details-dialog .tiptap-editor .ProseMirror pre code {
  background: none;
  padding: 0;
  color: #dbdbdb;
}

.details-dialog .tiptap-editor .ProseMirror ul,
.details-dialog .tiptap-editor .ProseMirror ol {
  padding-left: 1.4em;
  margin: 0.4em 0;
}

.details-dialog .tiptap-editor .ProseMirror blockquote {
  border-left: 3px solid #3d3d3d;
  margin: 0.6em 0;
  padding-left: 12px;
  color: #8a8a8a;
}
</style>
