import { useCallback, useEffect, useMemo, useState } from "react"
import { ChevronDown, ChevronLeft, ChevronRight, RefreshCw } from "lucide-react"
import spinnerSrc from "../../assets/Circular-indeterminate progress indicator.svg"
import { Card, CardContent, CardHeader, CardTitle } from "../../components/ui/card"
import { Button } from "../../components/ui/button"
import { Input } from "../../components/ui/input"
import { Select } from "../../components/ui/select"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../components/ui/table"
import { Badge } from "../../components/ui/badge"
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../../components/ui/dialog"
import { getQuestionSetById, getQuestionSets } from "../../api/courses.api"
import type { QuestionSet, QuestionSetDetail } from "../../types/course.types"
import { cn } from "../../lib/utils"
import { SpinnerIcon } from "../../components/ui/spinner-icon"

const statusColor: Record<string, string> = {
  PUBLISHED: "bg-green-100 text-green-700",
  DRAFT: "bg-amber-100 text-amber-700",
  ARCHIVED: "bg-grayScale-200 text-grayScale-600",
}

export function PracticeDetailsPage() {
  const [practices, setPractices] = useState<QuestionSet[]>([])
  const [selectedPracticeId, setSelectedPracticeId] = useState<number | null>(null)
  const [selectedPracticeDetail, setSelectedPracticeDetail] = useState<QuestionSetDetail | null>(null)
  const [detailOpen, setDetailOpen] = useState(false)
  const [loadingList, setLoadingList] = useState(false)
  const [loadingDetail, setLoadingDetail] = useState(false)
  const [searchQuery, setSearchQuery] = useState("")
  const [statusFilter, setStatusFilter] = useState("all")
  const [ownerTypeFilter, setOwnerTypeFilter] = useState("all")
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(10)

  const fetchPractices = useCallback(async () => {
    setLoadingList(true)
    try {
      const batchSize = 100
      let offset = 0
      let total = Number.POSITIVE_INFINITY
      const sets: QuestionSet[] = []

      while (sets.length < total) {
        const res = await getQuestionSets({ set_type: "PRACTICE", limit: batchSize, offset })
        const payload = res.data?.data as unknown
        let chunk: QuestionSet[] = []
        let chunkTotal = 0
        if (Array.isArray(payload)) {
          chunk = payload as QuestionSet[]
          chunkTotal = chunk.length
        } else if (
          payload &&
          typeof payload === "object" &&
          Array.isArray((payload as { question_sets?: unknown[] }).question_sets)
        ) {
          const mapped = payload as { question_sets: QuestionSet[]; total_count?: number }
          chunk = mapped.question_sets
          chunkTotal = mapped.total_count ?? chunk.length
        }
        sets.push(...chunk)
        total = chunkTotal
        if (chunk.length < batchSize) break
        offset += chunk.length
      }

      setPractices(sets)
      if (sets.length > 0) {
        setSelectedPracticeId((prev) => prev ?? sets[0].id)
      } else {
        setSelectedPracticeId(null)
        setSelectedPracticeDetail(null)
      }
    } catch (error) {
      console.error("Failed to fetch practices:", error)
      setPractices([])
      setSelectedPracticeId(null)
      setSelectedPracticeDetail(null)
    } finally {
      setLoadingList(false)
    }
  }, [])

  const fetchPracticeDetail = useCallback(async (practiceId: number) => {
    setLoadingDetail(true)
    try {
      const res = await getQuestionSetById(practiceId)
      setSelectedPracticeDetail(res.data?.data ?? null)
    } catch (error) {
      console.error("Failed to fetch practice detail:", error)
      setSelectedPracticeDetail(null)
    } finally {
      setLoadingDetail(false)
    }
  }, [])

  useEffect(() => {
    fetchPractices()
  }, [fetchPractices])

  useEffect(() => {
    if (selectedPracticeId) {
      fetchPracticeDetail(selectedPracticeId)
    }
  }, [selectedPracticeId, fetchPracticeDetail])

  useEffect(() => {
    setPage(1)
  }, [searchQuery, statusFilter, ownerTypeFilter])

  const filteredPractices = useMemo(() => {
    return practices.filter((practice) => {
      const matchesSearch =
        !searchQuery.trim() ||
        practice.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
        (practice.description || "").toLowerCase().includes(searchQuery.toLowerCase()) ||
        String(practice.id).includes(searchQuery) ||
        String(practice.owner_id).includes(searchQuery)
      const matchesStatus = statusFilter === "all" || practice.status === statusFilter
      const matchesOwnerType = ownerTypeFilter === "all" || practice.owner_type === ownerTypeFilter
      return matchesSearch && matchesStatus && matchesOwnerType
    })
  }, [practices, searchQuery, statusFilter, ownerTypeFilter])

  const totalCount = useMemo(() => filteredPractices.length, [filteredPractices])
  const totalPages = Math.max(1, Math.ceil(totalCount / pageSize))
  const safePage = Math.min(page, totalPages)
  const paginatedPractices = useMemo(() => {
    const start = (safePage - 1) * pageSize
    return filteredPractices.slice(start, start + pageSize)
  }, [filteredPractices, safePage, pageSize])
  const startEntry = totalCount === 0 ? 0 : (safePage - 1) * pageSize + 1
  const endEntry = Math.min(safePage * pageSize, totalCount)

  const getPageNumbers = () => {
    const pages: (number | string)[] = []
    if (totalPages <= 7) {
      for (let i = 1; i <= totalPages; i++) pages.push(i)
    } else {
      pages.push(1, 2, 3)
      if (safePage > 4) pages.push("...")
      if (safePage > 3 && safePage < totalPages - 2) pages.push(safePage)
      if (safePage < totalPages - 3) pages.push("...")
      pages.push(totalPages)
    }
    return pages
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <h1 className="text-2xl font-bold tracking-tight text-grayScale-600">Practice Management</h1>
          <p className="mt-1 text-sm text-grayScale-400">
            Browse all practice question sets and view their details.
          </p>
        </div>
        <Button variant="outline" onClick={fetchPractices} disabled={loadingList}>
          {loadingList ? <SpinnerIcon className="h-4 w-4" /> : <RefreshCw className="h-4 w-4" />}
          Refresh
        </Button>
      </div>

      <Card className="shadow-soft">
        <CardHeader className="border-b border-grayScale-200 pb-4">
          <CardTitle className="text-base font-semibold text-grayScale-600">
            Practices ({totalCount})
          </CardTitle>
        </CardHeader>
        <CardContent className="pt-5">
          <div className="mb-4 flex flex-col gap-3 lg:flex-row lg:items-center">
            <div className="flex-1">
              <Input
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                placeholder="Search by title, description, practice ID, or owner ID..."
              />
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <Select value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)}>
                <option value="all">All Statuses</option>
                <option value="PUBLISHED">PUBLISHED</option>
                <option value="DRAFT">DRAFT</option>
                <option value="ARCHIVED">ARCHIVED</option>
              </Select>
              <Select value={ownerTypeFilter} onChange={(e) => setOwnerTypeFilter(e.target.value)}>
                <option value="all">All Owner Types</option>
                <option value="SUB_COURSE">SUB_COURSE</option>
                <option value="COURSE">COURSE</option>
              </Select>
              <Button
                variant="outline"
                onClick={() => {
                  setSearchQuery("")
                  setStatusFilter("all")
                  setOwnerTypeFilter("all")
                  setPage(1)
                }}
              >
                Clear
              </Button>
            </div>
          </div>

          <div className="rounded-xl border bg-white">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Title</TableHead>
                  <TableHead className="hidden md:table-cell">Owner</TableHead>
                  <TableHead>Status</TableHead>
                  <TableHead className="hidden md:table-cell">Created</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {loadingList ? (
                  <TableRow>
                    <TableCell colSpan={4} className="py-12 text-center">
                      <div className="flex flex-col items-center gap-3">
                        <img src={spinnerSrc} alt="" className="h-6 w-6 animate-spin" />
                        <span className="text-sm text-grayScale-400">Loading practices...</span>
                      </div>
                    </TableCell>
                  </TableRow>
                ) : filteredPractices.length === 0 ? (
                  <TableRow>
                    <TableCell colSpan={4} className="py-12 text-center text-sm text-grayScale-500">
                      No practice sets found.
                    </TableCell>
                  </TableRow>
                ) : (
                  paginatedPractices.map((practice) => (
                    <TableRow
                      key={practice.id}
                      onClick={() => {
                        setSelectedPracticeId(practice.id)
                        setDetailOpen(true)
                      }}
                      className={cn(
                        "group cursor-pointer",
                        selectedPracticeId === practice.id && "bg-brand-100/30",
                      )}
                    >
                      <TableCell className="max-w-md py-3.5">
                        <p className="truncate text-sm font-medium text-grayScale-700">{practice.title}</p>
                        <p className="mt-1 truncate text-xs text-grayScale-500">{practice.description || "—"}</p>
                      </TableCell>
                      <TableCell className="hidden py-3.5 text-sm text-grayScale-500 md:table-cell">
                        {practice.owner_type} #{practice.owner_id}
                      </TableCell>
                      <TableCell className="py-3.5">
                        <Badge className={statusColor[practice.status] || "bg-grayScale-200 text-grayScale-600"}>
                          {practice.status}
                        </Badge>
                      </TableCell>
                      <TableCell className="hidden py-3.5 text-sm text-grayScale-500 md:table-cell">
                        {practice.created_at}
                      </TableCell>
                    </TableRow>
                  ))
                )}
              </TableBody>
            </Table>

            <div className="flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3 text-sm text-grayScale-500">
              <div className="flex items-center gap-2">
                <span>Showing</span>
                <span className="font-medium text-grayScale-600">
                  {startEntry}-{endEntry}
                </span>
                <span>of</span>
                <span className="font-medium text-grayScale-600">{totalCount}</span>
                <span className="mr-4">entries</span>
                <span className="border-l pl-4">Rows per page</span>
                <div className="relative">
                  <select
                    value={pageSize}
                    onChange={(e) => {
                      setPageSize(Number(e.target.value))
                      setPage(1)
                    }}
                    className="h-8 appearance-none rounded-md border bg-white pl-2 pr-7 text-sm font-medium text-grayScale-600 focus:outline-none"
                  >
                    {[10, 20, 50].map((size) => (
                      <option key={size} value={size}>
                        {size}
                      </option>
                    ))}
                  </select>
                  <ChevronDown className="pointer-events-none absolute right-2 top-1/2 h-3 w-3 -translate-y-1/2 text-grayScale-400" />
                </div>
              </div>
              <div className="flex items-center gap-1">
                <button
                  onClick={() => safePage > 1 && setPage(safePage - 1)}
                  disabled={safePage === 1}
                  className={cn(
                    "flex h-8 w-8 items-center justify-center rounded-md border bg-white text-grayScale-500",
                    safePage === 1 && "cursor-not-allowed opacity-50",
                  )}
                >
                  <ChevronLeft className="h-4 w-4" />
                </button>
                {getPageNumbers().map((n, idx) =>
                  typeof n === "string" ? (
                    <span key={`ellipsis-${idx}`} className="px-2 text-grayScale-400">
                      ...
                    </span>
                  ) : (
                    <button
                      key={n}
                      type="button"
                      onClick={() => setPage(n)}
                      className={cn(
                        "h-8 w-8 rounded-md border text-sm font-medium",
                        n === safePage
                          ? "border-brand-500 bg-brand-500 text-white"
                          : "bg-white text-grayScale-600 hover:bg-grayScale-50",
                      )}
                    >
                      {n}
                    </button>
                  ),
                )}
                <button
                  onClick={() => safePage < totalPages && setPage(safePage + 1)}
                  disabled={safePage === totalPages}
                  className={cn(
                    "flex h-8 w-8 items-center justify-center rounded-md border bg-white text-grayScale-500",
                    safePage === totalPages && "cursor-not-allowed opacity-50",
                  )}
                >
                  <ChevronRight className="h-4 w-4" />
                </button>
              </div>
            </div>
          </div>
        </CardContent>
      </Card>

      <Dialog open={detailOpen} onOpenChange={setDetailOpen}>
        <DialogContent className="sm:max-w-2xl">
          <DialogHeader>
            <DialogTitle>Practice Detail</DialogTitle>
          </DialogHeader>
          {!selectedPracticeId ? (
            <p className="text-sm text-grayScale-500">Select a practice from the list to view details.</p>
          ) : loadingDetail ? (
            <p className="text-sm text-grayScale-500">Loading detail...</p>
          ) : !selectedPracticeDetail ? (
            <p className="text-sm text-grayScale-500">Failed to load practice detail.</p>
          ) : (
            <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Title</p>
                <p className="mt-1 text-sm text-grayScale-700">{selectedPracticeDetail.title}</p>
              </div>
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Set Type</p>
                <p className="mt-1 text-sm text-grayScale-700">{selectedPracticeDetail.set_type}</p>
              </div>
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3 sm:col-span-2">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Description</p>
                <p className="mt-1 text-sm text-grayScale-700">{selectedPracticeDetail.description || "—"}</p>
              </div>
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Owner</p>
                <p className="mt-1 text-sm text-grayScale-700">
                  {selectedPracticeDetail.owner_type} #{selectedPracticeDetail.owner_id}
                </p>
              </div>
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Status</p>
                <p className="mt-1 text-sm text-grayScale-700">{selectedPracticeDetail.status}</p>
              </div>
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Question Count</p>
                <p className="mt-1 text-sm text-grayScale-700">{selectedPracticeDetail.question_count ?? 0}</p>
              </div>
              <div className="rounded-lg border border-grayScale-200 bg-grayScale-50 p-3">
                <p className="text-xs font-semibold uppercase tracking-wider text-grayScale-500">Created At</p>
                <p className="mt-1 text-sm text-grayScale-700">{selectedPracticeDetail.created_at}</p>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </div>
  )
}
