'use client'

import React, { useState, useMemo, useCallback, useEffect } from 'react'
import { Copy, Check, Spinner, Code, MagnifyingGlass } from '@phosphor-icons/react'
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip'
import { CodeViewer, type SupportedLanguage } from './code-editor'
import {
  generateCodeAsync,
  getCodegenByCategory,
  getMonacoLanguage,
  type CodegenName,
} from '@/lib/api-docs/codegen'
import type { BrainfishRESTRequest } from '@/lib/api-docs/types'

interface CodeSnippetProps {
  request: BrainfishRESTRequest
  defaultLanguage?: CodegenName
  className?: string
}

export function CodeSnippet({
  request,
  defaultLanguage = 'shell-curl',
  className = '',
}: CodeSnippetProps) {
  const [selectedLanguage, setSelectedLanguage] = useState<CodegenName>(defaultLanguage)
  const [copied, setCopied] = useState(false)
  const [searchQuery, setSearchQuery] = useState('')
  const [generatedCode, setGeneratedCode] = useState<string>('// Loading...')
  const [isLoading, setIsLoading] = useState(true)

  // Get codegen definitions grouped by category
  const codegenByCategory = useMemo(() => getCodegenByCategory(), [])

  // Filter definitions based on search
  const filteredCategories = useMemo(() => {
    if (!searchQuery) return codegenByCategory

    const filtered: typeof codegenByCategory = {}
    const query = searchQuery.toLowerCase()

    for (const [category, definitions] of Object.entries(codegenByCategory)) {
      const matchedDefs = definitions.filter(
        (def) =>
          def.caption.toLowerCase().includes(query) ||
          def.category.toLowerCase().includes(query) ||
          def.lang.toLowerCase().includes(query)
      )
      if (matchedDefs.length > 0) {
        filtered[category] = matchedDefs
      }
    }

    return filtered
  }, [codegenByCategory, searchQuery])

  // Generate code async when language or request changes
  useEffect(() => {
    let cancelled = false
    setIsLoading(true)

    generateCodeAsync(selectedLanguage, request).then((result) => {
      if (!cancelled) {
        setGeneratedCode(result.success ? result.code || '' : `// Error: ${result.error}`)
        setIsLoading(false)
      }
    })

    return () => {
      cancelled = true
    }
  }, [selectedLanguage, request])

  // Get Monaco language for syntax highlighting
  const monacoLanguage = useMemo(
    () => getMonacoLanguage(selectedLanguage),
    [selectedLanguage]
  )

  // Handle copy to clipboard
  const handleCopy = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(generatedCode)
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    } catch (err) {
      console.error('Failed to copy:', err)
    }
  }, [generatedCode])

  // Get current language display name
  const currentLanguageDisplay = useMemo(() => {
    for (const definitions of Object.values(codegenByCategory)) {
      const found = definitions.find((def) => def.name === selectedLanguage)
      if (found) {
        return `${found.category} - ${found.caption}`
      }
    }
    return selectedLanguage
  }, [codegenByCategory, selectedLanguage])

  return (
    <div className={`flex flex-col h-full ${className}`}>
      {/* Header */}
      <div className="flex items-center justify-between gap-2 border-b border-border bg-muted/30 px-4 py-2">
        <div className="flex items-center gap-2 flex-1">
          <Code size={16} className="text-muted-foreground" />
          <span className="text-sm font-medium text-muted-foreground">Code Snippet</span>
        </div>

        {/* Language Selector */}
        <Select
          value={selectedLanguage}
          onValueChange={(value) => setSelectedLanguage(value as CodegenName)}
        >
          <SelectTrigger className="w-[200px] h-8 text-xs">
            <SelectValue placeholder="Select language">
              {currentLanguageDisplay}
            </SelectValue>
          </SelectTrigger>
          <SelectContent className="max-h-[300px]">
            {/* Search */}
            <div className="sticky top-0 bg-popover p-2 border-b border-border">
              <div className="relative">
                <MagnifyingGlass
                  size={14}
                  className="absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground"
                />
                <Input
                  placeholder="Search languages..."
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                  className="h-7 pl-7 text-xs"
                />
              </div>
            </div>

            {/* Grouped languages */}
            {Object.entries(filteredCategories).map(([category, definitions]) => (
              <SelectGroup key={category}>
                <SelectLabel className="text-xs text-muted-foreground font-medium px-2 py-1">
                  {category}
                </SelectLabel>
                {definitions.map((def) => (
                  <SelectItem
                    key={def.name}
                    value={def.name}
                    className="text-xs pl-4"
                  >
                    <div className="flex items-center gap-2">
                      <span>{def.caption}</span>
                      {def.name === selectedLanguage && (
                        <Check size={12} className="text-primary" />
                      )}
                    </div>
                  </SelectItem>
                ))}
              </SelectGroup>
            ))}

            {Object.keys(filteredCategories).length === 0 && (
              <div className="p-4 text-center text-sm text-muted-foreground">
                No languages found for &ldquo;{searchQuery}&rdquo;
              </div>
            )}
          </SelectContent>
        </Select>

        {/* Copy Button */}
        <TooltipProvider>
          <Tooltip>
            <TooltipTrigger asChild>
              <Button
                variant="ghost"
                size="icon"
                className="h-8 w-8"
                onClick={handleCopy}
                disabled={isLoading}
              >
                {copied ? (
                  <Check size={16} className="text-green-500" />
                ) : (
                  <Copy size={16} />
                )}
              </Button>
            </TooltipTrigger>
            <TooltipContent>
              <p>{copied ? 'Copied!' : 'Copy to clipboard'}</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </div>

      {/* Code Display */}
      <div className="flex-1 min-h-0 relative">
        {isLoading && (
          <div className="absolute inset-0 flex items-center justify-center bg-background/80 z-10">
            <Spinner size={24} className="animate-spin text-muted-foreground" />
          </div>
        )}
        <CodeViewer
          value={generatedCode}
          language={monacoLanguage as SupportedLanguage}
          height="100%"
          theme="dark"
          showLineNumbers={false}
          className="border-0"
        />
      </div>
    </div>
  )
}

/**
 * Compact version for sidebar - styled like the reference image
 */
interface CodeSnippetCompactProps {
  request: BrainfishRESTRequest
}

// Method color mapping
const methodColors: Record<string, string> = {
  GET: 'text-green-400',
  POST: 'text-blue-400',
  PUT: 'text-orange-400',
  PATCH: 'text-yellow-400',
  DELETE: 'text-red-400',
  HEAD: 'text-purple-400',
  OPTIONS: 'text-gray-400',
}

export function CodeSnippetCompact({ request }: CodeSnippetCompactProps) {
  const [selectedLanguage, setSelectedLanguage] = useState<CodegenName>('shell-curl')
  const [copied, setCopied] = useState(false)
  const [generatedCode, setGeneratedCode] = useState<string>('// Loading...')
  const [isLoading, setIsLoading] = useState(true)

  const codegenByCategory = useMemo(() => getCodegenByCategory(), [])

  // Generate code async when language or request changes
  useEffect(() => {
    let cancelled = false
    setIsLoading(true)

    generateCodeAsync(selectedLanguage, request).then((result) => {
      if (!cancelled) {
        setGeneratedCode(result.success ? result.code || '' : `// Error: ${result.error}`)
        setIsLoading(false)
      }
    })

    return () => {
      cancelled = true
    }
  }, [selectedLanguage, request])

  const monacoLanguage = useMemo(
    () => getMonacoLanguage(selectedLanguage),
    [selectedLanguage]
  )

  const handleCopy = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(generatedCode)
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    } catch (err) {
      console.error('Failed to copy:', err)
    }
  }, [generatedCode])

  const currentCaption = useMemo(() => {
    for (const definitions of Object.values(codegenByCategory)) {
      const found = definitions.find((def) => def.name === selectedLanguage)
      if (found) return `${found.category} ${found.caption}`
    }
    return 'Shell Curl'
  }, [codegenByCategory, selectedLanguage])

  // Get shortened endpoint path (decode URL-encoded characters like <<id>>)
  const endpointPath = useMemo(() => {
    try {
      const url = new URL(request.endpoint)
      // Decode URL-encoded characters to show original path placeholders like <<id>>
      return decodeURIComponent(url.pathname)
    } catch {
      return request.endpoint
    }
  }, [request.endpoint])

  return (
    <div className="border-b border-border">
      {/* Dark code block container */}
      <div className="bg-[#1e1e1e] overflow-hidden">
        {/* Header with method, path, and language selector */}
        <div className="flex items-center justify-between px-4 py-2 border-b border-[#333]">
          <div className="flex items-center gap-2 font-mono text-sm">
            <span className={`font-semibold ${methodColors[request.method] || 'text-gray-400'}`}>
              {request.method}
            </span>
            <span className="text-gray-300">{endpointPath}</span>
          </div>
          
          {/* Language Selector */}
          <Select
            value={selectedLanguage}
            onValueChange={(value) => setSelectedLanguage(value as CodegenName)}
          >
            <SelectTrigger className="h-7 w-auto gap-1 border-0 bg-transparent text-gray-300 text-xs hover:bg-[#333] focus:ring-0 focus:ring-offset-0">
              <SelectValue>{currentCaption}</SelectValue>
            </SelectTrigger>
            <SelectContent className="max-h-[300px]">
              {Object.entries(codegenByCategory).map(([category, definitions]) => (
                <SelectGroup key={category}>
                  <SelectLabel className="text-xs">{category}</SelectLabel>
                  {definitions.map((def) => (
                    <SelectItem key={def.name} value={def.name} className="text-xs">
                      {def.caption}
                    </SelectItem>
                  ))}
                </SelectGroup>
              ))}
            </SelectContent>
          </Select>
        </div>

        {/* Code Display */}
        <div className="relative bg-[#1e1e1e] dark-editor">
          {isLoading && (
            <div className="absolute inset-0 flex items-center justify-center bg-[#1e1e1e]/80 z-10">
              <Spinner size={20} className="animate-spin text-gray-400" />
            </div>
          )}
          <CodeViewer
            value={generatedCode}
            language={monacoLanguage as SupportedLanguage}
            height="auto"
            minHeight={80}
            maxHeight={200}
            theme="dark"
            showLineNumbers={false}
            className="!bg-[#1e1e1e]"
          />
        </div>
      </div>

      {/* Copy button row */}
      <div className="flex justify-end px-2 py-1 bg-muted/30">
        <Button
          variant="ghost"
          size="sm"
          className="h-6 text-xs gap-1"
          onClick={handleCopy}
          disabled={isLoading}
        >
          {copied ? (
            <>
              <Check size={12} className="text-green-500" />
              Copied
            </>
          ) : (
            <>
              <Copy size={12} />
              Copy
            </>
          )}
        </Button>
      </div>
    </div>
  )
}
