import { useState, useEffect } from 'react'
import { useParams, Link, useNavigate } from 'react-router-dom'
import { usePR, useMergePR, useClosePR, useReopenPR, useUpdatePR } from '../api/queries/prs'
import { useRepoDiff } from '../api/queries/repos'
import { useMergeStrategies } from '../api/queries/workflow'
import { useAuth } from '../contexts/AuthContext'
import { DiffViewer } from '../components/diff/DiffViewer'
import { Skeleton } from '../ui/Skeleton'
import { cn } from '../lib/utils'
import type { PRReviewer } from '../types/api'

function timeAgo(iso: string): string {
  const diff = Date.now() - new Date(iso).getTime()
  const min = Math.floor(diff / 60_000)
  if (min < 1) return 'just now'
  if (min < 60) return `${min}m ago`
  const hr = Math.floor(min / 60)
  if (hr < 24) return `${hr}h ago`
  const d = Math.floor(hr / 24)
  if (d < 30) return `${d}d ago`
  return `${Math.floor(d / 30)}mo ago`
}

function formatDate(iso: string): string {
  return new Date(iso).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
}

// ── Status badge ──────────────────────────────────────────────────────────────

function StatusBadge({ status }: { status: string }) {
  const styles = {
    open:   { bg: 'bg-[#E3FCEF] border-[#79F2C0] text-[#006644]', dot: 'bg-[#00875A]', label: 'Open' },
    merged: { bg: 'bg-[#EAE6FF] border-[#C0B6F2] text-[#403294]', dot: 'bg-[#6554C0]', label: 'Merged' },
    closed: { bg: 'bg-[var(--c-surface-muted)] border-[var(--c-border)] text-[var(--c-muted)]', dot: 'bg-[var(--c-muted)]', label: 'Closed' },
  }[status] ?? { bg: '', dot: '', label: status }

  return (
    <span className={cn('inline-flex items-center gap-1.5 text-xs font-semibold px-2.5 py-1 rounded-full border', styles.bg)}>
      <span className={cn('w-1.5 h-1.5 rounded-full', styles.dot)} />
      {styles.label}
    </span>
  )
}

// ── Reviewer avatar ───────────────────────────────────────────────────────────

function ReviewerAvatar({ rv }: { rv: PRReviewer }) {
  const color = `hsl(${(rv.username.charCodeAt(0) * 37) % 360},55%,45%)`
  return (
    <div className="flex items-center gap-2">
      {rv.avatarUrl ? (
        <img src={rv.avatarUrl} alt={rv.username} className="w-6 h-6 rounded-full object-cover shrink-0" />
      ) : (
        <div className="w-6 h-6 rounded-full flex items-center justify-center text-white text-[10px] font-bold shrink-0" style={{ backgroundColor: color }}>
          {rv.username[0].toUpperCase()}
        </div>
      )}
      <span className="text-xs text-[var(--c-text)]">{rv.username}</span>
    </div>
  )
}

// ── Merge strategy selector ───────────────────────────────────────────────────

const STRATEGIES = [
  { value: 'merge',  label: 'Merge commit',    desc: 'Preserve all commits with a merge commit' },
  { value: 'squash', label: 'Squash and merge', desc: 'Combine all commits into one' },
  { value: 'rebase', label: 'Rebase and merge', desc: 'Rebase commits onto the target branch' },
] as const

export default function PRDetailPage() {
  const { owner = '', repo = '', prId = '' } = useParams<{ owner: string; repo: string; prId: string }>()
  const navigate = useNavigate()
  const { user } = useAuth()
  const numId = parseInt(prId, 10)

  const { data: pr, isLoading, isError } = usePR(owner, repo, numId)
  const { data: strategies } = useMergeStrategies(owner, repo)
  const { data: diffs = [] } = useRepoDiff(owner, repo, pr?.targetBranch ?? '', pr?.sourceBranch ?? '')

  const merge  = useMergePR(owner, repo)
  const close  = useClosePR(owner, repo)
  const reopen = useReopenPR(owner, repo)
  const update = useUpdatePR(owner, repo, numId)

  // Merge strategy
  const [strategy, setStrategy] = useState<'merge' | 'squash' | 'rebase'>('merge')
  const [mergeError, setMergeError] = useState('')

  // Inline title editing
  const [editingTitle, setEditingTitle] = useState(false)
  const [titleDraft, setTitleDraft] = useState('')
  const [editingBody, setEditingBody] = useState(false)
  const [bodyDraft, setBodyDraft] = useState('')

  useEffect(() => {
    if (pr) {
      setTitleDraft(pr.title)
      setBodyDraft(pr.body)
      // Set default strategy to first allowed one
      if (strategies) {
        if (strategies.allowMergeCommit) setStrategy('merge')
        else if (strategies.allowSquash) setStrategy('squash')
        else if (strategies.allowRebase) setStrategy('rebase')
      }
    }
  }, [pr, strategies])

  if (isLoading) {
    return (
      <div className="max-w-5xl mx-auto px-4 py-6 space-y-4">
        <Skeleton className="h-4 w-48 rounded" />
        <Skeleton className="h-7 w-3/4 rounded" />
        <Skeleton className="h-4 w-56 rounded" />
        <div className="grid grid-cols-1 lg:grid-cols-[1fr_272px] gap-6 mt-6">
          <div className="space-y-4">
            <Skeleton className="h-28 rounded" />
            <Skeleton className="h-64 rounded" />
          </div>
          <div className="space-y-3">
            <Skeleton className="h-32 rounded" />
            <Skeleton className="h-24 rounded" />
          </div>
        </div>
      </div>
    )
  }

  if (isError || !pr) {
    return (
      <div className="max-w-5xl mx-auto px-4 py-12 text-center">
        <p className="text-4xl font-bold text-[var(--c-border)] mb-3">404</p>
        <p className="text-sm text-[var(--c-muted)] mb-4">Pull request not found.</p>
        <Link to={`/repos/${owner}/${repo}/pulls`} className="text-sm text-[var(--c-brand)] hover:underline">
          ← Back to pull requests
        </Link>
      </div>
    )
  }

  const isAuthor = user?.id === pr.authorId
  const canEdit = isAuthor || user?.isAdmin
  const isOpen = pr.status === 'open'
  const isMerged = pr.status === 'merged'
  const isClosed = pr.status === 'closed'

  const allowedStrategies = STRATEGIES.filter(s => {
    if (!strategies) return true
    if (s.value === 'merge') return strategies.allowMergeCommit
    if (s.value === 'squash') return strategies.allowSquash
    if (s.value === 'rebase') return strategies.allowRebase
    return false
  })

  async function handleMerge() {
    setMergeError('')
    try {
      await merge.mutateAsync({ prId: numId, strategy })
      navigate(`/repos/${owner}/${repo}/pulls`)
    } catch (e: any) {
      setMergeError(e.message ?? 'Merge failed.')
    }
  }

  async function saveTitle() {
    if (titleDraft.trim() === pr!.title) { setEditingTitle(false); return }
    await update.mutateAsync({ title: titleDraft.trim() })
    setEditingTitle(false)
  }

  async function saveBody() {
    if (bodyDraft === pr!.body) { setEditingBody(false); return }
    await update.mutateAsync({ body: bodyDraft })
    setEditingBody(false)
  }

  const statLine = (
    <p className="text-xs text-[var(--c-muted)] mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5">
      <span>#{pr.id}</span>
      <span>·</span>
      <span className="font-mono bg-[var(--c-surface-muted)] px-1 rounded">{pr.sourceBranch}</span>
      <span className="text-[var(--c-subtle)]">→</span>
      <span className="font-mono bg-[var(--c-surface-muted)] px-1 rounded">{pr.targetBranch}</span>
      <span>·</span>
      <span>opened {timeAgo(pr.createdAt)}</span>
      {pr.updatedAt !== pr.createdAt && <><span>·</span><span>updated {timeAgo(pr.updatedAt)}</span></>}
    </p>
  )

  return (
    <div className="max-w-5xl mx-auto px-4 md:px-6 py-6 space-y-5">
      {/* Breadcrumb */}
      <div className="flex items-center gap-1 text-sm flex-wrap">
        <Link to={`/repos/${owner}/${repo}`} className="text-[var(--c-brand)] hover:underline">{repo}</Link>
        <span className="text-[var(--c-muted)]">/</span>
        <Link to={`/repos/${owner}/${repo}/pulls`} className="text-[var(--c-brand)] hover:underline">Pull requests</Link>
        <span className="text-[var(--c-muted)]">/</span>
        <span className="text-[var(--c-text)]">#{pr.id}</span>
      </div>

      {/* Title row */}
      <div>
        {editingTitle ? (
          <div className="flex items-center gap-2">
            <input
              value={titleDraft}
              onChange={e => setTitleDraft(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') saveTitle(); if (e.key === 'Escape') setEditingTitle(false) }}
              className="flex-1 text-xl font-semibold border border-[var(--c-brand-focus)] rounded px-3 py-1.5 bg-[var(--c-surface)] text-[var(--c-text)] focus:outline-none"
              autoFocus
            />
            <button onClick={saveTitle} disabled={update.isPending}
              className="px-3 py-1.5 rounded bg-[var(--c-brand)] text-white text-sm font-medium hover:bg-[var(--c-brand-hover)] disabled:opacity-50">
              Save
            </button>
            <button onClick={() => setEditingTitle(false)}
              className="px-3 py-1.5 rounded border border-[var(--c-border)] text-sm text-[var(--c-text)] hover:bg-[var(--c-surface-muted)]">
              Cancel
            </button>
          </div>
        ) : (
          <div className="flex items-start gap-3 flex-wrap">
            <h1 className="text-xl font-semibold text-[var(--c-text)] flex-1 min-w-0">{pr.title}</h1>
            <div className="flex items-center gap-2 shrink-0">
              <StatusBadge status={pr.status} />
              {canEdit && isOpen && (
                <button onClick={() => setEditingTitle(true)}
                  className="p-1.5 rounded text-[var(--c-muted)] hover:text-[var(--c-text)] hover:bg-[var(--c-surface-muted)] transition-colors"
                  title="Edit title">
                  <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125" />
                  </svg>
                </button>
              )}
            </div>
          </div>
        )}
        {statLine}
      </div>

      {/* Main 2-col layout */}
      <div className="grid grid-cols-1 lg:grid-cols-[1fr_272px] gap-6 items-start">

        {/* ── Left: description + diff ── */}
        <div className="space-y-5 min-w-0">

          {/* Description */}
          <div className="border border-[var(--c-border)] rounded-lg overflow-hidden">
            <div className="flex items-center justify-between px-4 py-2.5 bg-[var(--c-surface-muted)] border-b border-[var(--c-border)]">
              <span className="text-xs font-semibold text-[var(--c-muted)] uppercase tracking-wider">Description</span>
              {canEdit && isOpen && !editingBody && (
                <button onClick={() => setEditingBody(true)}
                  className="flex items-center gap-1 text-xs text-[var(--c-muted)] hover:text-[var(--c-text)] transition-colors">
                  <svg width="11" height="11" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125" />
                  </svg>
                  Edit
                </button>
              )}
            </div>
            {editingBody ? (
              <div className="p-4 space-y-3">
                <textarea value={bodyDraft} onChange={e => setBodyDraft(e.target.value)}
                  rows={8} className="w-full border border-[var(--c-border)] rounded px-3 py-2 text-sm font-mono bg-[var(--c-surface)] text-[var(--c-text)] focus:outline-none focus:border-[var(--c-brand-focus)] resize-y" />
                <div className="flex gap-2">
                  <button onClick={saveBody} disabled={update.isPending}
                    className="px-3 py-1.5 rounded bg-[var(--c-brand)] text-white text-sm font-medium hover:bg-[var(--c-brand-hover)] disabled:opacity-50">
                    {update.isPending ? 'Saving…' : 'Save'}
                  </button>
                  <button onClick={() => { setBodyDraft(pr.body); setEditingBody(false) }}
                    className="px-3 py-1.5 rounded border border-[var(--c-border)] text-sm text-[var(--c-text)] hover:bg-[var(--c-surface-muted)]">
                    Cancel
                  </button>
                </div>
              </div>
            ) : (
              <div className="px-4 py-3">
                {pr.body ? (
                  <p className="text-sm text-[var(--c-text)] whitespace-pre-wrap leading-relaxed">{pr.body}</p>
                ) : (
                  <p className="text-sm text-[var(--c-muted)] italic">No description provided.</p>
                )}
              </div>
            )}
          </div>

          {/* Status banner for non-open PRs */}
          {(isMerged || isClosed) && (
            <div className={cn(
              'flex items-center gap-3 px-4 py-3 rounded-lg border text-sm font-medium',
              isMerged ? 'border-[#C0B6F2] bg-[#EAE6FF] text-[#403294]' : 'border-[var(--c-border)] bg-[var(--c-surface-muted)] text-[var(--c-muted)]',
            )}>
              {isMerged ? (
                <>
                  <svg width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
                  </svg>
                  Merged on {formatDate(pr.updatedAt)}
                </>
              ) : (
                <>
                  <svg width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
                  </svg>
                  Closed on {formatDate(pr.updatedAt)} without merging
                </>
              )}
            </div>
          )}

          {/* Files changed */}
          <div className="border border-[var(--c-border)] rounded-lg overflow-hidden">
            <div className="flex items-center justify-between px-4 py-2.5 bg-[var(--c-surface-muted)] border-b border-[var(--c-border)]">
              <span className="text-xs font-semibold text-[var(--c-muted)] uppercase tracking-wider">
                Files changed
                {diffs.length > 0 && (
                  <span className="ml-1.5 text-[var(--c-text)]">({diffs.length})</span>
                )}
              </span>
              <div className="flex items-center gap-2 text-xs">
                {diffs.length > 0 && (
                  <>
                    <span className="text-[#006644]">+{diffs.reduce((s, f) => s + f.additions, 0)}</span>
                    <span className="text-[var(--c-danger)]">−{diffs.reduce((s, f) => s + f.deletions, 0)}</span>
                  </>
                )}
              </div>
            </div>
            {diffs.length === 0 ? (
              <div className="px-4 py-8 text-center text-sm text-[var(--c-muted)]">
                {pr.sourceBranch && pr.targetBranch
                  ? 'No differences detected between branches.'
                  : 'Diff unavailable — branches may not exist locally.'}
              </div>
            ) : (
              <>
                {/* File list */}
                <ul className="border-b border-[var(--c-border)] divide-y divide-[var(--c-border)] max-h-40 overflow-y-auto">
                  {diffs.map(f => (
                    <li key={f.path} className="flex items-center gap-2 px-3 py-1.5 text-xs font-mono hover:bg-[var(--c-surface-muted)]">
                      <span className="text-[#006644] tabular-nums w-8 text-right shrink-0">+{f.additions}</span>
                      <span className="text-[var(--c-danger)] tabular-nums w-8 text-right shrink-0">−{f.deletions}</span>
                      <span className="text-[var(--c-text)] truncate">{f.path}</span>
                    </li>
                  ))}
                </ul>
                <DiffViewer files={diffs} />
              </>
            )}
          </div>
        </div>

        {/* ── Right sidebar ── */}
        <div className="space-y-4">

          {/* Merge / close / reopen actions */}
          {isOpen && (
            <div className="border border-[var(--c-border)] rounded-lg overflow-hidden">
              <div className="px-4 py-2.5 bg-[var(--c-surface-muted)] border-b border-[var(--c-border)]">
                <span className="text-xs font-semibold text-[var(--c-muted)] uppercase tracking-wider">Merge pull request</span>
              </div>
              <div className="p-4 space-y-3">
                {allowedStrategies.length > 0 ? (
                  <>
                    <div className="space-y-1.5">
                      {allowedStrategies.map(s => (
                        <label key={s.value} className="flex items-start gap-2.5 cursor-pointer group">
                          <input type="radio" name="strategy" value={s.value}
                            checked={strategy === s.value}
                            onChange={() => setStrategy(s.value)}
                            className="mt-0.5 accent-[var(--c-brand)]" />
                          <div>
                            <span className="text-sm font-medium text-[var(--c-text)] group-hover:text-[var(--c-brand)] transition-colors">{s.label}</span>
                            <p className="text-xs text-[var(--c-muted)]">{s.desc}</p>
                          </div>
                        </label>
                      ))}
                    </div>
                    {mergeError && <p className="text-xs text-[var(--c-danger)]">{mergeError}</p>}
                    <button onClick={handleMerge} disabled={merge.isPending}
                      className="w-full py-2 rounded bg-[#6554C0] text-white text-sm font-medium hover:bg-[#5243AA] disabled:opacity-50 transition-colors">
                      {merge.isPending ? 'Merging…' : 'Merge pull request'}
                    </button>
                  </>
                ) : (
                  <p className="text-xs text-[var(--c-muted)]">No merge strategies are enabled for this repository.</p>
                )}
                <button onClick={() => close.mutate(numId)} disabled={close.isPending}
                  className="w-full py-1.5 rounded border border-[var(--c-border)] text-sm text-[var(--c-muted)] hover:text-[var(--c-danger)] hover:border-[var(--c-danger)] disabled:opacity-50 transition-colors">
                  {close.isPending ? 'Closing…' : 'Close without merging'}
                </button>
              </div>
            </div>
          )}

          {isClosed && (
            <div className="border border-[var(--c-border)] rounded-lg overflow-hidden">
              <div className="p-4">
                <button onClick={() => reopen.mutate(numId)} disabled={reopen.isPending}
                  className="w-full py-2 rounded border border-[var(--c-brand)] text-[var(--c-brand)] text-sm font-medium hover:bg-[var(--c-brand-tint)] disabled:opacity-50 transition-colors">
                  {reopen.isPending ? 'Reopening…' : 'Reopen pull request'}
                </button>
              </div>
            </div>
          )}

          {/* Reviewers */}
          <div className="border border-[var(--c-border)] rounded-lg overflow-hidden">
            <div className="px-4 py-2.5 bg-[var(--c-surface-muted)] border-b border-[var(--c-border)]">
              <span className="text-xs font-semibold text-[var(--c-muted)] uppercase tracking-wider">Reviewers</span>
            </div>
            <div className="p-3 space-y-2">
              {pr.reviewers.length === 0 ? (
                <p className="text-xs text-[var(--c-muted)]">No reviewers assigned.</p>
              ) : (
                pr.reviewers.map(rv => <ReviewerAvatar key={rv.userId} rv={rv} />)
              )}
            </div>
          </div>

          {/* Metadata */}
          <div className="border border-[var(--c-border)] rounded-lg overflow-hidden">
            <div className="px-4 py-2.5 bg-[var(--c-surface-muted)] border-b border-[var(--c-border)]">
              <span className="text-xs font-semibold text-[var(--c-muted)] uppercase tracking-wider">Details</span>
            </div>
            <dl className="p-3 space-y-2.5 text-xs">
              {[
                { label: 'From', value: <span className="font-mono text-[var(--c-text)]">{pr.sourceBranch}</span> },
                { label: 'Into', value: <span className="font-mono text-[var(--c-text)]">{pr.targetBranch}</span> },
                { label: 'Opened', value: <span className="text-[var(--c-text)]" title={pr.createdAt}>{formatDate(pr.createdAt)}</span> },
                { label: 'Updated', value: <span className="text-[var(--c-text)]" title={pr.updatedAt}>{timeAgo(pr.updatedAt)}</span> },
              ].map(row => (
                <div key={row.label} className="flex items-center justify-between gap-2">
                  <dt className="text-[var(--c-muted)] shrink-0">{row.label}</dt>
                  <dd className="truncate">{row.value}</dd>
                </div>
              ))}
            </dl>
          </div>

          {/* Quick links */}
          <div className="flex flex-col gap-1">
            <Link to={`/repos/${owner}/${repo}/pulls`}
              className="flex items-center gap-2 text-xs text-[var(--c-muted)] hover:text-[var(--c-brand)] transition-colors px-1 py-0.5">
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" />
              </svg>
              All pull requests
            </Link>
            <Link to={`/repos/${owner}/${repo}/pulls/new`}
              className="flex items-center gap-2 text-xs text-[var(--c-muted)] hover:text-[var(--c-brand)] transition-colors px-1 py-0.5">
              <svg width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
              </svg>
              New pull request
            </Link>
          </div>
        </div>
      </div>
    </div>
  )
}
