"use client"

import { useMemo, useState } from "react"
import { useFormStatus } from "react-dom"
import { useRouter } from "next/navigation"
import { toast } from "sonner"
import { Search } from "lucide-react"

import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
import { Button } from "@/shared/components/ui/button"
import { Input } from "@/shared/components/ui/input"
import { Label } from "@/shared/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/shared/components/ui/select"
import { ScrollArea } from "@/shared/components/ui/scroll-area"
import { Separator } from "@/shared/components/ui/separator"
import { Badge } from "@/shared/components/ui/badge"
import type { Question } from "@/modules/questions/types"
import { updateExamAction } from "@/modules/exams/actions"
import { StructureEditor } from "./assembly/structure-editor"
import { QuestionBankList } from "./assembly/question-bank-list"
import type { ExamNode } from "./assembly/selected-question-list"
import { createId } from "@paralleldrive/cuid2"

type ExamAssemblyProps = {
  examId: string
  title: string
  subject: string
  grade: string
  difficulty: number
  totalScore: number
  durationMin: number
  initialSelected?: Array<{ id: string; score: number }>
  initialStructure?: ExamNode[] // New prop
  questionOptions: Question[]
}

function SubmitButton({ label }: { label: string }) {
  const { pending } = useFormStatus()
  return (
    <Button type="submit" disabled={pending} className="w-full">
      {pending ? "Saving..." : label}
    </Button>
  )
}

export function ExamAssembly(props: ExamAssemblyProps) {
  const router = useRouter()
  const [search, setSearch] = useState("")
  const [typeFilter, setTypeFilter] = useState<string>("all")
  const [difficultyFilter, setDifficultyFilter] = useState<string>("all")
  
  // Initialize structure state
  const [structure, setStructure] = useState<ExamNode[]>(() => {
    // Hydrate structure with full question objects
    const hydrate = (nodes: ExamNode[]): ExamNode[] => {
      return nodes.map(node => {
        if (node.type === 'question') {
          const q = props.questionOptions.find(opt => opt.id === node.questionId)
          return { ...node, question: q }
        }
        if (node.type === 'group') {
          return { ...node, children: hydrate(node.children || []) }
        }
        return node
      })
    }
    
    // Use initialStructure if provided (Server generated or DB stored)
    if (props.initialStructure && props.initialStructure.length > 0) {
      return hydrate(props.initialStructure)
    }

    // Fallback logic removed as Server Component handles initial migration
    return []
  })

  const filteredQuestions = useMemo(() => {
    let list: Question[] = [...props.questionOptions]
    
    if (search) {
      const lower = search.toLowerCase()
      list = list.filter(q => {
        const content = q.content as { text?: string }
        return content.text?.toLowerCase().includes(lower)
      })
    }

    if (typeFilter !== "all") {
      list = list.filter((q) => q.type === (typeFilter as Question["type"]))
    }
    if (difficultyFilter !== "all") {
      const d = parseInt(difficultyFilter)
      list = list.filter((q) => q.difficulty === d)
    }
    return list
  }, [search, typeFilter, difficultyFilter, props.questionOptions])

  // Recursively calculate total score
  const assignedTotal = useMemo(() => {
    const calc = (nodes: ExamNode[]): number => {
      return nodes.reduce((sum, node) => {
        if (node.type === 'question') return sum + (node.score || 0)
        if (node.type === 'group') return sum + calc(node.children || [])
        return sum
      }, 0)
    }
    return calc(structure)
  }, [structure])

  const progress = Math.min(100, Math.max(0, (assignedTotal / props.totalScore) * 100))

  const handleAdd = (question: Question) => {
    setStructure(prev => [
      ...prev, 
      { 
        id: createId(), 
        type: 'question', 
        questionId: question.id, 
        score: 10, 
        question 
      }
    ])
  }

  const handleAddGroup = () => {
    setStructure(prev => [
      ...prev,
      {
        id: createId(),
        type: 'group',
        title: 'New Section',
        children: []
      }
    ])
  }

  const handleRemove = (id: string) => {
    const removeRecursive = (nodes: ExamNode[]): ExamNode[] => {
      return nodes.filter(n => n.id !== id).map(n => {
        if (n.type === 'group') {
          return { ...n, children: removeRecursive(n.children || []) }
        }
        return n
      })
    }
    setStructure(prev => removeRecursive(prev))
  }

  const handleScoreChange = (id: string, score: number) => {
    const updateRecursive = (nodes: ExamNode[]): ExamNode[] => {
      return nodes.map(n => {
        if (n.id === id) return { ...n, score }
        if (n.type === 'group') return { ...n, children: updateRecursive(n.children || []) }
        return n
      })
    }
    setStructure(prev => updateRecursive(prev))
  }

  const handleGroupTitleChange = (id: string, title: string) => {
    const updateRecursive = (nodes: ExamNode[]): ExamNode[] => {
      return nodes.map(n => {
        if (n.id === id) return { ...n, title }
        if (n.type === 'group') return { ...n, children: updateRecursive(n.children || []) }
        return n
      })
    }
    setStructure(prev => updateRecursive(prev))
  }

  // Helper to extract flat list for DB examQuestions table
  const getFlatQuestions = () => {
    const list: Array<{ id: string; score: number }> = []
    const traverse = (nodes: ExamNode[]) => {
      nodes.forEach(n => {
        if (n.type === 'question' && n.questionId) {
          list.push({ id: n.questionId, score: n.score || 0 })
        }
        if (n.type === 'group') {
          traverse(n.children || [])
        }
      })
    }
    traverse(structure)
    return list
  }
  
  // Helper to strip runtime question objects for DB structure storage
  const getCleanStructure = () => {
    const clean = (nodes: ExamNode[]): any[] => {
      return nodes.map(n => {
        const { question, ...rest } = n
        if (n.type === 'group') {
          return { ...rest, children: clean(n.children || []) }
        }
        return rest
      })
    }
    return clean(structure)
  }

  const handleSave = async (formData: FormData) => {
    formData.set("examId", props.examId)
    formData.set("questionsJson", JSON.stringify(getFlatQuestions()))
    formData.set("structureJson", JSON.stringify(getCleanStructure()))
    
    const result = await updateExamAction(null, formData)
    if (result.success) {
      toast.success("Saved draft")
    } else {
      toast.error(result.message || "Save failed")
    }
  }

  const handlePublish = async (formData: FormData) => {
    formData.set("examId", props.examId)
    formData.set("questionsJson", JSON.stringify(getFlatQuestions()))
    formData.set("structureJson", JSON.stringify(getCleanStructure()))
    formData.set("status", "published")
    
    const result = await updateExamAction(null, formData)
    if (result.success) {
      toast.success("Published exam")
      router.push("/teacher/exams/all")
    } else {
      toast.error(result.message || "Publish failed")
    }
  }

  return (
    <div className="grid h-[calc(100vh-12rem)] gap-6 lg:grid-cols-5">
      {/* Left: Preview (3 cols) */}
      <Card className="lg:col-span-3 flex flex-col overflow-hidden border-2 border-primary/10">
        <CardHeader className="bg-muted/30 pb-4">
          <div className="flex items-center justify-between">
            <CardTitle>Exam Structure</CardTitle>
            <div className="flex items-center gap-4 text-sm">
              <div className="flex flex-col items-end">
                <span className="font-medium">{assignedTotal} / {props.totalScore}</span>
                <span className="text-xs text-muted-foreground">Total Score</span>
              </div>
              <div className="h-2 w-24 rounded-full bg-secondary">
                <div 
                  className={`h-full rounded-full transition-all ${
                    assignedTotal > props.totalScore ? "bg-destructive" : "bg-primary"
                  }`} 
                  style={{ width: `${progress}%` }} 
                />
              </div>
            </div>
          </div>
        </CardHeader>
        
        <ScrollArea className="flex-1 p-4">
          <div className="space-y-6">
            <div className="grid grid-cols-3 gap-4 text-sm text-muted-foreground bg-muted/20 p-3 rounded-md">
              <div><span className="font-medium text-foreground">{props.subject}</span></div>
              <div><span className="font-medium text-foreground">{props.grade}</span></div>
              <div>Duration: <span className="font-medium text-foreground">{props.durationMin} min</span></div>
            </div>

            <StructureEditor 
              items={structure}
              onChange={setStructure}
              onScoreChange={handleScoreChange}
              onGroupTitleChange={handleGroupTitleChange}
              onRemove={handleRemove}
              onAddGroup={handleAddGroup}
            />
          </div>
        </ScrollArea>

        <div className="border-t p-4 bg-muted/30 flex gap-3 justify-end">
          <form action={handleSave} className="flex-1">
            <SubmitButton label="Save Draft" />
          </form>
          <form action={handlePublish} className="flex-1">
            <SubmitButton label="Publish Exam" />
          </form>
        </div>
      </Card>

      {/* Right: Question Bank (2 cols) */}
      <Card className="lg:col-span-2 flex flex-col overflow-hidden">
        <CardHeader className="pb-3 space-y-3">
          <CardTitle className="text-base">Question Bank</CardTitle>
          <div className="relative">
            <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
            <Input 
              placeholder="Search questions..." 
              className="pl-8" 
              value={search}
              onChange={(e) => setSearch(e.target.value)}
            />
          </div>
          <div className="flex gap-2">
            <Select value={typeFilter} onValueChange={setTypeFilter}>
              <SelectTrigger className="flex-1 h-8 text-xs"><SelectValue placeholder="Type" /></SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Types</SelectItem>
                <SelectItem value="single_choice">Single Choice</SelectItem>
                <SelectItem value="multiple_choice">Multiple Choice</SelectItem>
                <SelectItem value="judgment">True/False</SelectItem>
                <SelectItem value="text">Short Answer</SelectItem>
              </SelectContent>
            </Select>
            <Select value={difficultyFilter} onValueChange={setDifficultyFilter}>
              <SelectTrigger className="w-[80px] h-8 text-xs"><SelectValue placeholder="Diff" /></SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All</SelectItem>
                <SelectItem value="1">Lvl 1</SelectItem>
                <SelectItem value="2">Lvl 2</SelectItem>
                <SelectItem value="3">Lvl 3</SelectItem>
                <SelectItem value="4">Lvl 4</SelectItem>
                <SelectItem value="5">Lvl 5</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </CardHeader>
        
        <Separator />
        
        <ScrollArea className="flex-1 p-4 bg-muted/10">
          <QuestionBankList 
            questions={filteredQuestions}
            onAdd={handleAdd}
            isAdded={(id) => {
               // Check if question is added anywhere in the structure
               const isAddedRecursive = (nodes: ExamNode[]): boolean => {
                 return nodes.some(n => {
                   if (n.type === 'question' && n.questionId === id) return true
                   if (n.type === 'group' && n.children) return isAddedRecursive(n.children)
                   return false
                 })
               }
               return isAddedRecursive(structure)
            }}
          />
        </ScrollArea>
      </Card>
    </div>
  )
}
