'use client'

import { useState } from 'react'
import { CaretDown, CaretRight, Plus, Minus } from '@phosphor-icons/react'

interface SchemaProperty {
  type?: string
  description?: string
  format?: string
  example?: unknown
  properties?: Record<string, SchemaProperty>
  items?: SchemaProperty
  required?: string[]
  allOf?: SchemaProperty[]
  oneOf?: SchemaProperty[]
  anyOf?: SchemaProperty[]
  enum?: unknown[]
  default?: unknown
}

interface SchemaViewerProps {
  schema: SchemaProperty | string | unknown
  requiredFields?: string[]
  level?: number
}

function getTypeLabel(prop: SchemaProperty): string {
  if (prop.type === 'array' && prop.items) {
    const itemType = prop.items.type || 'object'
    return `${itemType}[]`
  }
  return prop.type || 'object'
}

function hasChildProperties(prop: SchemaProperty): boolean {
  if (prop.properties && Object.keys(prop.properties).length > 0) {
    return true
  }
  if (prop.type === 'array' && prop.items?.properties) {
    return true
  }
  if (prop.allOf || prop.oneOf || prop.anyOf) {
    return true
  }
  return false
}

function PropertyRow({
  name,
  prop,
  isRequired,
  level = 0,
}: {
  name: string
  prop: SchemaProperty
  isRequired: boolean
  level?: number
}) {
  const [showChildren, setShowChildren] = useState(false)
  const hasChildren = hasChildProperties(prop)
  const typeLabel = getTypeLabel(prop)

  // Get child properties
  const getChildProperties = (): Record<string, SchemaProperty> | null => {
    if (prop.properties) {
      return prop.properties
    }
    if (prop.type === 'array' && prop.items?.properties) {
      return prop.items.properties
    }
    if (prop.allOf) {
      // Merge all schemas
      const merged: Record<string, SchemaProperty> = {}
      prop.allOf.forEach((schema) => {
        if (schema.properties) {
          Object.assign(merged, schema.properties)
        }
      })
      return Object.keys(merged).length > 0 ? merged : null
    }
    return null
  }

  const getChildRequired = (): string[] => {
    if (prop.required) return prop.required
    if (prop.type === 'array' && prop.items?.required) {
      return prop.items.required
    }
    if (prop.allOf) {
      const allRequired: string[] = []
      prop.allOf.forEach((schema) => {
        if (schema.required) {
          allRequired.push(...schema.required)
        }
      })
      return allRequired
    }
    return []
  }

  const childProps = getChildProperties()
  const childRequired = getChildRequired()

  return (
    <div className={`${level > 0 ? 'border-l-2 border-muted pl-4 ml-2' : ''}`}>
      <div className="py-3 border-b border-border/50">
        <div className="flex items-start gap-2 flex-wrap">
          <span className="font-semibold text-sm text-foreground">{name}</span>
          <span className="text-xs text-muted-foreground">{typeLabel}</span>
          {prop.format && (
            <>
              <span className="text-xs text-muted-foreground">·</span>
              <span className="text-xs text-muted-foreground">{prop.format}</span>
            </>
          )}
          {isRequired && (
            <span className="text-xs text-orange-500 font-medium">required</span>
          )}
          {prop.example !== undefined && (
            <button className="text-xs text-muted-foreground hover:text-foreground underline">
              Example
            </button>
          )}
        </div>
        {prop.description && (
          <p className="text-sm text-muted-foreground mt-1">{prop.description}</p>
        )}
        {prop.enum && (
          <div className="mt-2 flex flex-wrap gap-1">
            <span className="text-xs text-muted-foreground">Enum:</span>
            {prop.enum.map((val, idx) => (
              <code key={idx} className="text-xs bg-muted px-1.5 py-0.5 rounded">
                {JSON.stringify(val)}
              </code>
            ))}
          </div>
        )}
        {prop.default !== undefined && (
          <div className="mt-1">
            <span className="text-xs text-muted-foreground">Default: </span>
            <code className="text-xs bg-muted px-1.5 py-0.5 rounded">
              {JSON.stringify(prop.default)}
            </code>
          </div>
        )}
        {hasChildren && childProps && (
          <button
            onClick={() => setShowChildren(!showChildren)}
            className="mt-2 flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground border rounded-full px-3 py-1 hover:bg-muted/50 transition-colors"
          >
            {showChildren ? (
              <>
                <Minus className="h-3 w-3" weight="bold" />
                Hide Child Attributes
              </>
            ) : (
              <>
                <Plus className="h-3 w-3" weight="bold" />
                Show Child Attributes
              </>
            )}
          </button>
        )}
      </div>
      {showChildren && childProps && (
        <div className="mt-2">
          {Object.entries(childProps).map(([childName, childProp]) => (
            <PropertyRow
              key={childName}
              name={childName}
              prop={childProp}
              isRequired={childRequired.includes(childName)}
              level={level + 1}
            />
          ))}
        </div>
      )}
    </div>
  )
}

export function SchemaViewer({ schema, requiredFields = [], level = 0 }: SchemaViewerProps) {
  // Parse schema if it's a string
  let parsedSchema: SchemaProperty
  try {
    if (typeof schema === 'string') {
      parsedSchema = JSON.parse(schema)
    } else {
      parsedSchema = schema as SchemaProperty
    }
  } catch {
    // If parsing fails, show raw content
    return (
      <pre className="text-xs text-muted-foreground p-3 bg-muted/50 rounded overflow-auto">
        {typeof schema === 'string' ? schema : JSON.stringify(schema, null, 2)}
      </pre>
    )
  }

  // Handle nested schema property (common in OpenAPI responses)
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  if ((parsedSchema as any).schema) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    parsedSchema = (parsedSchema as any).schema as SchemaProperty
  }

  // Handle allOf, oneOf, anyOf at root level
  if (parsedSchema.allOf) {
    const mergedProps: Record<string, SchemaProperty> = {}
    const mergedRequired: string[] = []
    parsedSchema.allOf.forEach((s) => {
      if (s.properties) Object.assign(mergedProps, s.properties)
      if (s.required) mergedRequired.push(...s.required)
    })
    parsedSchema = { ...parsedSchema, properties: mergedProps, required: mergedRequired }
  }

  const properties = parsedSchema.properties || {}
  const required = parsedSchema.required || requiredFields

  if (Object.keys(properties).length === 0) {
    // No properties - maybe it's a simple type
    if (parsedSchema.type) {
      return (
        <div className="py-2">
          <span className="text-xs text-muted-foreground">{parsedSchema.type}</span>
          {parsedSchema.description && (
            <p className="text-sm text-muted-foreground mt-1">{parsedSchema.description}</p>
          )}
        </div>
      )
    }
    return (
      <pre className="text-xs text-muted-foreground p-3 bg-muted/50 rounded overflow-auto">
        {JSON.stringify(parsedSchema, null, 2)}
      </pre>
    )
  }

  return (
    <div className={level > 0 ? 'pl-4 border-l-2 border-muted' : ''}>
      {Object.entries(properties).map(([name, prop]) => (
        <PropertyRow
          key={name}
          name={name}
          prop={prop}
          isRequired={required.includes(name)}
          level={level}
        />
      ))}
    </div>
  )
}

// Collapsible response component with schema view
interface ResponseSchemaProps {
  code: number
  status: string
  description?: string
  schema: unknown
  contentType?: string
}

export function ResponseSchema({
  code,
  status,
  description,
  schema,
  contentType = 'application/json',
}: ResponseSchemaProps) {
  const [isOpen, setIsOpen] = useState(code >= 200 && code < 300)
  const [viewMode, setViewMode] = useState<'schema' | 'example'>('schema')

  // Try to parse schema
  let parsedSchema: SchemaProperty | null = null
  try {
    if (typeof schema === 'string') {
      parsedSchema = JSON.parse(schema)
    } else {
      parsedSchema = schema as SchemaProperty
    }
    // Handle nested schema property
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    if (parsedSchema && (parsedSchema as any).schema) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      parsedSchema = (parsedSchema as any).schema as SchemaProperty
    }
  } catch {
    parsedSchema = null
  }

  const typeLabel = parsedSchema?.type || 'object'

  return (
    <div className="border-b border-border">
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="w-full py-3 flex items-center gap-3 hover:bg-muted/30 transition-colors text-left"
      >
        {isOpen ? (
          <CaretDown className="h-4 w-4 text-muted-foreground shrink-0" weight="bold" />
        ) : (
          <CaretRight className="h-4 w-4 text-muted-foreground shrink-0" weight="bold" />
        )}
        <span
          className={`font-semibold text-sm ${
            code >= 200 && code < 300
              ? 'text-green-600'
              : code >= 400
                ? 'text-red-500'
                : 'text-orange-500'
          }`}
        >
          {code}
        </span>
        <span className="text-sm text-muted-foreground truncate">
          {description || status}
        </span>
      </button>

      {isOpen && (
        <div className="pb-4 pl-7">
          {/* Type and content type row */}
          <div className="flex items-center justify-between mb-3">
            <div className="flex items-center gap-2">
              <span className="text-xs text-muted-foreground">{typeLabel}</span>
              <button
                onClick={() => setViewMode(viewMode === 'schema' ? 'example' : 'schema')}
                className={`text-xs underline ${viewMode === 'example' ? 'text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
              >
                Example
              </button>
            </div>
            <span className="text-xs text-muted-foreground font-mono">{contentType}</span>
          </div>

          {/* Schema or Example view */}
          {viewMode === 'schema' && parsedSchema ? (
            <SchemaViewer schema={parsedSchema} />
          ) : (
            <pre className="text-xs bg-muted/50 p-3 rounded overflow-auto">
              {typeof schema === 'string' ? schema : JSON.stringify(schema, null, 2)}
            </pre>
          )}
        </div>
      )}
    </div>
  )
}
