import { html, css, LitElement } from "../../assets/lit-core-2.7.4.min.js";

export class AssistantView extends LitElement {
  static styles = css`
    :host {
      height: 100%;
      display: flex;
      flex-direction: column;
    }

    * {
      font-family: var(--font);
      cursor: default;
    }

    /* ── Response area ── */

    .response-container {
      flex: 1;
      overflow-y: auto;
      font-size: var(--response-font-size, 15px);
      line-height: var(--line-height);
      background: var(--bg-app);
      padding: var(--space-sm) var(--space-md);
      scroll-behavior: smooth;
      user-select: text;
      cursor: text;
      color: var(--text-primary);
    }

    .response-container * {
      user-select: text;
      cursor: text;
    }

    .response-container a {
      cursor: pointer;
    }

    .response-container [data-word] {
      display: inline-block;
    }

    /* ── Markdown ── */

    .response-container h1,
    .response-container h2,
    .response-container h3,
    .response-container h4,
    .response-container h5,
    .response-container h6 {
      margin: 1em 0 0.5em 0;
      color: var(--text-primary);
      font-weight: var(--font-weight-semibold);
    }

    .response-container h1 {
      font-size: 1.5em;
    }
    .response-container h2 {
      font-size: 1.3em;
    }
    .response-container h3 {
      font-size: 1.15em;
    }
    .response-container h4 {
      font-size: 1.05em;
    }
    .response-container h5,
    .response-container h6 {
      font-size: 1em;
    }

    .response-container p {
      margin: 0.6em 0;
      color: var(--text-primary);
    }

    .response-container ul,
    .response-container ol {
      margin: 0.6em 0;
      padding-left: 1.5em;
      color: var(--text-primary);
    }

    .response-container li {
      margin: 0.3em 0;
    }

    .response-container blockquote {
      margin: 0.8em 0;
      padding: 0.5em 1em;
      border-left: 2px solid var(--border-strong);
      background: var(--bg-surface);
      border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    }

    .response-container code {
      background: var(--bg-elevated);
      padding: 0.15em 0.4em;
      border-radius: var(--radius-sm);
      font-family: var(--font-mono);
      font-size: 0.85em;
    }

    .response-container pre {
      background: var(--bg-surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      padding: var(--space-md);
      overflow-x: auto;
      margin: 0.8em 0;
      position: relative;
    }

    .response-container pre::before {
      content: attr(data-language);
      position: absolute;
      top: 0;
      right: 0;
      background: var(--bg-elevated);
      color: var(--text-secondary);
      padding: 4px 12px;
      font-size: var(--font-size-xs);
      font-family: var(--font-mono);
      border: 1px solid var(--border);
      border-top: none;
      border-right: none;
      border-bottom-left-radius: var(--radius-sm);
      text-transform: uppercase;
      letter-spacing: 0.5px;
    }

    .response-container pre code {
      background: none;
      padding: 0;
      font-family: var(--font-mono);
      font-size: 0.9em;
      line-height: 1.5;
      color: var(--text-primary);
    }

    /* ── Syntax highlighting for code blocks ── */
    /* Default (Dark theme) */
    .response-container .hljs {
      color: #c9d1d9;
      background: transparent;
    }

    .response-container .hljs-doctag,
    .response-container .hljs-keyword,
    .response-container .hljs-meta .hljs-keyword,
    .response-container .hljs-template-tag,
    .response-container .hljs-template-variable,
    .response-container .hljs-type,
    .response-container .hljs-variable.language_ {
      color: #ff7b72;
    }

    .response-container .hljs-title,
    .response-container .hljs-title.class_,
    .response-container .hljs-title.class_.inherited__,
    .response-container .hljs-title.function_ {
      color: #d2a8ff;
    }

    .response-container .hljs-attr,
    .response-container .hljs-attribute,
    .response-container .hljs-literal,
    .response-container .hljs-meta,
    .response-container .hljs-number,
    .response-container .hljs-operator,
    .response-container .hljs-selector-attr,
    .response-container .hljs-selector-class,
    .response-container .hljs-selector-id,
    .response-container .hljs-variable {
      color: #79c0ff;
    }

    .response-container .hljs-meta .hljs-string,
    .response-container .hljs-regexp,
    .response-container .hljs-string {
      color: #a5d6ff;
    }

    .response-container .hljs-built_in,
    .response-container .hljs-symbol {
      color: #ffa657;
    }

    .response-container .hljs-code,
    .response-container .hljs-comment,
    .response-container .hljs-formula {
      color: #8b949e;
    }

    .response-container .hljs-name,
    .response-container .hljs-quote,
    .response-container .hljs-selector-pseudo,
    .response-container .hljs-selector-tag {
      color: #7ee787;
    }

    .response-container .hljs-subst {
      color: #c9d1d9;
    }

    .response-container .hljs-section {
      color: #1f6feb;
      font-weight: 700;
    }

    .response-container .hljs-bullet {
      color: #f2cc60;
    }

    .response-container .hljs-emphasis {
      color: #c9d1d9;
      font-style: italic;
    }

    .response-container .hljs-strong {
      color: #c9d1d9;
      font-weight: 700;
    }

    .response-container .hljs-addition {
      color: #aff5b4;
      background-color: #033a16;
    }

    .response-container .hljs-deletion {
      color: #ffdcd7;
      background-color: #67060c;
    }

    /* Light theme syntax highlighting */
    :host-context(body[data-theme-type="light"]) .response-container .hljs {
      color: #24292f;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-doctag,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-keyword,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-meta .hljs-keyword,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-template-tag,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-template-variable,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-type,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-variable.language_ {
      color: #cf222e;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-title,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-title.class_,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-title.class_.inherited__,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-title.function_ {
      color: #8250df;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-attr,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-attribute,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-literal,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-meta,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-number,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-operator,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-selector-attr,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-selector-class,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-selector-id,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-variable {
      color: #0550ae;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-meta .hljs-string,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-regexp,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-string {
      color: #0a3069;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-built_in,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-symbol {
      color: #953800;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-code,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-comment,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-formula {
      color: #6e7781;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-name,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-quote,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-selector-pseudo,
    :host-context(body[data-theme-type="light"]) .response-container .hljs-selector-tag {
      color: #116329;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-subst {
      color: #24292f;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-section {
      color: #0969da;
      font-weight: 700;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-bullet {
      color: #953800;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-emphasis {
      color: #24292f;
      font-style: italic;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-strong {
      color: #24292f;
      font-weight: 700;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-addition {
      color: #116329;
      background-color: #dafbe1;
    }

    :host-context(body[data-theme-type="light"]) .response-container .hljs-deletion {
      color: #82071e;
      background-color: #ffebe9;
    }

    .response-container a {
      color: var(--accent);
      text-decoration: underline;
      text-underline-offset: 2px;
    }

    .response-container strong,
    .response-container b {
      font-weight: var(--font-weight-semibold);
    }

    .response-container hr {
      border: none;
      border-top: 1px solid var(--border);
      margin: 1.5em 0;
    }

    .response-container table {
      border-collapse: collapse;
      width: 100%;
      margin: 0.8em 0;
    }

    .response-container th,
    .response-container td {
      border: 1px solid var(--border);
      padding: var(--space-sm);
      text-align: left;
    }

    .response-container th {
      background: var(--bg-surface);
      font-weight: var(--font-weight-semibold);
    }

    .response-container::-webkit-scrollbar {
      width: 6px;
    }

    .response-container::-webkit-scrollbar-track {
      background: transparent;
    }

    .response-container::-webkit-scrollbar-thumb {
      background: var(--border-strong);
      border-radius: 3px;
    }

    .response-container::-webkit-scrollbar-thumb:hover {
      background: #444444;
    }

    /* ── Response navigation strip ── */

    .response-nav {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--space-sm);
      padding: var(--space-xs) var(--space-md);
      border-top: 1px solid var(--border);
      background: var(--bg-app);
    }

    .nav-btn {
      background: none;
      border: none;
      color: var(--text-muted);
      cursor: pointer;
      padding: var(--space-xs);
      border-radius: var(--radius-sm);
      display: flex;
      align-items: center;
      justify-content: center;
      transition: color var(--transition);
    }

    .nav-btn:hover:not(:disabled) {
      color: var(--text-primary);
    }

    .nav-btn:disabled {
      opacity: 0.25;
      cursor: default;
    }

    .nav-btn svg {
      width: 14px;
      height: 14px;
    }

    .response-counter {
      font-size: var(--font-size-xs);
      color: var(--text-muted);
      font-family: var(--font-mono);
      min-width: 40px;
      text-align: center;
    }

    /* ── Bottom input bar ── */

    .input-bar {
      display: flex;
      align-items: center;
      gap: var(--space-sm);
      padding: var(--space-md);
      background: var(--bg-app);
    }

    .input-bar-inner {
      display: flex;
      align-items: center;
      flex: 1;
      background: var(--bg-elevated);
      border: 1px solid var(--border);
      border-radius: 100px;
      padding: 0 var(--space-md);
      height: 32px;
      transition: border-color var(--transition);
    }

    .input-bar-inner:focus-within {
      border-color: var(--accent);
    }

    .input-bar-inner input {
      flex: 1;
      background: none;
      color: var(--text-primary);
      border: none;
      padding: 0;
      font-size: var(--font-size-sm);
      font-family: var(--font);
      height: 100%;
      outline: none;
    }

    .input-bar-inner input::placeholder {
      color: var(--text-muted);
    }

    .analyze-btn {
      position: relative;
      background: var(--bg-elevated);
      border: 1px solid var(--border);
      color: var(--text-primary);
      cursor: pointer;
      font-size: var(--font-size-xs);
      font-family: var(--font-mono);
      white-space: nowrap;
      padding: var(--space-xs) var(--space-md);
      border-radius: 100px;
      height: 32px;
      display: flex;
      align-items: center;
      gap: 4px;
      transition:
        border-color 0.4s ease,
        background var(--transition);
      flex-shrink: 0;
      overflow: hidden;
    }

    .analyze-btn:hover:not(.analyzing) {
      border-color: var(--accent);
      background: var(--bg-surface);
    }

    .analyze-btn.analyzing {
      cursor: default;
      border-color: transparent;
    }

    .analyze-btn-content {
      display: flex;
      align-items: center;
      gap: 4px;
      transition: opacity 0.4s ease;
      z-index: 1;
      position: relative;
    }

    .analyze-btn.analyzing .analyze-btn-content {
      opacity: 0;
    }

    .analyze-canvas {
      position: absolute;
      inset: -1px;
      width: calc(100% + 2px);
      height: calc(100% + 2px);
      pointer-events: none;
    }

    /* ── Expand button ── */

    .expand-bar {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: var(--space-xs) var(--space-md);
      border-top: 1px solid var(--border);
      background: var(--bg-app);
    }

    .expand-btn {
      display: flex;
      align-items: center;
      gap: 4px;
      background: none;
      border: 1px solid var(--border);
      color: var(--text-secondary);
      cursor: pointer;
      font-size: var(--font-size-xs);
      font-family: var(--font-mono);
      padding: var(--space-xs) var(--space-md);
      border-radius: 100px;
      height: 26px;
      transition:
        color var(--transition),
        border-color var(--transition),
        background var(--transition);
    }

    .expand-btn:hover:not(:disabled) {
      color: var(--text-primary);
      border-color: var(--accent);
      background: var(--bg-surface);
    }

    .expand-btn:disabled {
      opacity: 0.4;
      cursor: default;
    }

    .expand-btn svg {
      width: 12px;
      height: 12px;
    }
  `;

  static properties = {
    responses: { type: Array },
    currentResponseIndex: { type: Number },
    selectedProfile: { type: String },
    onSendText: { type: Function },
    onExpandResponse: { type: Function },
    shouldAnimateResponse: { type: Boolean },
    isAnalyzing: { type: Boolean, state: true },
    isExpanding: { type: Boolean, state: true },
  };

  constructor() {
    super();
    this.responses = [];
    this.currentResponseIndex = -1;
    this.selectedProfile = "interview";
    this.onSendText = () => {};
    this.onExpandResponse = () => {};
    this.isAnalyzing = false;
    this.isExpanding = false;
    this._animFrame = null;
  }

  getProfileNames() {
    return {
      interview: "Job Interview",
      sales: "Sales Call",
      meeting: "Business Meeting",
      presentation: "Presentation",
      negotiation: "Negotiation",
      exam: "Exam Assistant",
    };
  }

  getCurrentResponse() {
    const profileNames = this.getProfileNames();
    return this.responses.length > 0 && this.currentResponseIndex >= 0
      ? this.responses[this.currentResponseIndex]
      : `Listening to your ${profileNames[this.selectedProfile] || "session"}...`;
  }

  renderMarkdown(content) {
    if (typeof window !== "undefined" && window.marked) {
      try {
        // Configure marked to use highlight.js for syntax highlighting
        window.marked.setOptions({
          breaks: true,
          gfm: true,
          sanitize: false,
          highlight: (code, lang) => {
            if (window.hljs && lang) {
              try {
                return window.hljs.highlight(code, { language: lang }).value;
              } catch (e) {
                // If language is not recognized, try auto-detection
                try {
                  return window.hljs.highlightAuto(code).value;
                } catch (err) {
                  return window.hljs.escapeHtml(code);
                }
              }
            } else if (window.hljs) {
              // Auto-detect language if not specified
              try {
                return window.hljs.highlightAuto(code).value;
              } catch (e) {
                return window.hljs.escapeHtml(code);
              }
            }
            return code;
          },
        });
        let rendered = window.marked.parse(content);
        rendered = this.wrapWordsInSpans(rendered);
        return rendered;
      } catch (error) {
        console.warn("Error parsing markdown:", error);
        return content;
      }
    }
    return content;
  }

  wrapWordsInSpans(html) {
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, "text/html");
    const tagsToSkip = ["PRE", "CODE"];

    function wrap(node) {
      if (
        node.nodeType === Node.TEXT_NODE &&
        node.textContent.trim() &&
        !tagsToSkip.includes(node.parentNode.tagName)
      ) {
        const words = node.textContent.split(/(\s+)/);
        const frag = document.createDocumentFragment();
        words.forEach((word) => {
          if (word.trim()) {
            const span = document.createElement("span");
            span.setAttribute("data-word", "");
            span.textContent = word;
            frag.appendChild(span);
          } else {
            frag.appendChild(document.createTextNode(word));
          }
        });
        node.parentNode.replaceChild(frag, node);
      } else if (
        node.nodeType === Node.ELEMENT_NODE &&
        !tagsToSkip.includes(node.tagName)
      ) {
        Array.from(node.childNodes).forEach(wrap);
      }
    }
    Array.from(doc.body.childNodes).forEach(wrap);
    return doc.body.innerHTML;
  }

  applyCodeHighlighting(container) {
    if (!window.hljs) return;
    
    // Find all code blocks in the rendered content
    const codeBlocks = container.querySelectorAll("pre code");
    
    codeBlocks.forEach((block) => {
      const pre = block.parentElement;
      if (!pre || pre.tagName !== "PRE") return;
      
      // Skip if already highlighted
      if (block.classList.contains("hljs")) {
        return;
      }
      
      const code = block.textContent;
      let lang = block.className.replace(/language-|lang-/, "") || "";
      
      try {
        if (lang && window.hljs.getLanguage(lang)) {
          block.innerHTML = window.hljs.highlight(code, { language: lang }).value;
        } else {
          // Auto-detect language
          const result = window.hljs.highlightAuto(code);
          block.innerHTML = result.value;
          if (result.language && !lang) {
            lang = result.language;
            block.className = `language-${lang}`;
          }
        }
        block.classList.add("hljs");
        
        // Set data-language attribute on pre tag for display
        if (lang) {
          pre.setAttribute("data-language", lang);
        }
      } catch (e) {
        console.warn("Error highlighting code block:", e);
        // Leave block as-is if highlighting fails
      }
    });
  }

  navigateToPreviousResponse() {
    if (this.currentResponseIndex > 0) {
      this.currentResponseIndex--;
      this.dispatchEvent(
        new CustomEvent("response-index-changed", {
          detail: { index: this.currentResponseIndex },
        }),
      );
      this.requestUpdate();
    }
  }

  navigateToNextResponse() {
    if (this.currentResponseIndex < this.responses.length - 1) {
      this.currentResponseIndex++;
      this.dispatchEvent(
        new CustomEvent("response-index-changed", {
          detail: { index: this.currentResponseIndex },
        }),
      );
      this.requestUpdate();
    }
  }

  scrollResponseUp() {
    const container = this.shadowRoot.querySelector(".response-container");
    if (container) {
      const scrollAmount = container.clientHeight * 0.3;
      container.scrollTop = Math.max(0, container.scrollTop - scrollAmount);
    }
  }

  scrollResponseDown() {
    const container = this.shadowRoot.querySelector(".response-container");
    if (container) {
      const scrollAmount = container.clientHeight * 0.3;
      container.scrollTop = Math.min(
        container.scrollHeight - container.clientHeight,
        container.scrollTop + scrollAmount,
      );
    }
  }

  connectedCallback() {
    super.connectedCallback();

    if (window.require) {
      const { ipcRenderer } = window.require("electron");

      this.handlePreviousResponse = () => this.navigateToPreviousResponse();
      this.handleNextResponse = () => this.navigateToNextResponse();
      this.handleScrollUp = () => this.scrollResponseUp();
      this.handleScrollDown = () => this.scrollResponseDown();
      this.handleExpandHotkey = () => this.handleExpandResponse();

      ipcRenderer.on("navigate-previous-response", this.handlePreviousResponse);
      ipcRenderer.on("navigate-next-response", this.handleNextResponse);
      ipcRenderer.on("scroll-response-up", this.handleScrollUp);
      ipcRenderer.on("scroll-response-down", this.handleScrollDown);
      ipcRenderer.on("expand-response", this.handleExpandHotkey);
    }
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this._stopWaveformAnimation();

    if (window.require) {
      const { ipcRenderer } = window.require("electron");
      if (this.handlePreviousResponse)
        ipcRenderer.removeListener(
          "navigate-previous-response",
          this.handlePreviousResponse,
        );
      if (this.handleNextResponse)
        ipcRenderer.removeListener(
          "navigate-next-response",
          this.handleNextResponse,
        );
      if (this.handleScrollUp)
        ipcRenderer.removeListener("scroll-response-up", this.handleScrollUp);
      if (this.handleScrollDown)
        ipcRenderer.removeListener(
          "scroll-response-down",
          this.handleScrollDown,
        );
      if (this.handleExpandHotkey)
        ipcRenderer.removeListener("expand-response", this.handleExpandHotkey);
    }
  }

  async handleSendText() {
    const textInput = this.shadowRoot.querySelector("#textInput");
    if (textInput && textInput.value.trim()) {
      const message = textInput.value.trim();
      textInput.value = "";
      await this.onSendText(message);
    }
  }

  handleTextKeydown(e) {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      this.handleSendText();
    }
  }

  async handleScreenAnswer() {
    if (this.isAnalyzing) return;
    if (window.captureManualScreenshot) {
      this.isAnalyzing = true;
      this._responseCountWhenStarted = this.responses.length;
      window.captureManualScreenshot();
    }
  }

  async handleExpandResponse() {
    if (
      this.isExpanding ||
      this.responses.length === 0 ||
      this.currentResponseIndex < 0
    )
      return;
    this.isExpanding = true;
    this._responseCountWhenStarted = this.responses.length;
    await this.onExpandResponse();
  }

  _startWaveformAnimation() {
    const canvas = this.shadowRoot.querySelector(".analyze-canvas");
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const dpr = window.devicePixelRatio || 1;

    const rect = canvas.getBoundingClientRect();
    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    ctx.scale(dpr, dpr);

    const dangerColor =
      getComputedStyle(this).getPropertyValue("--danger").trim() || "#EF4444";
    const startTime = performance.now();
    const FADE_IN = 0.5; // seconds
    const PARTICLE_SPREAD = 4; // px inward from border
    const PARTICLE_COUNT = 250;

    // Pill perimeter helpers
    const w = rect.width;
    const h = rect.height;
    const r = h / 2; // pill radius = half height
    const straightLen = w - 2 * r;
    const arcLen = Math.PI * r;
    const perimeter = 2 * straightLen + 2 * arcLen;

    // Given a distance along the perimeter, return {x, y, nx, ny} (position + inward normal)
    const pointOnPerimeter = (d) => {
      d = ((d % perimeter) + perimeter) % perimeter;
      // Top straight: left to right
      if (d < straightLen) {
        return { x: r + d, y: 0, nx: 0, ny: 1 };
      }
      d -= straightLen;
      // Right arc
      if (d < arcLen) {
        const angle = -Math.PI / 2 + (d / arcLen) * Math.PI;
        return {
          x: w - r + Math.cos(angle) * r,
          y: r + Math.sin(angle) * r,
          nx: -Math.cos(angle),
          ny: -Math.sin(angle),
        };
      }
      d -= arcLen;
      // Bottom straight: right to left
      if (d < straightLen) {
        return { x: w - r - d, y: h, nx: 0, ny: -1 };
      }
      d -= straightLen;
      // Left arc
      const angle = Math.PI / 2 + (d / arcLen) * Math.PI;
      return {
        x: r + Math.cos(angle) * r,
        y: r + Math.sin(angle) * r,
        nx: -Math.cos(angle),
        ny: -Math.sin(angle),
      };
    };

    // Pre-seed random offsets for stable particles
    const seeds = [];
    for (let i = 0; i < PARTICLE_COUNT; i++) {
      seeds.push({
        pos: Math.random(),
        drift: Math.random(),
        depthSeed: Math.random(),
      });
    }

    const draw = (now) => {
      const elapsed = (now - startTime) / 1000;
      const fade = Math.min(1, elapsed / FADE_IN);

      ctx.clearRect(0, 0, w, h);

      // ── Particle border ──
      ctx.fillStyle = dangerColor;
      for (let i = 0; i < PARTICLE_COUNT; i++) {
        const s = seeds[i];
        const along = (s.pos + s.drift * elapsed * 0.03) * perimeter;
        const depth = s.depthSeed * PARTICLE_SPREAD;
        const density = 1 - depth / PARTICLE_SPREAD;

        if (Math.random() > density) continue;

        const p = pointOnPerimeter(along);
        const px = p.x + p.nx * depth;
        const py = p.y + p.ny * depth;
        const size = 0.8 + density * 0.6;

        ctx.globalAlpha = fade * density * 0.85;
        ctx.beginPath();
        ctx.arc(px, py, size, 0, Math.PI * 2);
        ctx.fill();
      }

      // ── Waveform ──
      const midY = h / 2;
      const waves = [
        { freq: 3, amp: 0.35, speed: 2.5, opacity: 0.9, width: 1.8 },
        { freq: 5, amp: 0.2, speed: 3.5, opacity: 0.5, width: 1.2 },
        { freq: 7, amp: 0.12, speed: 5, opacity: 0.3, width: 0.8 },
      ];

      for (const wave of waves) {
        ctx.beginPath();
        ctx.strokeStyle = dangerColor;
        ctx.globalAlpha = wave.opacity * fade;
        ctx.lineWidth = wave.width;
        ctx.lineCap = "round";
        ctx.lineJoin = "round";

        for (let x = 0; x <= w; x++) {
          const norm = x / w;
          const envelope = Math.sin(norm * Math.PI);
          const y =
            midY +
            Math.sin(norm * Math.PI * 2 * wave.freq + elapsed * wave.speed) *
              (midY * wave.amp) *
              envelope;
          if (x === 0) ctx.moveTo(x, y);
          else ctx.lineTo(x, y);
        }
        ctx.stroke();
      }

      ctx.globalAlpha = 1;
      this._animFrame = requestAnimationFrame(draw);
    };

    this._animFrame = requestAnimationFrame(draw);
  }

  _stopWaveformAnimation() {
    if (this._animFrame) {
      cancelAnimationFrame(this._animFrame);
      this._animFrame = null;
    }
    const canvas = this.shadowRoot.querySelector(".analyze-canvas");
    if (canvas) {
      const ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
  }

  scrollToBottom() {
    setTimeout(() => {
      const container = this.shadowRoot.querySelector(".response-container");
      if (container) {
        container.scrollTop = container.scrollHeight;
      }
    }, 0);
  }

  firstUpdated() {
    super.firstUpdated();
    this.updateResponseContent();
  }

  updated(changedProperties) {
    super.updated(changedProperties);
    if (
      changedProperties.has("responses") ||
      changedProperties.has("currentResponseIndex")
    ) {
      this.updateResponseContent();
    }

    if (changedProperties.has("isAnalyzing")) {
      if (this.isAnalyzing) {
        this._startWaveformAnimation();
      } else {
        this._stopWaveformAnimation();
      }
    }

    if (
      changedProperties.has("responses") &&
      (this.isAnalyzing || this.isExpanding)
    ) {
      if (this.responses.length > this._responseCountWhenStarted) {
        this.isAnalyzing = false;
        this.isExpanding = false;
      }
    }
  }

  updateResponseContent() {
    const container = this.shadowRoot.querySelector("#responseContainer");
    if (container) {
      const currentResponse = this.getCurrentResponse();
      const renderedResponse = this.renderMarkdown(currentResponse);
      container.innerHTML = renderedResponse;
      
      // Apply syntax highlighting to code blocks
      this.applyCodeHighlighting(container);
      
      if (this.shouldAnimateResponse) {
        this.dispatchEvent(
          new CustomEvent("response-animation-complete", {
            bubbles: true,
            composed: true,
          }),
        );
      }
    }
  }

  render() {
    const hasMultipleResponses = this.responses.length > 1;
    const hasResponse =
      this.responses.length > 0 && this.currentResponseIndex >= 0;

    return html`
      <div class="response-container" id="responseContainer"></div>

      ${hasMultipleResponses || hasResponse
        ? html`
            <div class="response-nav">
              ${hasMultipleResponses
                ? html`
                    <button
                      class="nav-btn"
                      @click=${this.navigateToPreviousResponse}
                      ?disabled=${this.currentResponseIndex <= 0}
                      title="Previous response"
                    >
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 20 20"
                        fill="currentColor"
                      >
                        <path
                          fill-rule="evenodd"
                          d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z"
                          clip-rule="evenodd"
                        />
                      </svg>
                    </button>
                    <span class="response-counter"
                      >${this.currentResponseIndex + 1} of
                      ${this.responses.length}</span
                    >
                    <button
                      class="nav-btn"
                      @click=${this.navigateToNextResponse}
                      ?disabled=${this.currentResponseIndex >=
                      this.responses.length - 1}
                      title="Next response"
                    >
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 20 20"
                        fill="currentColor"
                      >
                        <path
                          fill-rule="evenodd"
                          d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z"
                          clip-rule="evenodd"
                        />
                      </svg>
                    </button>
                  `
                : ""}
              ${hasResponse
                ? html`
                    <button
                      class="expand-btn"
                      @click=${this.handleExpandResponse}
                      ?disabled=${this.isExpanding}
                      title="Expand this response with more detail"
                    >
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 20 20"
                        fill="currentColor"
                      >
                        <path
                          fill-rule="evenodd"
                          d="M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.938a.75.75 0 1 1 1.08 1.04l-4.25 4.5a.75.75 0 0 1-1.08 0l-4.25-4.5a.75.75 0 0 1 .02-1.06Z"
                          clip-rule="evenodd"
                        />
                      </svg>
                      ${this.isExpanding ? "Expanding..." : "Expand"}
                    </button>
                  `
                : ""}
            </div>
          `
        : ""}

      <div class="input-bar">
        <div class="input-bar-inner">
          <input
            type="text"
            id="textInput"
            placeholder="Type a message..."
            @keydown=${this.handleTextKeydown}
          />
        </div>
        <button
          class="analyze-btn ${this.isAnalyzing ? "analyzing" : ""}"
          @click=${this.handleScreenAnswer}
        >
          <canvas class="analyze-canvas"></canvas>
          <span class="analyze-btn-content">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="14"
              height="14"
              viewBox="0 0 24 24"
            >
              <path
                fill="none"
                stroke="currentColor"
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M13 3v7h6l-8 11v-7H5z"
              />
            </svg>
            Analyze Screen
          </span>
        </button>
      </div>
    `;
  }
}

customElements.define("assistant-view", AssistantView);
