"use client"

import * as React from "react"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { Badge } from "@/components/ui/badge"
import { ScrollArea } from "@/components/ui/scroll-area"

import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import { 
  Loader, 
  ArrowUpDown, 
  ArrowUp, 
  ArrowDown, 
  GripVertical, 
  RotateCcw,
  Info
} from "lucide-react"
import { toast } from "sonner"
import { cn } from "@/lib/utils"

import { reorderGtcClausesSchema, type ReorderGtcClausesSchema } from "@/lib/gtc-contract/gtc-clauses/validations"
import { reorderGtcClauses, getGtcClausesTree } from "@/lib/gtc-contract/gtc-clauses/service"
import { type GtcClauseTreeView } from "@/db/schema/gtc"
import { useSession } from "next-auth/react"

interface ReorderGtcClausesDialogProps
  extends React.ComponentPropsWithRef<typeof Dialog> {
  documentId: number
  onSuccess?: () => void
}

interface ClauseWithOrder extends GtcClauseTreeView {
  newSortOrder: number
  hasChanges: boolean
  children?: ClauseWithOrder[]
}

export function ReorderGtcClausesDialog({ 
  documentId, 
  onSuccess,
  ...props 
}: ReorderGtcClausesDialogProps) {
  const [isUpdatePending, startUpdateTransition] = React.useTransition()
  const [clauses, setClauses] = React.useState<ClauseWithOrder[]>([])
  const [originalClauses, setOriginalClauses] = React.useState<ClauseWithOrder[]>([])
  const [isLoading, setIsLoading] = React.useState(false)
  const [draggedItem, setDraggedItem] = React.useState<ClauseWithOrder | null>(null)
  const { data: session } = useSession()

  const currentUserId = React.useMemo(() => {
    return session?.user?.id ? Number(session.user.id) : null
  }, [session])

  const form = useForm<ReorderGtcClausesSchema>({
    resolver: zodResolver(reorderGtcClausesSchema),
    defaultValues: {
      clauses: [],
      editReason: "",
    },
  })

  // 조항 데이터 로드
  React.useEffect(() => {
    if (props.open && documentId) {
      loadClauses()
    }
  }, [props.open, documentId])

  const loadClauses = async () => {
    setIsLoading(true)
    try {
      const tree = await getGtcClausesTree(documentId)
      const flatClauses = flattenTreeWithOrder(tree)
      setClauses(flatClauses)
      setOriginalClauses(JSON.parse(JSON.stringify(flatClauses))) // 깊은 복사
    } catch (error) {
      console.error("Error loading clauses:", error)
      toast.error("조항 목록을 불러오는 중 오류가 발생했습니다.")
    } finally {
      setIsLoading(false)
    }
  }

  // 트리를 평면 배열로 변환하면서 순서 정보 추가
  const flattenTreeWithOrder = (tree: any[]): ClauseWithOrder[] => {
    const result: ClauseWithOrder[] = []
    
    function traverse(nodes: any[], parentId: number | null = null) {
      nodes.forEach((node, index) => {
        const clauseWithOrder: ClauseWithOrder = {
          ...node,
          newSortOrder: parseFloat(node.sortOrder),
          hasChanges: false,
        }
        
        result.push(clauseWithOrder)
        
        if (node.children && node.children.length > 0) {
          traverse(node.children, node.id)
        }
      })
    }
    
    traverse(tree)
    return result
  }

  // 조항 순서 변경
  const moveClause = (clauseId: number, direction: 'up' | 'down') => {
    setClauses(prev => {
      const newClauses = [...prev]
      const clauseIndex = newClauses.findIndex(c => c.id === clauseId)
      
      if (clauseIndex === -1) return prev
      
      const clause = newClauses[clauseIndex]
      
      // 같은 부모를 가진 형제 조항들 찾기
      const siblings = newClauses.filter(c => c.parentId === clause.parentId)
      const siblingIndex = siblings.findIndex(c => c.id === clauseId)
      
      if (direction === 'up' && siblingIndex > 0) {
        // 위로 이동
        const targetSibling = siblings[siblingIndex - 1]
        const tempOrder = clause.newSortOrder
        clause.newSortOrder = targetSibling.newSortOrder
        targetSibling.newSortOrder = tempOrder
        
        clause.hasChanges = true
        targetSibling.hasChanges = true
      } else if (direction === 'down' && siblingIndex < siblings.length - 1) {
        // 아래로 이동
        const targetSibling = siblings[siblingIndex + 1]
        const tempOrder = clause.newSortOrder
        clause.newSortOrder = targetSibling.newSortOrder
        targetSibling.newSortOrder = tempOrder
        
        clause.hasChanges = true
        targetSibling.hasChanges = true
      }
      
      // sortOrder로 정렬
      return newClauses.sort((a, b) => {
        if (a.parentId !== b.parentId) {
          // 부모가 다르면 부모 기준으로 정렬
          return (a.parentId || 0) - (b.parentId || 0)
        }
        return a.newSortOrder - b.newSortOrder
      })
    })
  }

  // 변경사항 초기화
  const resetChanges = () => {
    setClauses(JSON.parse(JSON.stringify(originalClauses)))
    toast.success("변경사항이 초기화되었습니다.")
  }

  // 드래그 앤 드롭 핸들러
  const handleDragStart = (e: React.DragEvent, clause: ClauseWithOrder) => {
    setDraggedItem(clause)
    e.dataTransfer.effectAllowed = 'move'
  }

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault()
    e.dataTransfer.dropEffect = 'move'
  }

  const handleDrop = (e: React.DragEvent, targetClause: ClauseWithOrder) => {
    e.preventDefault()
    
    if (!draggedItem || draggedItem.id === targetClause.id) {
      setDraggedItem(null)
      return
    }

    // 같은 부모를 가진 경우에만 순서 변경 허용
    if (draggedItem.parentId === targetClause.parentId) {
      setClauses(prev => {
        const newClauses = [...prev]
        const draggedIndex = newClauses.findIndex(c => c.id === draggedItem.id)
        const targetIndex = newClauses.findIndex(c => c.id === targetClause.id)
        
        if (draggedIndex !== -1 && targetIndex !== -1) {
          const tempOrder = newClauses[draggedIndex].newSortOrder
          newClauses[draggedIndex].newSortOrder = newClauses[targetIndex].newSortOrder
          newClauses[targetIndex].newSortOrder = tempOrder
          
          newClauses[draggedIndex].hasChanges = true
          newClauses[targetIndex].hasChanges = true
        }
        
        return newClauses.sort((a, b) => {
          if (a.parentId !== b.parentId) {
            return (a.parentId || 0) - (b.parentId || 0)
          }
          return a.newSortOrder - b.newSortOrder
        })
      })
    }
    
    setDraggedItem(null)
  }

  async function onSubmit(data: ReorderGtcClausesSchema) {
    startUpdateTransition(async () => {
      if (!currentUserId) {
        toast.error("로그인이 필요합니다")
        return
      }

      // 변경된 조항들만 필터링
      const changedClauses = clauses.filter(c => c.hasChanges).map(c => ({
        id: c.id,
        sortOrder: c.newSortOrder,
        parentId: c.parentId,
        depth: c.depth,
        fullPath: c.fullPath,
      }))

      if (changedClauses.length === 0) {
        toast.error("변경된 조항이 없습니다.")
        return
      }

      try {
        const result = await reorderGtcClauses({
          clauses: changedClauses,
          editReason: data.editReason || "조항 순서 변경",
          updatedById: currentUserId
        })
        
        if (result.error) {
          toast.error(`에러: ${result.error}`)
          return
        }

        form.reset()
        props.onOpenChange?.(false)
        toast.success(`${changedClauses.length}개 조항의 순서가 변경되었습니다.`)
        onSuccess?.()
      } catch (error) {
        toast.error("조항 순서 변경 중 오류가 발생했습니다.")
      }
    })
  }

  function handleDialogOpenChange(nextOpen: boolean) {
    if (!nextOpen) {
      form.reset()
      setClauses([])
      setOriginalClauses([])
    }
    props.onOpenChange?.(nextOpen)
  }

  const changedCount = clauses.filter(c => c.hasChanges).length
  const groupedClauses = groupClausesByParent(clauses)

  return (
    <Dialog {...props} onOpenChange={handleDialogOpenChange}>
      <DialogContent className="max-w-4xl h-[90vh] flex flex-col">
        <DialogHeader className="flex-shrink-0">
          <DialogTitle className="flex items-center gap-2">
            <ArrowUpDown className="h-5 w-5" />
            조항 순서 변경
          </DialogTitle>
          <DialogDescription>
            드래그 앤 드롭 또는 화살표 버튼으로 조항의 순서를 변경하세요. 같은 계층 내에서만 순서 변경이 가능합니다.
          </DialogDescription>
        </DialogHeader>

        {/* 상태 정보 */}
        <div className="flex items-center justify-between p-3 bg-muted/50 rounded-lg flex-shrink-0">
          <div className="flex items-center gap-4 text-sm">
            <div className="flex items-center gap-2">
              <Info className="h-4 w-4 text-muted-foreground" />
              <span>총 {clauses.length}개 조항</span>
            </div>
            {changedCount > 0 && (
              <Badge variant="default">
                {changedCount}개 변경됨
              </Badge>
            )}
          </div>
          
          <div className="flex gap-2">
            {changedCount > 0 && (
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={resetChanges}
              >
                <RotateCcw className="mr-2 h-4 w-4" />
                초기화
              </Button>
            )}
          </div>
        </div>

        <Form {...form}>
          <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col flex-1 min-h-0">
            {/* 조항 목록 */}
            <ScrollArea className="flex-1 border rounded-lg">
              {isLoading ? (
                <div className="flex items-center justify-center h-32">
                  <Loader className="h-6 w-6 animate-spin" />
                  <span className="ml-2">조항을 불러오는 중...</span>
                </div>
              ) : (
                <div className="p-4 space-y-2">
                  {Object.entries(groupedClauses).map(([parentInfo, clauses]) => (
                    <ClauseGroup
                      key={parentInfo}
                      parentInfo={parentInfo}
                      clauses={clauses}
                      onMove={moveClause}
                      onDragStart={handleDragStart}
                      onDragOver={handleDragOver}
                      onDrop={handleDrop}
                    />
                  ))}
                </div>
              )}
            </ScrollArea>

            {/* 편집 사유 */}
            <div className="mt-4 flex-shrink-0">
              <FormField
                control={form.control}
                name="editReason"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>편집 사유 (선택사항)</FormLabel>
                    <FormControl>
                      <Textarea
                        placeholder="순서 변경 사유를 입력하세요..."
                        {...field}
                        rows={2}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
            </div>

            <DialogFooter className="flex-shrink-0 border-t pt-4 mt-4">
              <Button
                type="button"
                variant="outline"
                onClick={() => props.onOpenChange?.(false)}
                disabled={isUpdatePending}
              >
                Cancel
              </Button>
              <Button 
                type="submit" 
                disabled={isUpdatePending || changedCount === 0}
              >
                {isUpdatePending && (
                  <Loader
                    className="mr-2 size-4 animate-spin"
                    aria-hidden="true"
                  />
                )}
                <ArrowUpDown className="mr-2 h-4 w-4" />
                Apply Changes ({changedCount})
              </Button>
            </DialogFooter>
          </form>
        </Form>
      </DialogContent>
    </Dialog>
  )
}

// 조항 그룹 컴포넌트
interface ClauseGroupProps {
  parentInfo: string
  clauses: ClauseWithOrder[]
  onMove: (clauseId: number, direction: 'up' | 'down') => void
  onDragStart: (e: React.DragEvent, clause: ClauseWithOrder) => void
  onDragOver: (e: React.DragEvent) => void
  onDrop: (e: React.DragEvent, clause: ClauseWithOrder) => void
}

function ClauseGroup({ 
  parentInfo, 
  clauses, 
  onMove, 
  onDragStart, 
  onDragOver, 
  onDrop 
}: ClauseGroupProps) {
  const isRootLevel = parentInfo === "root"
  
  return (
    <div className="space-y-1">
      {!isRootLevel && (
        <div className="text-sm font-medium text-muted-foreground px-2 py-1 bg-muted/30 rounded">
          {parentInfo}
        </div>
      )}
      
      {clauses.map((clause, index) => (
        <ClauseItem
          key={clause.id}
          clause={clause}
          index={index}
          isFirst={index === 0}
          isLast={index === clauses.length - 1}
          onMove={onMove}
          onDragStart={onDragStart}
          onDragOver={onDragOver}
          onDrop={onDrop}
        />
      ))}
    </div>
  )
}

// 개별 조항 컴포넌트
interface ClauseItemProps {
  clause: ClauseWithOrder
  index: number
  isFirst: boolean
  isLast: boolean
  onMove: (clauseId: number, direction: 'up' | 'down') => void
  onDragStart: (e: React.DragEvent, clause: ClauseWithOrder) => void
  onDragOver: (e: React.DragEvent) => void
  onDrop: (e: React.DragEvent, clause: ClauseWithOrder) => void
}

function ClauseItem({ 
  clause, 
  isFirst, 
  isLast, 
  onMove, 
  onDragStart, 
  onDragOver, 
  onDrop 
}: ClauseItemProps) {
  return (
    <div
      className={cn(
        "flex items-center gap-2 p-3 border rounded-lg bg-background",
        clause.hasChanges && "border-blue-300 bg-blue-50",
        "hover:bg-muted/50 transition-colors"
      )}
      draggable
      onDragStart={(e) => onDragStart(e, clause)}
      onDragOver={onDragOver}
      onDrop={(e) => onDrop(e, clause)}
    >
      {/* 드래그 핸들 */}
      <GripVertical className="h-4 w-4 text-muted-foreground cursor-grab" />
      
      {/* 조항 정보 */}
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2 mb-1">
          <Badge variant="outline" className="text-xs">
            {clause.itemNumber}
          </Badge>
          <span className="font-medium truncate">{clause.subtitle}</span>
          {clause.hasChanges && (
            <Badge variant="default" className="text-xs">
              변경됨
            </Badge>
          )}
        </div>
        {clause.content && (
          <p className="text-xs text-muted-foreground line-clamp-1">
            {clause.content.substring(0, 100)}...
          </p>
        )}
      </div>
      
      {/* 순서 변경 버튼 */}
      <div className="flex gap-1">
        <Button
          type="button"
          variant="ghost"
          size="sm"
          className="h-8 w-8 p-0"
          disabled={isFirst}
          onClick={() => onMove(clause.id, 'up')}
        >
          <ArrowUp className="h-4 w-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          className="h-8 w-8 p-0"
          disabled={isLast}
          onClick={() => onMove(clause.id, 'down')}
        >
          <ArrowDown className="h-4 w-4" />
        </Button>
      </div>
    </div>
  )
}

// 조항을 부모별로 그룹화
function groupClausesByParent(clauses: ClauseWithOrder[]): Record<string, ClauseWithOrder[]> {
  const groups: Record<string, ClauseWithOrder[]> = {}
  
  clauses.forEach(clause => {
    const parentKey = clause.parentId 
      ? `${clause.parentItemNumber || 'Unknown'} - ${clause.parentSubtitle || 'Unknown'}`
      : "root"
    
    if (!groups[parentKey]) {
      groups[parentKey] = []
    }
    groups[parentKey].push(clause)
  })
  
  // 각 그룹 내에서 sortOrder로 정렬
  Object.keys(groups).forEach(key => {
    groups[key].sort((a, b) => a.newSortOrder - b.newSortOrder)
  })
  
  return groups
}