import { useEffect, useMemo, useState } from 'react'
import { AnimatePresence, motion } from 'framer-motion'
import { ArrowRight, Building2, ExternalLink, GitFork, Radio, Search, Star, X } from 'lucide-react'
import { Link } from 'react-router-dom'

import { cn } from '@/lib/utils'

const featuredProjects = [
  { slug: 'website-reliability', name: 'A portfolio reliability fix', description: 'An internal technical walkthrough: isolate a GitHub failure so the portfolio stays useful. Inspect the implementation and tests.', icon: Building2, color: 'green' as const },
  {
    slug: 'agentwire-dev',
    name: 'AgentWire',
    description: 'A self-hosted, keyboard-driven cockpit for running a whole fleet of Claude Code agents at once. An inspectable example of how we coordinate development work.',
    icon: Radio,
    color: 'green' as const,
  },
  {
    slug: 'playchek',
    to: '/playchek',
    name: 'Playchek Inspector',
    description: 'A custom offline-first inspection app — web, desktop, and native mobile — built for a playground safety consultancy in Ontario. Drop-test records to on-device PDF reports.',
    icon: Building2,
    color: 'blue' as const,
  },
]

interface Repository {
  id: number
  name: string
  description: string | null
  html_url: string
  stargazers_count: number
  forks_count: number
  language: string | null
  topics: string[]
}

const FEATURED_TOPICS = ['featured', 'production', 'active']
const FEATURED_STAR_THRESHOLD = 5

function isFeatured(repo: Repository): boolean {
  return (
    repo.stargazers_count >= FEATURED_STAR_THRESHOLD ||
    repo.topics.some((topic) => FEATURED_TOPICS.includes(topic.toLowerCase()))
  )
}

export function Projects() {
  const [repos, setRepos] = useState<Repository[]>([])
  const [loading, setLoading] = useState(true)
  const [attempt, setAttempt] = useState(0)
  const [error, setError] = useState<string | null>(null)
  const [searchQuery, setSearchQuery] = useState('')
  const [activeLanguage, setActiveLanguage] = useState<string | null>(null)

  useEffect(() => {
    const controller = new AbortController()
    const timeout = window.setTimeout(() => controller.abort(), 10000)
    let active = true
    async function fetchRepos() {
      try {
        const response = await fetch(
          'https://api.github.com/users/dotdevdotdev/repos?sort=updated&per_page=30', { signal: controller.signal }
        )
        if (!response.ok) throw new Error('Failed to fetch repositories')
        const data = await response.json()
        if (active) setRepos(data)
      } catch (err) {
        if (active) setError(err instanceof Error ? 'Repositories are temporarily unavailable.' : 'Unable to load repositories.')
      } finally {
        clearTimeout(timeout)
        if (active) setLoading(false)
      }
    }
    fetchRepos()
    return () => { active = false; clearTimeout(timeout); controller.abort() }
  }, [attempt])

  const languages = useMemo(() => {
    const langSet = new Set<string>()
    repos.forEach((repo) => {
      if (repo.language) langSet.add(repo.language)
    })
    return Array.from(langSet).sort()
  }, [repos])

  const filteredRepos = useMemo(() => {
    return repos.filter((repo) => {
      const matchesSearch =
        !searchQuery ||
        repo.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
        repo.description?.toLowerCase().includes(searchQuery.toLowerCase())
      const matchesLanguage = !activeLanguage || repo.language === activeLanguage
      return matchesSearch && matchesLanguage
    })
  }, [repos, searchQuery, activeLanguage])

  const clearFilters = () => {
    setSearchQuery('')
    setActiveLanguage(null)
  }

  return (
    <div className="container mx-auto px-4 py-12 max-w-5xl">
      <motion.div
        initial={false}
        animate={{ opacity: 1, y: 0 }}
        className="mb-8"
      >
        <h1 className="text-3xl font-bruno text-neon-green neon-glow-green mb-2">
          Projects
        </h1>
        <p className="text-muted-foreground">
          Open source projects from the .dev collective
        </p>
      </motion.div>

      <motion.div
        initial={false}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.05 }}
        className="mb-12"
      >
        <h2 className="text-xl font-bruno text-neon-blue mb-4">Featured</h2>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
          {featuredProjects.map((project) => {
            const Icon = project.icon
            const isGreen = project.color === 'green'
            const to =
              'to' in project && project.to
                ? project.to
                : `/projects/${project.slug}`
            return (
              <Link
                key={project.slug}
                to={to}
                className={cn(
                  'group p-6 card-neon transition-all duration-300',
                  isGreen
                    ? 'hover:border-neon-green hover:neon-box-green'
                    : 'hover:border-neon-blue hover:neon-box-blue'
                )}
              >
                <div className="flex items-start gap-4">
                  <div
                    className={cn(
                      'p-3 rounded-lg',
                      isGreen
                        ? 'bg-neon-green/10 text-neon-green'
                        : 'bg-neon-blue/10 text-neon-blue'
                    )}
                  >
                    <Icon className="w-6 h-6" />
                  </div>
                  <div className="flex-1">
                    <div className="flex items-center justify-between mb-2">
                      <h3
                        className={cn(
                          'font-bruno text-lg transition-all',
                          isGreen
                            ? 'text-neon-green group-hover:neon-glow-green'
                            : 'text-neon-blue group-hover:neon-glow-blue'
                        )}
                      >
                        {project.name}
                      </h3>
                      <ArrowRight
                        className={cn(
                          'w-5 h-5 opacity-0 group-hover:opacity-100 transform translate-x-0 group-hover:translate-x-1 transition-all',
                          isGreen ? 'text-neon-green' : 'text-neon-blue'
                        )}
                      />
                    </div>
                    <p className="text-sm text-muted-foreground leading-relaxed">
                      {project.description}
                    </p>
                  </div>
                </div>
              </Link>
            )
          })}
        </div>
      </motion.div>

      <section aria-label="GitHub repository status" className="mb-6">
        <h2 className="font-bruno text-xl mb-3">Latest 30 public repositories</h2>
        <p className="text-sm text-muted-foreground">Search and filters apply to these recently updated repositories.</p>
        {loading && <p role="status" className="mt-3">Loading repositories… Featured projects above are ready to explore.</p>}
        {error && <div role="status" className="mt-3"><p>{error}</p><button className="underline py-3 text-neon-green" onClick={() => { setLoading(true); setError(null); setAttempt(value => value + 1) }}>Retry repositories</button></div>}
      </section>
      <motion.div
        initial={false}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.1 }}
        className="mb-8 space-y-4"
      >
        <div className="relative w-full md:w-64">
          <label htmlFor="project-search" className="sr-only">Search projects</label>
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
          <input
            type="text"
            id="project-search"
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            placeholder="Search projects..."
            className="w-full bg-transparent border border-neon-green/30 rounded-md pl-10 pr-4 py-2
                       text-foreground placeholder:text-muted-foreground font-mono
                       focus:outline-none focus:border-neon-green focus:shadow-[0_0_10px_rgba(0,255,102,0.3)]
                       transition-all duration-300"
          />
          {searchQuery && (
            <button
              onClick={() => setSearchQuery('')}
              className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-neon-green transition-colors"
              aria-label="Clear search"
            >
              <X className="w-4 h-4" />
            </button>
          )}
        </div>

        <div className="flex flex-wrap gap-2" role="group" aria-label="Filter by programming language">
          <button
            onClick={() => setActiveLanguage(null)}
            aria-pressed={!activeLanguage}
            className={cn(
              'px-3 py-1 rounded-full text-sm font-mono transition-all duration-300',
              !activeLanguage
                ? 'bg-neon-green/20 text-neon-green border border-neon-green shadow-[0_0_10px_rgba(0,255,102,0.2)]'
                : 'border border-border text-muted-foreground hover:border-neon-green/50 hover:text-neon-green'
            )}
          >
            All
          </button>
          {languages.map((lang) => (
            <button
              key={lang}
              onClick={() => setActiveLanguage(lang === activeLanguage ? null : lang)}
              aria-pressed={activeLanguage === lang}
              className={cn(
                'px-3 py-1 rounded-full text-sm font-mono transition-all duration-300',
                activeLanguage === lang
                  ? 'bg-neon-green/20 text-neon-green border border-neon-green shadow-[0_0_10px_rgba(0,255,102,0.2)]'
                  : 'border border-border text-muted-foreground hover:border-neon-green/50 hover:text-neon-green'
              )}
            >
              {lang}
            </button>
          ))}
        </div>
      </motion.div>

      {!loading && !error && <AnimatePresence mode="wait">
        {filteredRepos.length === 0 ? (
          <motion.div
            key="empty"
            initial={false}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -20 }}
            className="flex flex-col items-center justify-center min-h-[40vh] text-center"
          >
            <div aria-hidden="true" className="text-6xl mb-4 font-mono text-neon-green">
              {'{ }'}
            </div>
            <h2 className="text-xl font-bruno text-neon-green mb-2">
              No projects found
            </h2>
            <p className="text-muted-foreground mb-4 max-w-md">
              {searchQuery || activeLanguage ? 'No repositories match your current search' : 'No public repositories are available in this list.'}
              {activeLanguage && ` for "${activeLanguage}"`}
              {searchQuery && ` containing "${searchQuery}"`}
            </p>
            <button
              onClick={clearFilters}
              className="px-4 py-2 rounded-md border border-neon-green/50 text-neon-green font-mono
                         hover:bg-neon-green/10 hover:shadow-[0_0_15px_rgba(0,255,102,0.3)]
                         transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neon-green focus-visible:ring-offset-2 focus-visible:ring-offset-background"
              aria-label="Clear all search and filter selections"
            >
              Clear filters
            </button>
          </motion.div>
        ) : (
          <motion.div
            key="grid"
            initial={false}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"
          >
            {filteredRepos.map((repo, index) => (
              <motion.a
                key={repo.id}
                href={repo.html_url}
                target="_blank"
                rel="noopener noreferrer"
                initial={false}
                animate={{ opacity: 1, y: 0 }}
                transition={{ delay: index * 0.05 }}
                className="group p-5 card-muted hover:border-neon-green/50 hover:bg-card/50 transition-all duration-300"
              >
                <div className="flex items-start justify-between mb-3">
                  <div className="flex items-center gap-2">
                    <h2 className="font-mono text-lg text-foreground group-hover:text-neon-green transition-colors">
                      {repo.name}
                    </h2>
                    {isFeatured(repo) && (
                      <span className="px-2 py-0.5 text-xs rounded bg-neon-green/20 text-neon-green border border-neon-green/50">
                        Featured
                      </span>
                    )}
                  </div>
                  <ExternalLink className="w-4 h-4 text-muted-foreground group-hover:text-neon-green transition-colors flex-shrink-0" />
                </div>

                <p className="text-sm text-muted-foreground mb-4 line-clamp-2">
                  {repo.description || 'No description available'}
                </p>

                <div className="flex items-center gap-4 text-xs text-muted-foreground">
                  {repo.language && (
                    <span className="flex items-center gap-1">
                      <span className="w-2 h-2 rounded-full bg-neon-blue"></span>
                      {repo.language}
                    </span>
                  )}
                  <span className="flex items-center gap-1">
                    <Star className="w-3 h-3" />
                    {repo.stargazers_count}
                  </span>
                  <span className="flex items-center gap-1">
                    <GitFork className="w-3 h-3" />
                    {repo.forks_count}
                  </span>
                </div>

                {repo.topics.length > 0 && (
                  <div className="flex flex-wrap gap-1 mt-3">
                    {repo.topics.slice(0, 3).map((topic) => (
                      <span
                        key={topic}
                        className="px-2 py-0.5 text-xs rounded-full bg-neon-green/10 text-neon-green"
                      >
                        {topic}
                      </span>
                    ))}
                  </div>
                )}
              </motion.a>
            ))}
          </motion.div>
        )}
      </AnimatePresence>}
    </div>
  )
}
