'use client'

import { useState, useEffect } from 'react'
import { FileText, WarningCircle } from '@phosphor-icons/react'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import type { BrainfishRESTReqBody } from '@/lib/api-docs/types'
import { KeyValueEditor, KeyValueItem } from './key-value-editor'
import { CodeEditor, SupportedLanguage } from './code-editor'
import { cn } from '@/lib/utils'

type ContentType = BrainfishRESTReqBody['contentType']

const CONTENT_TYPES: { label: string; value: string; language?: SupportedLanguage }[] = [
  { label: 'None', value: 'none' },
  { label: 'JSON', value: 'application/json', language: 'json' },
  { label: 'XML', value: 'application/xml', language: 'xml' },
  { label: 'Plain Text', value: 'text/plain', language: 'plaintext' },
  { label: 'HTML', value: 'text/html', language: 'html' },
  { label: 'Form URL Encoded', value: 'application/x-www-form-urlencoded' },
  { label: 'Multipart Form', value: 'multipart/form-data' },
  { label: 'Binary', value: 'application/octet-stream' },
]

interface BodyEditorProps {
  body: string | null
  contentType: ContentType
  onBodyChange: (body: string | null) => void
  onContentTypeChange: (contentType: ContentType) => void
  /** Show error styling to indicate this section needs attention */
  showError?: boolean
}

export function BodyEditor({
  body,
  contentType,
  onBodyChange,
  onContentTypeChange,
  showError = false,
}: BodyEditorProps) {
  const [formData, setFormData] = useState<KeyValueItem[]>([])

  // Parse form data from body when content type changes
  useEffect(() => {
    if (contentType === 'application/x-www-form-urlencoded' || contentType === 'multipart/form-data') {
      try {
        if (body) {
          const parsed = JSON.parse(body)
          if (Array.isArray(parsed)) {
            setFormData(parsed.map((item: { key: string; value: string }, i: number) => ({
              id: `form_${i}`,
              key: item.key || '',
              value: item.value || '',
              active: true,
            })))
          }
        }
      } catch {
        setFormData([])
      }
    }
  }, [contentType, body])

  // Default templates for each content type
  const DEFAULT_TEMPLATES: Record<string, string> = {
    'application/json': '{\n  \n}',
    'application/xml': '<?xml version="1.0" encoding="UTF-8"?>\n<root>\n  \n</root>',
    'text/html': '<!DOCTYPE html>\n<html>\n<head>\n  <title></title>\n</head>\n<body>\n  \n</body>\n</html>',
    'text/plain': '',
  }

  // Check if current body is a default template or invalid (should be replaced when switching types)
  const isDefaultTemplate = (currentBody: string | null): boolean => {
    if (!currentBody || currentBody.trim() === '' || currentBody.trim() === 'null') return true
    return Object.values(DEFAULT_TEMPLATES).some(
      template => currentBody.trim() === template.trim()
    )
  }

  // Normalize body value - convert "null" string to empty
  const normalizedBody = (body === 'null' || body === null) ? '' : body

  const handleContentTypeChange = (value: string) => {
    console.log('[BodyEditor] Content type changed to:', value)
    const newType = value === 'none' ? null : value as ContentType
    onContentTypeChange(newType)
    
    // Set default body content based on type
    if (newType === null) {
      onBodyChange(null)
    } else if (isDefaultTemplate(body)) {
      // Replace with new template if current body is empty or a default template
      const template = DEFAULT_TEMPLATES[newType] ?? ''
      onBodyChange(template)
    }
    // If body has custom content, keep it when switching types
  }

  const handleFormDataChange = (items: KeyValueItem[]) => {
    setFormData(items)
    onBodyChange(JSON.stringify(items.map(({ key, value }) => ({ key, value }))))
  }

  const currentValue = contentType || 'none'
  const currentTypeInfo = CONTENT_TYPES.find((t) => t.value === currentValue)
  const editorLanguage = currentTypeInfo?.language || 'plaintext'

  // Content type selector header component
  const ContentTypeHeader = () => (
    <div className={cn(
      "flex items-center border-b bg-muted/30 px-4 py-2",
      showError ? "border-red-500 bg-red-500/5" : "border-border"
    )}>
      {showError && (
        <WarningCircle className="h-4 w-4 text-red-500 animate-pulse mr-2" weight="fill" />
      )}
      <span className={cn(
        "text-xs font-medium mr-3",
        showError ? "text-red-500" : "text-muted-foreground"
      )}>
        {showError ? "Body needs attention" : "Type"}
      </span>
      <Select value={currentValue} onValueChange={handleContentTypeChange}>
        <SelectTrigger className="h-8 w-auto min-w-[140px] text-sm border-0 bg-transparent hover:bg-muted/50">
          <SelectValue placeholder="Select type" />
        </SelectTrigger>
        <SelectContent>
          {CONTENT_TYPES.map((type) => (
            <SelectItem key={type.value} value={type.value}>
              {type.label}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  )

  // Form data editors (URL encoded, multipart)
  if (contentType === 'application/x-www-form-urlencoded' || contentType === 'multipart/form-data') {
    return (
      <div className="flex flex-col h-full">
        <ContentTypeHeader />
        <div className="flex-1 overflow-auto">
          <KeyValueEditor
            items={formData}
            onChange={handleFormDataChange}
            title={contentType === 'multipart/form-data' ? 'Form Data' : 'URL Encoded'}
            keyLabel="Field"
            valueLabel="Value"
            showDescription={false}
          />
        </div>
      </div>
    )
  }

  // Binary file (placeholder)
  if (contentType === 'application/octet-stream') {
    return (
      <div className="flex flex-col h-full">
        <ContentTypeHeader />
        <div className="flex-1 flex flex-col items-center justify-center p-8 text-center">
          <FileText className="h-10 w-10 text-muted-foreground/50 mb-3" weight="duotone" />
          <p className="text-sm text-muted-foreground">Binary file upload not supported</p>
        </div>
      </div>
    )
  }

  // No body
  if (contentType === null) {
    return (
      <div className="flex flex-col h-full">
        <ContentTypeHeader />
        <div className="flex-1 flex flex-col items-center justify-center p-8 text-center">
          <FileText className="h-10 w-10 text-muted-foreground/50 mb-3" weight="duotone" />
          <p className="text-sm text-muted-foreground">No request body</p>
          <p className="text-xs text-muted-foreground/70 mt-1">Select a type to add body</p>
        </div>
      </div>
    )
  }

  // Monaco editor for JSON, XML, Text, HTML
  const editorValue = normalizedBody || ''
  
  // Placeholder text based on content type
  const placeholderMap: Record<string, string> = {
    'application/json': 'Enter JSON body...',
    'application/xml': 'Enter XML body...',
    'text/html': 'Enter HTML body...',
    'text/plain': 'Enter text...',
  }
  
  const placeholder = placeholderMap[contentType || ''] || 'Enter request body...'
  
  return (
    <div className="flex flex-col h-full">
      <ContentTypeHeader />
      <div className="flex-1 dark-editor h-full">
        <CodeEditor
          key={`editor-${contentType}`}
          value={editorValue}
          onChange={onBodyChange}
          language={editorLanguage}
          height="100%"
          theme="dark"
          showLineNumbers={false}
          showBorder={false}
          rounded={false}
          placeholder={placeholder}
        />
      </div>
    </div>
  )
}
