"use client";

import { useEffect, useMemo, useState } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { Register, RegisterAccess, Note } from "@/utils/register_parser";
import { Form, Row, Table, OverlayTrigger, Tooltip } from "react-bootstrap";
import RegisterDetail from "@/app/registers/RegisterDetail";
import ExplorerLayout from "@/components/explorer/ExplorerLayout";
import FilterSidebar from "@/components/explorer/FilterSidebar";

interface RegisterBrowserProps {
  registers: Register[];
}

/**
 * Renders the access details for a register, including its description, operations, and notes.
 * @param access The register access data to render.
 * @param extraNotes Non access footnotes to include in the tooltip.
 * @returns A React component that displays the register access details.
 */
export function renderAccess(access: RegisterAccess, extraNotes: Note[] = []) {
  const renderTooltip = (notes: Note[]) => (
    <Tooltip id="tooltip">
      {notes.map((note, index) => (
        <div key={index}><span className="footnote-anchor">{note.ref}</span> {note.text}</div>
      ))}
    </Tooltip>
  );

  return (
    <>
      {access.description && <pre>{access.description}</pre>}
      {access.operations.length > 0 &&
        <Table striped bordered hover size="sm" className="bits-table">
          <thead>
            <tr>
              <th>Bits</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            {access.operations.map((op, index) => {
              const access_notes = access.notes.filter(note => note.ref === op.footnoteRef);
              const extra_notes = extraNotes.filter(note => note.ref === op.footnoteRef);

              const notes = [...access_notes, ...extra_notes].filter(note => note.text.length > 0);

              return (
                <tr key={index}>
                  <td>{op.bits}</td>
                  <td>
                    {op.description}
                    {op.footnoteRef && notes.length > 0 && (
                      <OverlayTrigger placement="top" overlay={renderTooltip(notes)}>
                          <span className="footnote-ref">{op.footnoteRef}</span>
                      </OverlayTrigger>
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </Table>
      }
      {access.notes.map((note, index) => (
          <p key={index} className="small text-muted"><span className="footnote-anchor">{note.ref}</span> {note.text}</p>
      ))}
    </>
  );
}

/**
 * A component for browsing and searching through a list of registers.
 * @param registers An array of Register objects to display.
 * @returns A React component that allows users to browse and search registers.
 */
export default function RegisterBrowser({ registers }: RegisterBrowserProps) {
  const [searchTerm, setSearchTerm] = useState("");
  const searchParams = useSearchParams();
  const router = useRouter();
  const pathname = usePathname();

  // Initialize from query string and keep in sync when the URL changes
  useEffect(() => {
    const qp = (searchParams?.get('q') || '').trim();
    // Only update state if different to avoid loops
    if (qp !== searchTerm) {
      setSearchTerm(qp);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [searchParams]);

  // Update the URL query string whenever the user types
  const updateQueryString = (value: string) => {
    const params = new URLSearchParams(searchParams?.toString());
    const v = value.trim();
    if (v) {
      params.set('q', v);
    } else {
      params.delete('q');
    }
    const query = params.toString();
    const url = query ? `${pathname}?${query}` : pathname;
    router.replace(url, { scroll: false });
  };

  const filteredRegisters = useMemo(() => (
    registers.filter((register) => register.search.includes(searchTerm.toLowerCase()))
  ), [registers, searchTerm]);

  return (
    <ExplorerLayout
      title="NextReg Explorer"
      subtitle={`${filteredRegisters.length.toLocaleString()} results`}
      chips={searchTerm ? [`q: ${searchTerm}`] : []}
      onClearChips={() => {
        setSearchTerm("");
        updateQueryString("");
      }}
      sidebar={(
        <FilterSidebar>
          <Form.Group>
            <Form.Label className="form-label small text-secondary">Search</Form.Label>
            <Form.Control
              type="text"
              placeholder="Search registers..."
              value={searchTerm}
              onChange={(e) => {
                const v = e.target.value;
                setSearchTerm(v);
                updateQueryString(v);
              }}
            />
          </Form.Group>
        </FilterSidebar>
      )}
    >
      <Row>
        {filteredRegisters.map((register) => (
          <RegisterDetail key={register.hex_address} register={register} />
        ))}
      </Row>
    </ExplorerLayout>
  );
}
