import { useCoreServices } from '@learnitive/context';
import { captureSourceAnchor, type SourceAnchor } from '@learnitive/latex-source';
import type { ProjectPaperMemoryCitationVerification } from '@learnitive/service-core';
import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@learnitive/ui-components';
import { WsPath } from '@learnitive/ws-path';
import { LoaderCircle, ShieldCheck } from 'lucide-react';
import React from 'react';

type LocalCitationCandidate = {
  id: string;
  key: string;
  file: string;
  line: number;
  anchor: SourceAnchor;
  paperTitle: string;
};

type VerificationItem = LocalCitationCandidate & { verification: ProjectPaperMemoryCitationVerification };

function verificationLabel(status: ProjectPaperMemoryCitationVerification['status']): string {
  if (status === 'strongly-supported') return 'Strongly supported';
  if (status === 'partial') return 'Partial';
  if (status === 'weak-conflicting') return 'Weak/conflicting';
  return 'Not verified';
}

export function CitationSufficiencyDialog({
  open,
  onOpenChange,
  wsName,
  onOpenPaper,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  wsName: string;
  onOpenPaper?: (paperId: string, page?: number) => void;
}) {
  const { latexSource, projectPaperMemory, projectSemantic, projectTools } = useCoreServices();
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState<string>();
  const [gaps, setGaps] = React.useState<Awaited<ReturnType<typeof projectTools.researchReview>>['findings']>([]);
  const [auditIssues, setAuditIssues] = React.useState<Awaited<ReturnType<typeof projectTools.citationAudit>>['issues']>([]);
  const [candidates, setCandidates] = React.useState<LocalCitationCandidate[]>([]);
  const [showDetails, setShowDetails] = React.useState(false);
  const [verifying, setVerifying] = React.useState(false);
  const [verifyProgress, setVerifyProgress] = React.useState({ completed: 0, total: 0 });
  const [verifications, setVerifications] = React.useState<VerificationItem[]>([]);

  React.useEffect(() => {
    if (!open) return;
    let cancelled = false;
    setLoading(true);
    setError(undefined);
    setShowDetails(false);
    setVerifications([]);
    setVerifyProgress({ completed: 0, total: 0 });
    void (async () => {
      const [review, audit, semantic] = await Promise.all([
        projectTools.researchReview(wsName),
        projectTools.citationAudit(wsName),
        projectSemantic.refresh(wsName),
      ]);
      const localCandidates: LocalCitationCandidate[] = [];
      const seen = new Set<string>();
      for (const node of semantic.citations) {
        if (!node.target) continue;
        const id = `${node.file}:${node.range.from}:${node.range.to}:${node.target}`;
        if (seen.has(id)) continue;
        seen.add(id);
        const context = await projectPaperMemory.citationContext(wsName, node.target);
        if (!context.localPaper?.ready) continue;
        const wsPath = WsPath.fromParts(wsName, node.file).wsPath;
        let snapshot = latexSource.getSnapshot(wsPath);
        if (!snapshot) {
          await latexSource.load(wsPath);
          snapshot = latexSource.getSnapshot(wsPath);
        }
        if (!snapshot) continue;
        localCandidates.push({
          id,
          key: node.target,
          file: String(node.file),
          line: node.line,
          paperTitle: context.localPaper.title,
          anchor: captureSourceAnchor({
            filePath: node.file,
            source: snapshot.text,
            from: node.range.from,
            to: node.range.to,
            sourceRevision: snapshot.revision,
            semanticId: node.id,
            semanticKind: node.kind,
          }),
        });
      }
      if (cancelled) return;
      setGaps(review.findings.filter((finding) => finding.kind === 'citation-coverage'));
      setAuditIssues(audit.issues.filter((issue) => issue.kind !== 'unused-entry'));
      setCandidates(localCandidates);
    })().catch((reason) => {
      if (!cancelled) setError(reason instanceof Error ? reason.message : 'Unable to scan citation sufficiency.');
    }).finally(() => {
      if (!cancelled) setLoading(false);
    });
    return () => { cancelled = true; };
  }, [latexSource, open, projectPaperMemory, projectSemantic, projectTools, wsName]);

  const verifyLocal = React.useCallback(async () => {
    setVerifying(true);
    setError(undefined);
    setVerifications([]);
    setVerifyProgress({ completed: 0, total: candidates.length });
    const output: VerificationItem[] = [];
    try {
      for (let index = 0; index < candidates.length; index += 1) {
        const candidate = candidates[index]!;
        const verification = await projectPaperMemory.verifyCitation(wsName, candidate.key, candidate.anchor);
        output.push({ ...candidate, verification });
        setVerifications([...output]);
        setVerifyProgress({ completed: index + 1, total: candidates.length });
      }
    } catch (reason) {
      setError(reason instanceof Error ? reason.message : 'Unable to finish local citation verification.');
    } finally {
      setVerifying(false);
    }
  }, [candidates, projectPaperMemory, wsName]);

  const weakCount = verifications.filter((item) => item.verification.status === 'weak-conflicting' || item.verification.status === 'not-verified').length;
  const baseIssueCount = gaps.length + auditIssues.length;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-h-[min(84vh,760px)] max-w-2xl overflow-y-auto" data-testid="citation-sufficiency-dialog">
        <DialogHeader>
          <DialogTitle>Citation sufficiency</DialogTitle>
          <DialogDescription>A conservative local scan. Learnitive flags review candidates; it does not assert that every flagged passage requires a citation.</DialogDescription>
        </DialogHeader>

        {loading ? (
          <div className="flex items-center gap-2 py-5 text-sm text-muted-foreground"><LoaderCircle className="size-4 animate-spin" />Scanning manuscript and bibliography…</div>
        ) : (
          <div className="space-y-3">
            <div className="grid gap-2 sm:grid-cols-3">
              <div className="rounded-lg border p-3"><div className="text-2xl font-semibold">{baseIssueCount}</div><div className="text-xs text-muted-foreground">review items</div></div>
              <div className="rounded-lg border p-3"><div className="text-2xl font-semibold">{gaps.length}</div><div className="text-xs text-muted-foreground">possible citation gaps</div></div>
              <div className="rounded-lg border p-3"><div className="text-2xl font-semibold">{candidates.length}</div><div className="text-xs text-muted-foreground">citations verifiable locally</div></div>
            </div>

            <div className="flex flex-wrap gap-2">
              <Button size="sm" variant="outline" onClick={() => setShowDetails((value) => !value)}>{showDetails ? 'Hide details' : 'Review issues'}</Button>
              <Button size="sm" disabled={verifying || candidates.length === 0} onClick={() => void verifyLocal()}>
                {verifying ? <LoaderCircle className="mr-1 size-3.5 animate-spin" /> : <ShieldCheck className="mr-1 size-3.5" />}
                Verify local citations
              </Button>
            </div>

            {verifying && <div className="text-xs text-muted-foreground">Verifying {verifyProgress.completed}/{verifyProgress.total} against the cited local papers…</div>}
            {error && <div className="rounded border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive">{error}</div>}

            {showDetails && (
              <div className="space-y-2" data-testid="citation-sufficiency-details">
                {gaps.map((finding) => (
                  <div key={finding.id} className="rounded border p-2 text-xs">
                    <div className="font-medium">{finding.title} · {finding.file}:{finding.line}</div>
                    <div className="mt-1 text-muted-foreground">{finding.message}</div>
                  </div>
                ))}
                {auditIssues.map((issue) => (
                  <div key={issue.id} className="rounded border p-2 text-xs">
                    <div className="font-medium">{issue.kind === 'incomplete-metadata' ? 'Incomplete bibliography metadata' : 'Bibliography/citation issue'}{issue.target ? ` · ${issue.target}` : ''}</div>
                    <div className="mt-1 text-muted-foreground">{issue.message}</div>
                  </div>
                ))}
                {baseIssueCount === 0 && <div className="rounded bg-muted/40 p-3 text-xs text-muted-foreground">No deterministic citation gaps or bibliography integrity issues were found by this conservative scan.</div>}
              </div>
            )}

            {verifications.length > 0 && (
              <div className="space-y-2 border-t pt-3" data-testid="citation-sufficiency-verification-results">
                <div className="text-xs font-medium">Local evidence verification · {weakCount} need closer review</div>
                {verifications.map((item) => (
                  <div key={item.id} className="rounded border p-2 text-xs">
                    <div className="font-medium">{item.key} · {verificationLabel(item.verification.status)}</div>
                    <div className="mt-0.5 text-[11px] text-muted-foreground">{item.file}:{item.line} · {item.paperTitle}</div>
                    <div className="mt-1 leading-5">{item.verification.rationale}</div>
                    {item.verification.evidence.length > 0 && (
                      <div className="mt-2 flex flex-wrap gap-1">
                        {item.verification.evidence.map((evidence) => (
                          <button key={evidence.sourceId} type="button" className="rounded bg-muted px-2 py-1 hover:bg-accent" onClick={() => onOpenPaper?.(evidence.paperId, evidence.pageStart)}>
                            {evidence.paperTitle} · p. {evidence.pageStart}
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
}
