import { html } from 'lit'
import type { FunctionSchema } from '@pawel-up/jexl/schemas/types.js'
import reactive from '../../../src/decorators/reactive.js'
import { DemoPage } from '../../../src/demo/DemoPage.js'
import type {
  Suggestion,
  FunctionInsertEvent,
  SuggestionInsertEvent,
} from '../../../src/elements/code-editor/code-editor.js'
import '../../../src/elements/code-editor/code-editor.js'

class CodeEditorDemo extends DemoPage {
  override accessor componentName = 'Code Editor'

  @reactive()
  private accessor output = ''

  @reactive()
  private accessor editorValue = [
    '// Start typing function names or {{ mentions }}',
    'console.log("Hello, world!")',
    '',
    '// Try: getData, processData, or @John, @Jane',
    '// Example: Ask {{John}} about the API design',
    '// Example: {{Jane}} can review the implementation',
    '',
    '"Hello {{John}}! Can you help with the " + getData() + " function?"',
  ].join('\n')

  private functionSchemas: FunctionSchema[] = [
    {
      name: 'getData',
      description: 'Fetches data from the server',
      parameters: [
        {
          name: 'url',
          schema: { type: 'string', description: 'The URL to fetch data from' },
          required: true,
        },
        {
          name: 'options',
          schema: { type: 'object', description: 'Fetch options' },
          required: false,
        },
      ],
      returns: {
        type: 'object',
        description: 'The fetched data as an object',
      },
      category: 'network',
    },
    {
      name: 'processData',
      description: 'Processes raw data into a usable format',
      parameters: [
        {
          name: 'data',
          schema: { description: 'Raw data to process' },
          required: true,
        },
        {
          name: 'transformer',
          schema: { description: 'Optional transformer function' },
          required: false,
        },
      ],
      returns: {},
      category: 'data',
    },
    {
      category: 'validation',
      name: 'validateInput',
      description: 'Validates user input against a schema',
      parameters: [
        {
          name: 'input',
          schema: { type: 'object', description: 'The input to validate' },
          required: true,
        },
        {
          name: 'schema',
          schema: { type: 'object', description: 'Validation schema' },
          required: true,
        },
      ],
      returns: { type: 'object', description: 'Validation result' },
    },
  ]

  private suggestions: Suggestion[] = [
    {
      id: 'user-john',
      label: 'John',
      description: 'Software Engineer',
      suffix: 'Engineering',
      data: { role: 'developer', department: 'engineering' },
    },
    {
      id: 'user-jane',
      label: 'Jane',
      description: 'Product Manager',
      suffix: 'Product',
      data: { role: 'manager', department: 'product' },
    },
    {
      id: 'admin-system',
      label: 'System',
      description: 'System Administrator',
      suffix: 'Admin',
      data: { role: 'admin', department: 'infrastructure' },
    },
  ]

  private handleFunctionInsert(event: CustomEvent<FunctionInsertEvent>): void {
    const { functionSchema, position } = event.detail
    this.output = `Function inserted: ${functionSchema.name} at position ${position}`
  }

  private handleSuggestionInsert(event: CustomEvent<SuggestionInsertEvent>): void {
    const { suggestion, position } = event.detail
    this.output = `Suggestion inserted: ${suggestion.label} at position ${position}`
  }

  private handleInput(event: Event): void {
    const target = event.target as HTMLElement & { value: string }
    this.editorValue = target.value
  }

  contentTemplate() {
    return html`
      <a href="../">Back</a>

      <section class="demo-section">
        <h2 class="display-large">Basic Code Editor</h2>
        <p>A CodeMirror 6 based editor with function autocomplete and suggestion pills.</p>

        <code-editor
          label="Code Editor"
          supporting-text="Type function names or {{fnName}} to see autocomplete"
          .value=${this.editorValue}
          .functionSchemas=${this.functionSchemas}
          .suggestions=${this.suggestions}
          @function-insert=${this.handleFunctionInsert}
          @suggestion-insert=${this.handleSuggestionInsert}
          @input=${this.handleInput}
        ></code-editor>

        ${this.output ? html`<p><strong>Output:</strong> ${this.output}</p>` : ''}
      </section>

      <section class="demo-section">
        <h2 class="display-large">Dark Theme</h2>
        <p>The same editor with dark theme enabled.</p>

        <code-editor
          label="Dark Theme Editor"
          supporting-text="Dark theme variant"
          .value=${'// Dark theme example\nconst theme = "dark"'}
          .functionSchemas=${this.functionSchemas}
          .suggestions=${this.suggestions}
          dark-theme
        ></code-editor>
      </section>

      <section class="demo-section">
        <h2 class="display-large">Disabled State</h2>
        <p>A disabled editor for read-only content.</p>

        <code-editor
          label="Disabled Editor"
          supporting-text="This editor is disabled"
          .value=${'// This editor is disabled\nconst readOnly = true'}
          .functionSchemas=${this.functionSchemas}
          .suggestions=${this.suggestions}
          disabled
        ></code-editor>
      </section>

      <section class="demo-section">
        <h2 class="display-large">Error State</h2>
        <p>An editor in error state.</p>

        <code-editor
          label="Error Editor"
          supporting-text="This editor has an error"
          .value=${'// This editor has an error\nconst invalid = true'}
          .functionSchemas=${this.functionSchemas}
          .suggestions=${this.suggestions}
          invalid
        ></code-editor>
      </section>

      <section class="demo-section">
        <h2 class="display-large">Function Schemas</h2>
        <p>Available function schemas for autocomplete:</p>
        <pre>${JSON.stringify(this.functionSchemas, null, 2)}</pre>
      </section>

      <section class="demo-section">
        <h2 class="display-large">Suggestions</h2>
        <p>Available suggestions (use @mention syntax):</p>
        <pre>${JSON.stringify(this.suggestions, null, 2)}</pre>
      </section>
    `
  }
}

const instance = new CodeEditorDemo()
instance.render()
