"use client"

import { Loader2, RefreshCw, Search } from "lucide-react"
import Link from "next/link"
import * as React from "react"
import { toast } from "sonner"

import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { DeepdexSearchResultItem } from "@/components/deepdex/components/deepdex-search-result-item"
import { DEEPDEX_DOC_TYPE_OPTIONS } from "@/components/deepdex/data/deepdex-doc-types"
import { deepdexSettingsDefaults } from "@/components/deepdex/data/deepdex-settings.defaults"
import {
  reindexDeepdex,
  searchDeepdex,
} from "@/components/deepdex/api/deepdex.api"
import type {
  DeepdexSearchFilters,
  DeepdexSearchResponse,
  DeepdexSettings,
} from "@/components/deepdex/types"
import { ListPageCard } from "@/app/dashboard/_components"
import { ErrorBanner } from "@/components/shared/error-banner"
import { SETTINGS_INPUT_CLASS } from "@/components/settings/constants"
import { TABLE_TOOLBAR_BTN_OUTLINE } from "@/components/shared/table-ui"

const emptyFilters: DeepdexSearchFilters = {
  docType: "",
  issuer: "",
  name: "",
  isin: "",
  productType: "",
  status: "",
}

type DeepdexSearchPageProps = {
  initialIndexedCount?: number
  initialSettings?: DeepdexSettings
  initialTagKeys?: string[]
  initialErrorMessage?: string | null
}

export function DeepdexSearchPage({
  initialIndexedCount = 0,
  initialSettings = deepdexSettingsDefaults,
  initialTagKeys = [],
  initialErrorMessage = null,
}: DeepdexSearchPageProps) {
  const [query, setQuery] = React.useState("")
  const [filters, setFilters] = React.useState<DeepdexSearchFilters>(emptyFilters)
  const [settings] = React.useState<DeepdexSettings>(
    initialSettings
  )
  const [response, setResponse] = React.useState<DeepdexSearchResponse | null>(
    null
  )
  const [isSearching, setIsSearching] = React.useState(false)
  const [isReindexing, setIsReindexing] = React.useState(false)
  const [indexedCount, setIndexedCount] = React.useState(initialIndexedCount)
  const tagKeysCount = initialTagKeys.length

  const runSearch = React.useCallback(
    async (q: string, f: DeepdexSearchFilters, signal: AbortSignal) => {
      if (!q.trim()) {
        setResponse(null)
        setIsSearching(false)
        return
      }
      setIsSearching(true)
      try {
        const data = await searchDeepdex(q, f, signal)
        setResponse(data)
        setIndexedCount(data.indexedCount)
      } catch (error) {
        if (error instanceof DOMException && error.name === "AbortError") {
          return
        }
        const message =
          error instanceof Error && error.message.trim()
            ? error.message
            : "Search failed"
        toast.error(message)
      } finally {
        if (!signal.aborted) {
          setIsSearching(false)
        }
      }
    },
    []
  )

  React.useEffect(() => {
    const controller = new AbortController()
    const timer = setTimeout(() => {
      void runSearch(query, filters, controller.signal)
    }, 300)
    return () => {
      controller.abort()
      clearTimeout(timer)
    }
  }, [query, filters, runSearch])

  const clearFilters = () => {
    setFilters(emptyFilters)
  }

  const handleReindex = async () => {
    setIsReindexing(true)
    try {
      const data = await reindexDeepdex()
      if (data.success) {
        toast.success(
          `Index updated. ${data.indexed} indexed, ${data.removed} removed. ${data.total} total.`
        )
        setIndexedCount(data.total)
        if (query.trim()) {
          const controller = new AbortController()
          void runSearch(query, filters, controller.signal)
        }
      } else {
        toast.error("Re-index failed")
      }
    } catch {
      toast.error("Re-index failed")
    } finally {
      setIsReindexing(false)
    }
  }

  return (
    <ListPageCard
      icon={Search}
      title="Search"
      description="Search indexed Deepdex documents with filters and metadata tags."
      breadcrumb={[
        { label: "Deepdex", href: "/dashboard/deepdex/view-all" },
        { label: "Search" },
      ]}
    >
      <div className="space-y-6">
        <div className="flex flex-wrap items-center justify-between gap-2">
          <div className="text-sm text-muted-foreground">
            <p>
              <span id="deepdex-indexed-count-num">{indexedCount}</span> document(s)
              indexed for search.
            </p>
            {tagKeysCount > 0 ? <p>{tagKeysCount} searchable tag(s) available.</p> : null}
          </div>
          <div className="flex flex-wrap gap-2">
            <Button
              {...TABLE_TOOLBAR_BTN_OUTLINE}
              onClick={() => void handleReindex()}
              disabled={isReindexing}
            >
              {isReindexing ? (
                <Loader2 className="size-4 animate-spin" />
              ) : (
                <RefreshCw className="size-4" />
              )}
              Re-index
            </Button>
            <Button {...TABLE_TOOLBAR_BTN_OUTLINE} asChild>
              <Link href="/dashboard/deepdex/view-all">View all</Link>
            </Button>
          </div>
        </div>

        <ErrorBanner message={initialErrorMessage} />

        {indexedCount === 0 && !initialErrorMessage ? (
          <Card className="border-amber-200 bg-amber-50/50">
            <CardContent className="py-4 text-sm text-amber-950">
              No documents are indexed for search yet. Click{" "}
              <span className="font-medium">Re-index</span> to build the spotlight index
              from your Deepdex library before searching.
            </CardContent>
          </Card>
        ) : null}

        <Card>
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-3">
            <CardTitle className="text-base">Filters</CardTitle>
            <Button
              type="button"
              variant="ghost"
              size="sm"
              onClick={clearFilters}
            >
              Clear
            </Button>
          </CardHeader>
          <CardContent>
            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
              <div className="space-y-1.5">
                <Label>Doc type</Label>
                <Select
                  value={filters.docType || "all"}
                  onValueChange={(v) =>
                    setFilters((f) => ({ ...f, docType: v === "all" ? "" : v }))
                  }
                >
                  <SelectTrigger className={SETTINGS_INPUT_CLASS}>
                    <SelectValue placeholder="All" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All</SelectItem>
                    {DEEPDEX_DOC_TYPE_OPTIONS.map((o) => (
                      <SelectItem key={o.value} value={o.value}>
                        {o.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="filter-issuer">Issuer</Label>
                <Input
                  id="filter-issuer"
                  className={SETTINGS_INPUT_CLASS}
                  value={filters.issuer}
                  onChange={(e) =>
                    setFilters((f) => ({ ...f, issuer: e.target.value }))
                  }
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="filter-name">Name</Label>
                <Input
                  id="filter-name"
                  className={SETTINGS_INPUT_CLASS}
                  value={filters.name}
                  onChange={(e) =>
                    setFilters((f) => ({ ...f, name: e.target.value }))
                  }
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="filter-isin">ISIN / Underlying / Ticker</Label>
                <Input
                  id="filter-isin"
                  className={SETTINGS_INPUT_CLASS}
                  placeholder="ISIN, Underlying or Ticker"
                  value={filters.isin}
                  onChange={(e) =>
                    setFilters((f) => ({ ...f, isin: e.target.value }))
                  }
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="filter-product">Product type</Label>
                <Input
                  id="filter-product"
                  className={SETTINGS_INPUT_CLASS}
                  value={filters.productType}
                  onChange={(e) =>
                    setFilters((f) => ({ ...f, productType: e.target.value }))
                  }
                />
              </div>
              <div className="space-y-1.5">
                <Label>Status</Label>
                <Select
                  value={filters.status || "all"}
                  onValueChange={(v) =>
                    setFilters((f) => ({ ...f, status: v === "all" ? "" : v }))
                  }
                >
                  <SelectTrigger className={SETTINGS_INPUT_CLASS}>
                    <SelectValue placeholder="All" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All</SelectItem>
                    <SelectItem value="Active">Active</SelectItem>
                    <SelectItem value="Expired">Expired</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </div>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="text-base">Search</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="relative">
              <Search className="absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                className={`${SETTINGS_INPUT_CLASS} pl-9`}
                placeholder="Type to search…"
                value={query}
                onChange={(e) => setQuery(e.target.value)}
              />
              {isSearching ? (
                <Loader2 className="absolute top-1/2 right-3 size-4 -translate-y-1/2 animate-spin text-muted-foreground" />
              ) : null}
            </div>
          </CardContent>
        </Card>

        {response && response.results.length > 0 ? (
          <Card>
            <CardHeader className="flex flex-row items-center justify-between">
              <CardTitle className="text-base">Results</CardTitle>
              <span className="text-sm font-medium text-muted-foreground">
                {response.count}
              </span>
            </CardHeader>
            <CardContent className="p-0">
              {response.results.map((r) => (
                <DeepdexSearchResultItem
                  key={r.id}
                  result={r}
                  settings={settings}
                />
              ))}
            </CardContent>
          </Card>
        ) : null}

        {response && response.results.length === 0 && query.trim() ? (
          <Card>
            <CardContent className="py-8 text-center text-sm text-muted-foreground">
              {indexedCount === 0 ? (
                <>
                  Search index is empty. Run <span className="font-medium">Re-index</span>{" "}
                  first, then try again.
                </>
              ) : (
                <>No results for &quot;{response.query}&quot;.</>
              )}
            </CardContent>
          </Card>
        ) : null}
      </div>
    </ListPageCard>
  )
}
