import { useState, useEffect, useRef } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { useExploreRepos, useExploreUsers } from '../api/queries/explore'
import type { ExploreRepo, ExploreUser } from '../api/queries/explore'
import { Skeleton } from '../ui/Skeleton'

const PAGE_SIZE = 20

function hashColor(s: string): string {
  let h = 0
  for (let i = 0; i < s.length; i++) h = (Math.imul(31, h) + s.charCodeAt(i)) | 0
  const hue = Math.abs(h) % 360
  return `hsl(${hue},55%,45%)`
}

function timeAgo(iso: string): string {
  const diff = Date.now() - new Date(iso).getTime()
  const min = Math.floor(diff / 60000)
  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`
  const mo = Math.floor(d / 30)
  if (mo < 12) return `${mo}mo ago`
  return `${Math.floor(mo / 12)}y ago`
}

export default function ExplorePage() {
  const [searchParams, setSearchParams] = useSearchParams()
  const tab = (searchParams.get('tab') ?? 'repos') as 'repos' | 'users'
  const sort = searchParams.get('sort') ?? 'updated'
  const [inputValue, setInputValue] = useState(searchParams.get('q') ?? '')
  const [q, setQ] = useState(searchParams.get('q') ?? '')
  const [offset, setOffset] = useState(0)
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  // Debounce search input
  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current)
    debounceRef.current = setTimeout(() => {
      setQ(inputValue)
      setOffset(0)
      setSearchParams(prev => {
        const next = new URLSearchParams(prev)
        if (inputValue) next.set('q', inputValue)
        else next.delete('q')
        next.delete('offset')
        return next
      }, { replace: true })
    }, 300)
    return () => { if (debounceRef.current) clearTimeout(debounceRef.current) }
  }, [inputValue])

  function setTab(t: string) {
    setOffset(0)
    setSearchParams(prev => {
      const next = new URLSearchParams(prev)
      next.set('tab', t)
      next.delete('offset')
      return next
    }, { replace: true })
  }

  function setSort(s: string) {
    setOffset(0)
    setSearchParams(prev => {
      const next = new URLSearchParams(prev)
      next.set('sort', s)
      next.delete('offset')
      return next
    }, { replace: true })
  }

  return (
    <div className="max-w-4xl mx-auto px-4 md:px-6 py-6 space-y-5">
      <div>
        <h1 className="text-xl font-semibold text-[var(--c-text)]">Explore</h1>
        <p className="text-sm text-[var(--c-muted)] mt-0.5">Discover public repositories and users.</p>
      </div>

      {/* Search bar */}
      <div className="relative">
        <svg className="absolute left-3 top-1/2 -translate-y-1/2 text-[var(--c-muted)] pointer-events-none" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
        </svg>
        <input
          value={inputValue}
          onChange={e => setInputValue(e.target.value)}
          placeholder={tab === 'repos' ? 'Search repositories…' : 'Search users…'}
          className="w-full border border-[var(--c-border)] rounded-lg pl-10 pr-4 py-2.5 text-sm bg-[var(--c-surface)] text-[var(--c-text)] focus:outline-none focus:border-[var(--c-brand-focus)] transition-colors"
        />
        {inputValue && (
          <button onClick={() => setInputValue('')} className="absolute right-3 top-1/2 -translate-y-1/2 text-[var(--c-muted)] hover:text-[var(--c-text)]">
            <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
            </svg>
          </button>
        )}
      </div>

      {/* Tabs + sort */}
      <div className="flex items-center justify-between">
        <div className="flex border-b border-[var(--c-border)] w-full">
          <div className="flex gap-0 flex-1">
            {(['repos', 'users'] as const).map(t => (
              <button key={t} onClick={() => setTab(t)}
                className={`px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors capitalize ${tab === t ? 'border-[var(--c-brand)] text-[var(--c-brand)]' : 'border-transparent text-[var(--c-muted)] hover:text-[var(--c-text)]'}`}>
                {t === 'repos' ? 'Repositories' : 'Users'}
              </button>
            ))}
          </div>
          {tab === 'repos' && (
            <div className="flex items-center gap-1 pb-1 shrink-0">
              <span className="text-xs text-[var(--c-muted)]">Sort:</span>
              <select value={sort} onChange={e => setSort(e.target.value)}
                className="text-xs border border-[var(--c-border)] rounded px-2 py-1 bg-[var(--c-surface)] text-[var(--c-text)] focus:outline-none focus:border-[var(--c-brand-focus)]">
                <option value="updated">Recently updated</option>
                <option value="created">Newest</option>
                <option value="name">Name A–Z</option>
              </select>
            </div>
          )}
        </div>
      </div>

      {/* Results */}
      {tab === 'repos'
        ? <RepoResults q={q} sort={sort} offset={offset} setOffset={setOffset} />
        : <UserResults q={q} offset={offset} setOffset={setOffset} />
      }
    </div>
  )
}

function RepoResults({ q, sort, offset, setOffset }: { q: string; sort: string; offset: number; setOffset: (n: number) => void }) {
  const { data: repos = [], isLoading, isFetching } = useExploreRepos(q, sort, offset)

  if (isLoading) return <RepoSkeleton />

  if (repos.length === 0 && !isFetching) {
    return (
      <div className="flex flex-col items-center justify-center py-16 text-center">
        <svg width="36" height="36" fill="none" stroke="var(--c-border)" strokeWidth="1.2" viewBox="0 0 24 24" className="mb-3">
          <path strokeLinecap="round" strokeLinejoin="round" d="M2.25 12.75V12A2.25 2.25 0 0 1 4.5 9.75h15A2.25 2.25 0 0 1 21.75 12v.75m-8.69-6.44-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v8.25A2.25 2.25 0 0 0 4.5 16.5h15a2.25 2.25 0 0 0 2.25-2.25V9A2.25 2.25 0 0 0 19.5 6.75h-1.06l-2.44-2.44a1.5 1.5 0 0 0-1.061-.44H8.69Z" />
        </svg>
        <p className="text-sm font-medium text-[var(--c-text)]">{q ? `No repositories match "${q}"` : 'No public repositories yet'}</p>
        <p className="text-xs text-[var(--c-muted)] mt-1">Try a different search term.</p>
      </div>
    )
  }

  return (
    <>
      <ul className={`divide-y divide-[var(--c-border)] border border-[var(--c-border)] rounded-lg overflow-hidden transition-opacity ${isFetching ? 'opacity-60' : ''}`}>
        {repos.map(repo => <RepoCard key={repo.id} repo={repo} />)}
      </ul>
      <Pagination offset={offset} count={repos.length} pageSize={PAGE_SIZE} onPrev={() => setOffset(Math.max(0, offset - PAGE_SIZE))} onNext={() => setOffset(offset + PAGE_SIZE)} />
    </>
  )
}

function RepoCard({ repo }: { repo: ExploreRepo }) {
  const color = hashColor(repo.ownerUsername + repo.name)
  return (
    <li className="flex items-start gap-4 px-4 py-4 bg-[var(--c-surface)] hover:bg-[var(--c-surface-muted)] transition-colors">
      <div className="shrink-0 w-9 h-9 rounded-md flex items-center justify-center text-white text-sm font-bold" style={{ backgroundColor: color }}>
        {repo.name.slice(0, 1).toUpperCase()}
      </div>
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2 flex-wrap">
          <Link to={`/repos/${repo.ownerUsername}/${repo.name}`}
            className="text-sm font-semibold text-[var(--c-brand)] hover:underline truncate">
            {repo.ownerUsername}/{repo.name}
          </Link>
          {repo.isPrivate && (
            <span className="text-[10px] font-semibold uppercase tracking-wider border border-[var(--c-border)] text-[var(--c-muted)] px-1.5 py-0.5 rounded-full">Private</span>
          )}
        </div>
        {repo.description && (
          <p className="text-xs text-[var(--c-muted)] mt-0.5 line-clamp-2">{repo.description}</p>
        )}
        <div className="flex items-center gap-3 mt-1.5">
          <span className="flex items-center gap-1 text-[10px] text-[var(--c-muted)]">
            <svg width="10" height="10" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" d="M9.568 3H5.25A2.25 2.25 0 0 0 3 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 0 0 5.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 0 0 9.568 3Z" />
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 6h.008v.008H6V6Z" />
            </svg>
            {repo.defaultBranch}
          </span>
          <span className="text-[10px] text-[var(--c-muted)]">Updated {timeAgo(repo.updatedAt)}</span>
        </div>
      </div>
    </li>
  )
}

function UserResults({ q, offset, setOffset }: { q: string; offset: number; setOffset: (n: number) => void }) {
  const { data: users = [], isLoading, isFetching } = useExploreUsers(q, offset)

  if (isLoading) return <UserSkeleton />

  if (users.length === 0 && !isFetching) {
    return (
      <div className="flex flex-col items-center justify-center py-16 text-center">
        <svg width="36" height="36" fill="none" stroke="var(--c-border)" strokeWidth="1.2" viewBox="0 0 24 24" className="mb-3">
          <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
        </svg>
        <p className="text-sm font-medium text-[var(--c-text)]">{q ? `No users match "${q}"` : 'No users found'}</p>
      </div>
    )
  }

  return (
    <>
      <ul className={`grid grid-cols-1 sm:grid-cols-2 gap-3 transition-opacity ${isFetching ? 'opacity-60' : ''}`}>
        {users.map(user => <UserCard key={user.id} user={user} />)}
      </ul>
      <Pagination offset={offset} count={users.length} pageSize={PAGE_SIZE} onPrev={() => setOffset(Math.max(0, offset - PAGE_SIZE))} onNext={() => setOffset(offset + PAGE_SIZE)} />
    </>
  )
}

function UserCard({ user }: { user: ExploreUser }) {
  const color = hashColor(user.username)
  return (
    <li className="flex items-center gap-3 px-4 py-3 border border-[var(--c-border)] rounded-lg bg-[var(--c-surface)] hover:bg-[var(--c-surface-muted)] transition-colors">
      {user.avatarUrl ? (
        <img src={user.avatarUrl} alt={user.username} className="w-10 h-10 rounded-full object-cover shrink-0" />
      ) : (
        <div className="w-10 h-10 rounded-full flex items-center justify-center text-white text-sm font-bold shrink-0" style={{ backgroundColor: color }}>
          {user.username.slice(0, 1).toUpperCase()}
        </div>
      )}
      <div className="min-w-0">
        <Link to={`/repos?owner=${user.username}`}
          className="text-sm font-semibold text-[var(--c-brand)] hover:underline block truncate">
          {user.username}
        </Link>
        <p className="text-[10px] text-[var(--c-muted)] mt-0.5">Joined {timeAgo(user.createdAt)}</p>
      </div>
    </li>
  )
}

function Pagination({ offset, count, pageSize, onPrev, onNext }: {
  offset: number; count: number; pageSize: number; onPrev: () => void; onNext: () => void
}) {
  const hasPrev = offset > 0
  const hasNext = count >= pageSize
  if (!hasPrev && !hasNext) return null
  const page = Math.floor(offset / pageSize) + 1

  return (
    <div className="flex items-center justify-between pt-2">
      <button onClick={onPrev} disabled={!hasPrev}
        className="flex items-center gap-1.5 px-3 py-1.5 text-sm border border-[var(--c-border)] rounded text-[var(--c-text)] hover:bg-[var(--c-surface-muted)] disabled:opacity-40 disabled:cursor-not-allowed">
        <svg width="14" height="14" 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>
        Previous
      </button>
      <span className="text-xs text-[var(--c-muted)]">Page {page}</span>
      <button onClick={onNext} disabled={!hasNext}
        className="flex items-center gap-1.5 px-3 py-1.5 text-sm border border-[var(--c-border)] rounded text-[var(--c-text)] hover:bg-[var(--c-surface-muted)] disabled:opacity-40 disabled:cursor-not-allowed">
        Next
        <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" />
        </svg>
      </button>
    </div>
  )
}

function RepoSkeleton() {
  return (
    <ul className="divide-y divide-[var(--c-border)] border border-[var(--c-border)] rounded-lg overflow-hidden">
      {Array.from({ length: 5 }).map((_, i) => (
        <li key={i} className="flex items-start gap-4 px-4 py-4 bg-[var(--c-surface)]">
          <Skeleton className="w-9 h-9 rounded-md shrink-0" />
          <div className="flex-1 space-y-2">
            <Skeleton className="h-4 w-40 rounded" />
            <Skeleton className="h-3 w-3/4 rounded" />
            <Skeleton className="h-3 w-24 rounded" />
          </div>
        </li>
      ))}
    </ul>
  )
}

function UserSkeleton() {
  return (
    <ul className="grid grid-cols-1 sm:grid-cols-2 gap-3">
      {Array.from({ length: 6 }).map((_, i) => (
        <li key={i} className="flex items-center gap-3 px-4 py-3 border border-[var(--c-border)] rounded-lg bg-[var(--c-surface)]">
          <Skeleton className="w-10 h-10 rounded-full shrink-0" />
          <div className="space-y-1.5 flex-1">
            <Skeleton className="h-3.5 w-28 rounded" />
            <Skeleton className="h-2.5 w-20 rounded" />
          </div>
        </li>
      ))}
    </ul>
  )
}
