import { Button, DiffViewer } from '@overdeck/deck-ui'
import { useEffect, useState, type JSX } from 'react'
import type { RequestStoryAttachment, RequestStoryCoverage, RequestStoryEvidenceLink } from '@overdeck/report-contract'
import { useFactoryRun } from '../../lib/collector-queries'
import { FactoryPhaseTable } from '../factory/FactoryPhaseTable'
import { FactoryAttemptTable, FactoryDiffTable, FactoryGateTable } from '../factory/FactoryTraceTables'

function coverageStatusLabel(status: RequestStoryCoverage['status']): string {
  if (status === 'complete') return 'Complete'
  if (status === 'partial') return 'Partial'
  if (status === 'unavailable') return 'Unavailable'
  if (status === 'stale') return 'Stale'
  return 'Waiting for delivery'
}

function FactoryRunEvidence({ link }: { link: RequestStoryEvidenceLink }): JSX.Element {
  const query = useFactoryRun(link.targetId, true, false)
  const run = query.data
  const unavailable = new Set(run?.unavailableTables ?? [])

  return (
    <article className="requests-work-run">
      <div className="requests-work-heading">
        <div>
          <h4>Work run</h4>
          <p>{typeof link.metadata.status === 'string' ? link.metadata.status : 'Status not recorded'}</p>
        </div>
        <a href={`/factory/${encodeURIComponent(link.targetId)}`}>Open full run</a>
      </div>
      {query.isPending ? <p className="requests-drawer-gap">Loading recorded run evidence…</p> : null}
      {query.isError ? <p className="requests-drawer-gap">The linked run exists, but its detailed trace could not be loaded.</p> : null}
      {run ? (
        <div className="requests-work-details">
          <div className="requests-work-facts">
            <span>State: {run.status ?? 'not recorded'}</span>
            <span>Repository: {run.repo ?? 'not recorded'}</span>
          </div>
          <div>
            <h4>Phases and retries</h4>
            {run.phases.length > 0
              ? <FactoryPhaseTable phases={run.phases} attempts={run.attempts ?? []} />
              : <p className="requests-drawer-gap">No phases were recorded for this run.</p>}
          </div>
          <div>
            <h4>Attempts, tools, sessions, hosts, and accounts</h4>
            {unavailable.has('agent_attempts')
              ? <p className="requests-drawer-gap">This run’s Factory version did not record agent attempts.</p>
              : (run.attempts?.length ?? 0) > 0
                ? <FactoryAttemptTable attempts={run.attempts ?? []} runAttempts={run.attempts ?? []} />
                : <p className="requests-drawer-gap">No agent attempts were recorded for this run.</p>}
          </div>
          <div>
            <h4>Gate verdicts</h4>
            {unavailable.has('gate_results')
              ? <p className="requests-drawer-gap">This run’s Factory version did not record gate verdicts.</p>
              : (run.gates?.length ?? 0) > 0
                ? <FactoryGateTable gates={run.gates ?? []} />
                : <p className="requests-drawer-gap">No gate verdicts were recorded for this run.</p>}
          </div>
          <div>
            <h4>Structured changes</h4>
            {unavailable.has('phase_diffs')
              ? <p className="requests-drawer-gap">This run’s Factory version did not record structured changes.</p>
              : (run.diffs?.length ?? 0) > 0
                ? <FactoryDiffTable diffs={run.diffs ?? []} />
                : <p className="requests-drawer-gap">No structured changes were recorded for this run.</p>}
          </div>
        </div>
      ) : null}
    </article>
  )
}

function AttachmentEvidence({ requestId, attachment }: { requestId: string; attachment: RequestStoryAttachment }): JSX.Element {
  const [content, setContent] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [expanded, setExpanded] = useState(attachment.mediaType === 'text/x-diff')
  const expectedUrl = `/api/collector/requests/${encodeURIComponent(requestId)}/attachments/${encodeURIComponent(attachment.digest)}`

  useEffect(() => {
    if (!expanded || attachment.status !== 'available' || content !== null) return
    const controller = new AbortController()
    void fetch(expectedUrl, { signal: controller.signal })
      .then((response) => {
        if (!response.ok) throw new Error(`Evidence could not be loaded (${response.status}).`)
        return response.text()
      })
      .then(setContent)
      .catch((cause: unknown) => {
        if (!controller.signal.aborted) setError(cause instanceof Error ? cause.message : 'Evidence could not be loaded.')
      })
    return () => controller.abort()
  }, [attachment.status, content, expanded, expectedUrl])

  return (
    <article className="requests-work-attachment">
      <div className="requests-work-heading">
        <div>
          <h4>{attachment.mediaType === 'text/x-diff' ? 'Attached change' : attachment.mediaType === 'application/json' ? 'Attached data' : 'Attached log'}</h4>
          <p>{attachment.byteCount.toLocaleString()} bytes · {attachment.redactionStatus === 'redacted' ? 'redacted' : 'redaction not required'}{attachment.truncated ? ' · truncated' : ''}</p>
        </div>
        {attachment.status === 'available' ? <Button size="sm" variant="ghost" tone="neutral" onClick={() => setExpanded((value: boolean) => !value)} aria-expanded={expanded}>{expanded ? 'Hide' : 'Open'}</Button> : null}
      </div>
      {attachment.status !== 'available' ? <p className="requests-drawer-gap">This evidence is {attachment.status}.</p> : null}
      {expanded && !content && !error ? <p className="requests-drawer-gap">Loading evidence…</p> : null}
      {error ? <p className="requests-drawer-gap">{error}</p> : null}
      {content && attachment.mediaType === 'text/x-diff' ? <DiffViewer diff={content} ariaLabel="Recorded request change" /> : null}
      {content && attachment.mediaType !== 'text/x-diff' ? <pre className="requests-work-text">{content}</pre> : null}
    </article>
  )
}

export function RequestWorkEvidence({ requestId, links, attachments, coverage }: {
  requestId: string
  links: RequestStoryEvidenceLink[]
  attachments: RequestStoryAttachment[]
  coverage?: RequestStoryCoverage
}): JSX.Element {
  const factoryRuns = links.filter((link) => link.kind === 'factory_run' && link.targetSource === 'factory-trace')
  const directWork = links.filter((link) => link.kind !== 'factory_run')

  return (
    <section aria-labelledby="request-work-evidence">
      <h3 id="request-work-evidence">Work evidence</h3>
      {factoryRuns.map((link) => <FactoryRunEvidence key={`${link.targetSource}:${link.targetId}`} link={link} />)}
      {directWork.length > 0 ? (
        <ul className="requests-work-links">
          {directWork.map((link) => <li key={`${link.kind}:${link.targetSource}:${link.targetId}`}>{link.kind.replace('_', ' ')} · {link.targetSource}</li>)}
        </ul>
      ) : null}
      {attachments.map((attachment) => <AttachmentEvidence key={attachment.digest} requestId={requestId} attachment={attachment} />)}
      {factoryRuns.length === 0 && directWork.length === 0 && attachments.length === 0 && coverage?.reason
        ? <p className="requests-drawer-gap">{coverage.reason}</p>
        : null}
      {coverage ? <p className="requests-drawer-gap">Work records · {coverageStatusLabel(coverage.status)}{coverage.reason && (factoryRuns.length > 0 || directWork.length > 0 || attachments.length > 0) ? ` — ${coverage.reason}` : ''}</p> : null}
    </section>
  )
}
