import { useCallback, useEffect, useMemo, useState } from "react";
import { Link, createFileRoute } from "@tanstack/react-router";
import { ArrowLeft, Loader2, Paperclip, Send, ShieldAlert, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { EmptyState, SectionCard } from "@/components/ledger/Primitives";
import { QueryThread } from "@/components/ledger/QueryThread";
import { useAuthSession } from "@/hooks/useAuthSession";
import { fetchQueryApi } from "@/lib/api";
import { eur, useLedger } from "@/lib/ledger-store";
import type { ClientQuery } from "@/lib/ledger-types";

function QueryRouteError({ error, reset }: { error: Error; reset: () => void }) {
  return (
    <SectionCard>
      <EmptyState
        icon={X}
        title="Unable to load this query."
        description={error.message || "Something went wrong while opening this question."}
        action={
          <div className="flex flex-wrap justify-center gap-2">
            <Button variant="outline" onClick={reset}>
              Try again
            </Button>
            <Button variant="ghost" asChild>
              <Link to="/queries">Back to questions</Link>
            </Button>
          </div>
        }
      />
    </SectionCard>
  );
}

function QueryLoading() {
  return (
    <div className="flex items-center gap-3 px-1 py-8 text-[13px] text-muted-foreground">
      <Loader2 size={16} className="animate-spin text-brand" aria-hidden="true" />
      Loading query...
    </div>
  );
}

export const Route = createFileRoute("/queries/$id")({
  component: ClientQueryDetail,
  errorComponent: QueryRouteError,
  pendingComponent: QueryLoading,
});

function ClientQueryDetail() {
  const { id } = Route.useParams();
  const session = useAuthSession("client");
  const { getInvoice, answerQuery, replyToQuery } = useLedger();

  const [query, setQuery] = useState<ClientQuery | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [statusCode, setStatusCode] = useState<number | null>(null);
  const [answer, setAnswer] = useState("");
  const [attachment, setAttachment] = useState<string | undefined>();
  const [sent, setSent] = useState(false);
  const [busy, setBusy] = useState(false);

  const load = useCallback(async () => {
    if (!session?.email) return;
    setLoading(true);
    setError(null);
    setStatusCode(null);
    try {
      const next = await fetchQueryApi(id, { platform: "client", email: session.email });
      setQuery(next);
    } catch (err) {
      setQuery(null);
      setError(err instanceof Error ? err.message : "Unable to load this query.");
      const code = (err as Error & { status?: number }).status;
      setStatusCode(typeof code === "number" ? code : null);
    } finally {
      setLoading(false);
    }
  }, [id, session?.email]);

  useEffect(() => {
    void load();
  }, [load]);

  const invoice = useMemo(
    () => (query?.invoiceId ? getInvoice(query.invoiceId) : undefined),
    [getInvoice, query?.invoiceId],
  );

  if (loading) {
    return <QueryLoading />;
  }

  if (error || !query) {
    const unauthorized = statusCode === 403;
    const notFound = statusCode === 404;
    return (
      <SectionCard>
        <EmptyState
          icon={unauthorized ? ShieldAlert : X}
          title={
            unauthorized ? "Access denied" : notFound ? "Query not found" : "Unable to load this query."
          }
          description={
            unauthorized
              ? "You do not have access to this query."
              : notFound
                ? "This query may have been deleted or you may not have access to it."
                : error ?? "This query may have been deleted or you may not have access to it."
          }
          action={
            <div className="flex flex-wrap justify-center gap-2">
              {!unauthorized ? (
                <Button variant="outline" onClick={() => void load()}>
                  Try again
                </Button>
              ) : null}
              <Button variant="ghost" asChild>
                <Link to="/queries">Back to questions</Link>
              </Button>
            </div>
          }
        />
      </SectionCard>
    );
  }

  const canAnswer = query.status === "Delivered" || query.status === "Answered";
  const isClosed = query.status === "Resolved" || query.status === "Cancelled";

  return (
    <div className="space-y-6">
      <Button variant="ghost" size="sm" asChild>
        <Link to="/queries">
          <ArrowLeft size={15} /> Back to questions
        </Link>
      </Button>

      <div>
        <h1 className="text-[20px] font-semibold tracking-tight">
          {query.question || "Your accountant has a question"}
        </h1>
        <p className="mt-1 text-[13px] text-muted-foreground">
          {query.id} · Created {query.createdAt}
        </p>
      </div>

      {query.invoiceId ? (
        <SectionCard title="Related invoice" bodyClassName="p-5">
          <p className="text-[14px] font-semibold">
            {invoice?.supplier || invoice?.file || query.invoiceId}
          </p>
          <p className="mt-1 text-[13px] text-muted-foreground">
            {invoice?.number ? `Invoice ${invoice.number}` : invoice?.file || query.invoiceId}
            {invoice?.total ? ` · ${eur(invoice.total)}` : ""}
          </p>
          <Button size="sm" variant="outline" className="mt-3" asChild>
            <Link to="/documents/$id" params={{ id: query.invoiceId }}>
              View document
            </Link>
          </Button>
        </SectionCard>
      ) : null}

      <SectionCard title="Conversation" bodyClassName="p-5 space-y-4">
        <QueryThread messages={query.messages ?? []} />

        {canAnswer && !isClosed ? (
          <div className="space-y-3 border-t border-border pt-4">
            <Label htmlFor="client-answer">Write your answer</Label>
            <Textarea
              id="client-answer"
              value={answer}
              onChange={(e) => setAnswer(e.target.value)}
              placeholder="Yes, both were paid."
              className="min-h-24 bg-surface"
            />
            {attachment ? (
              <p className="flex items-center gap-1.5 text-[12px] text-primary">
                <Paperclip size={12} aria-hidden="true" />
                Attached: {attachment}
              </p>
            ) : null}
            <div className="flex flex-wrap gap-2">
              <Button
                disabled={!answer.trim() || busy}
                onClick={() => {
                  const text = answer.trim();
                  if (!text) return;
                  setBusy(true);
                  const action =
                    query.status === "Delivered" && !query.answer
                      ? attachment
                        ? answerQuery(query.id, text, attachment)
                        : answerQuery(query.id, text)
                      : attachment
                        ? replyToQuery(query.id, text, attachment)
                        : replyToQuery(query.id, text);
                  void action
                    .then(() => {
                      setAnswer("");
                      setAttachment(undefined);
                      setSent(true);
                      return load();
                    })
                    .catch(() => undefined)
                    .finally(() => setBusy(false));
                }}
              >
                <Send size={15} /> Send answer
              </Button>
            </div>
            {sent ? (
              <p className="text-[13px] text-success">Your answer has been sent to your accountant.</p>
            ) : null}
          </div>
        ) : isClosed ? (
          <p className="text-[13px] text-muted-foreground">
            {query.status === "Cancelled" ? "This question was cancelled." : "This question has been resolved."}
          </p>
        ) : null}
      </SectionCard>
    </div>
  );
}
