import { useMemo, useState } from "react";

type Definition = {
  source: string;
  title: string;
  url: string;
  definition: string;
};

type BulkTermMeta = {
  definitions_count: number;
  taxonomy_count: number;
};

type BulkTermResult = {
  term: string;
  results: Definition[];
  taxonomy?: TaxonomyMatch[];
  meta: BulkTermMeta;
  error?: string | null;
};

type BulkDefinitionResponse = {
  terms: string[];
  results: Record<string, BulkTermResult>;
  request_id?: string | null;
};

type TaxonomyMatch = {
  category: string;
  class_name: string;
  class_code: string;
  type_description?: string | null;
  type_code?: string | null;
  annex?: string | null;
  full_name: string;
};

const API_BASE_URL =
  import.meta.env.VITE_API_BASE_URL?.toString() || "http://localhost:8000";

const MAX_TERMS = 5;

export default function App() {
  const [termInput, setTermInput] = useState("");
  const [resultsByTerm, setResultsByTerm] = useState<
    Record<string, BulkTermResult>
  >({});
  const [orderedTerms, setOrderedTerms] = useState<string[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const parsedTerms = useMemo(() => {
    const terms: string[] = [];
    const seen = new Set<string>();
    for (const line of termInput.split(/\r?\n/)) {
      const trimmed = line.trim();
      if (!trimmed || seen.has(trimmed)) continue;
      terms.push(trimmed);
      seen.add(trimmed);
    }
    return terms;
  }, [termInput]);

  const hasTooManyTerms = parsedTerms.length > MAX_TERMS;
  const canSearch = parsedTerms.length > 0 && !hasTooManyTerms && !loading;

  const apiUrl = useMemo(() => {
    const url = new URL("/api/definitions/bulk", API_BASE_URL);
    return url.toString();
  }, [API_BASE_URL]);

  const summary = useMemo(() => {
    let definitions = 0;
    let taxonomy = 0;
    let failed = 0;

    for (const term of orderedTerms) {
      const item = resultsByTerm[term];
      if (!item) continue;
      if (item.error) failed += 1;
      definitions += item.meta?.definitions_count ?? item.results?.length ?? 0;
      taxonomy += item.meta?.taxonomy_count ?? item.taxonomy?.length ?? 0;
    }

    return { definitions, taxonomy, failed };
  }, [orderedTerms, resultsByTerm]);

  const handleSearch = async (event: React.FormEvent) => {
    event.preventDefault();

    if (!canSearch) return;

    setLoading(true);
    setError(null);

    try {
      const response = await fetch(apiUrl, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ terms: parsedTerms }),
      });
      if (!response.ok) {
        let message = "Failed to fetch definitions.";
        try {
          const payload = (await response.json()) as { detail?: string };
          if (payload?.detail) {
            message = payload.detail;
          }
        } catch {
          // ignore JSON parsing errors
        }
        throw new Error(message);
      }
      const data = (await response.json()) as BulkDefinitionResponse;
      setOrderedTerms(data.terms ?? parsedTerms);
      setResultsByTerm(data.results ?? {});
    } catch (err) {
      setError(err instanceof Error ? err.message : "Something went wrong.");
      setOrderedTerms([]);
      setResultsByTerm({});
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="min-h-screen px-6 py-12">
      <div className="mx-auto flex w-full max-w-3xl flex-col gap-8">
        <header className="space-y-3">
          <p className="text-sm font-semibold uppercase tracking-wide text-sky-600">
            TermSearch
          </p>
          <h1 className="text-4xl font-semibold text-slate-900">
            Oil &amp; Gas term definitions
          </h1>
          <p className="text-base text-slate-600">
            Search multiple glossary sources from a single interface.
          </p>
        </header>

        <form
          onSubmit={handleSearch}
          className="flex flex-col gap-4 rounded-2xl bg-white p-6 shadow-sm"
        >
          <div className="flex items-center justify-between">
            <label className="text-sm font-medium text-slate-700" htmlFor="terms">
              Search terms (one per line)
            </label>
            <span
              className={`text-xs ${
                hasTooManyTerms ? "text-rose-600" : "text-slate-500"
              }`}
            >
              {parsedTerms.length}/{MAX_TERMS} terms
            </span>
          </div>
          <div className="flex flex-col gap-3 sm:flex-row">
            <textarea
              id="terms"
              name="terms"
              rows={4}
              value={termInput}
              onChange={(
                event: React.ChangeEvent<HTMLTextAreaElement>
              ) => setTermInput(event.target.value)}
              placeholder={`Ex:\ngas lift\npump\nflow assurance`}
              className="flex-1 rounded-xl border border-slate-200 px-4 py-3 text-base focus:border-sky-500 focus:outline-none focus:ring-2 focus:ring-sky-200"
            />
            <button
              type="submit"
              disabled={!canSearch}
              className="rounded-xl bg-sky-600 px-6 py-3 text-base font-semibold text-white transition hover:bg-sky-700 disabled:cursor-not-allowed disabled:bg-slate-300"
            >
              {loading ? "Searching..." : "Search"}
            </button>
          </div>
          {hasTooManyTerms ? (
            <p className="text-xs text-rose-600">
              Maximum of {MAX_TERMS} terms allowed. Please remove extra terms to
              continue.
            </p>
          ) : (
            <p className="text-xs text-slate-500">
              Maximum of {MAX_TERMS} terms per search.
            </p>
          )}
          <p className="text-xs text-slate-500">
            API base: <span className="font-medium">{API_BASE_URL}</span>
          </p>
        </form>

        <section className="space-y-4">
          <div className="flex flex-wrap items-center justify-between gap-2">
            <h2 className="text-xl font-semibold text-slate-800">Results</h2>
            <span className="text-sm text-slate-500">
              {summary.definitions} definitions · {summary.taxonomy} taxonomy
              matches · {summary.failed} failed term
              {summary.failed === 1 ? "" : "s"}
            </span>
          </div>

          {error ? (
            <div className="rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-600">
              {error}
            </div>
          ) : null}

          {orderedTerms.length === 0 && !loading ? (
            <div className="rounded-xl border border-dashed border-slate-200 bg-white p-6 text-sm text-slate-500">
              No definitions yet. Add terms and search.
            </div>
          ) : null}

          <div className="space-y-6">
            {orderedTerms.map((term) => {
              const item = resultsByTerm[term];
              const definitions = item?.results ?? [];
              const taxonomy = item?.taxonomy ?? [];
              const termError = item?.error;

              return (
                <section
                  key={term}
                  className="space-y-4 rounded-2xl border border-slate-100 bg-white p-5 shadow-sm"
                >
                  <div className="flex flex-wrap items-center justify-between gap-2">
                    <h3 className="text-lg font-semibold text-slate-900">
                      {term}
                    </h3>
                    <span className="text-xs text-slate-500">
                      {definitions.length} source
                      {definitions.length === 1 ? "" : "s"} · {taxonomy.length}
                      {taxonomy.length === 1 ? " match" : " matches"}
                    </span>
                  </div>

                  {termError ? (
                    <div className="rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-600">
                      {termError}
                    </div>
                  ) : null}

                  <div className="space-y-3">
                    <h4 className="text-xs font-semibold uppercase tracking-wide text-slate-500">
                      Definitions
                    </h4>
                    {definitions.length === 0 ? (
                      <div className="rounded-xl border border-dashed border-slate-200 bg-white p-4 text-sm text-slate-500">
                        No definitions found for this term.
                      </div>
                    ) : (
                      <div className="space-y-3">
                        {definitions.map((result) => (
                          <article
                            key={`${term}-${result.source}-${result.title}`}
                            className="rounded-xl border border-slate-100 bg-white p-4 shadow-sm"
                          >
                            <h5 className="text-xs font-semibold uppercase tracking-wide text-sky-600">
                              {result.source}
                            </h5>
                            <p className="mt-2 text-base font-semibold text-slate-900">
                              {result.title}
                            </p>
                            <a
                              href={result.url}
                              target="_blank"
                              rel="noreferrer"
                              className="mt-2 inline-flex text-sm font-medium text-sky-600 hover:text-sky-700"
                            >
                              View source
                            </a>
                            <p className="mt-2 text-sm text-slate-700">
                              {result.definition}
                            </p>
                          </article>
                        ))}
                      </div>
                    )}
                  </div>

                  <div className="space-y-3">
                    <h4 className="text-xs font-semibold uppercase tracking-wide text-slate-500">
                      ISO 14224 Taxonomy
                    </h4>
                    {taxonomy.length === 0 ? (
                      <div className="rounded-xl border border-dashed border-slate-200 bg-white p-4 text-sm text-slate-500">
                        No taxonomy matches found for this term.
                      </div>
                    ) : (
                      <div className="space-y-3">
                        {taxonomy.map((item) => (
                          <article
                            key={`${term}-${item.class_code}-${
                              item.type_code ?? "class"
                            }`}
                            className="rounded-xl border border-slate-100 bg-white p-4 shadow-sm"
                          >
                            <p className="text-xs font-semibold uppercase tracking-wide text-emerald-600">
                              {item.category}
                            </p>
                            <h5 className="mt-2 text-base font-semibold text-slate-900">
                              {item.full_name}
                            </h5>
                            <div className="mt-2 flex flex-wrap gap-3 text-sm text-slate-600">
                              <span>
                                Class: {item.class_name} ({item.class_code})
                              </span>
                              {item.type_description ? (
                                <span>
                                  Type: {item.type_description} ({item.type_code})
                                </span>
                              ) : null}
                              {item.annex ? <span>Annex: {item.annex}</span> : null}
                            </div>
                          </article>
                        ))}
                      </div>
                    )}
                  </div>
                </section>
              );
            })}
          </div>
        </section>
      </div>
    </div>
  );
}
