import { useParams } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import ReactMarkdown from 'react-markdown';
import { VerticalTimeline } from 'react-vertical-timeline-component';

import { fetchEvents, fetchReadme, fetchLanguages, fetchProjects, type Source } from '../api/client';
import { TimelineEntry } from '../components/TimelineEntry';

export function ProjectPage() {
  const { source, '*': repoPath } = useParams();
  const repo = repoPath ?? '';

  const projectsQ = useQuery({
    queryKey: ['projects'],
    queryFn: fetchProjects,
    staleTime: 60_000,
  });
  const project = projectsQ.data?.find(
    (p) => p.source === source && p.repo === repo,
  );
  const host = project?.host ?? '';

  const eventsQ = useQuery({
    queryKey: ['project-events', source, repo],
    queryFn: () =>
      fetchEvents({
        sources: source ? [source as Source] : undefined,
        repo,
        limit: 500,
      }),
    refetchInterval: 60_000,
  });

  const readmeQ = useQuery({
    queryKey: ['readme', source, host, repo],
    queryFn: () => fetchReadme(source as Source, host, repo),
    enabled: !!host && (source === 'github' || source === 'gitea'),
    staleTime: 5 * 60_000,
  });

  const langsQ = useQuery({
    queryKey: ['languages', source, host, repo],
    queryFn: () => fetchLanguages(source as Source, host, repo),
    enabled: !!host && (source === 'github' || source === 'gitea'),
    staleTime: 5 * 60_000,
  });

  const events = eventsQ.data ?? [];
  const langs = langsQ.data;

  return (
    <>
      <Row className="mb-3">
        <Col>
          <h2>{repo}</h2>
          <small className="text-muted">{source}</small>
          {langs && <LanguageBar languages={langs} />}
        </Col>
      </Row>

      {readmeQ.data && (
        <Row className="mb-4">
          <Col>
            <div className="project-readme">
              <ReactMarkdown>{readmeQ.data}</ReactMarkdown>
            </div>
          </Col>
        </Row>
      )}

      <Row>
        <Col>
          <p style={{ fontSize: '85%' }}>
            {eventsQ.isLoading
              ? 'loading...'
              : eventsQ.isError
                ? `error: ${(eventsQ.error as Error).message}`
                : `${events.length} ${events.length === 1 ? 'activity' : 'activities'}`}
          </p>
          <VerticalTimeline>
            {events.map((item) => (
              <TimelineEntry key={item.id} item={item} />
            ))}
          </VerticalTimeline>
        </Col>
      </Row>
    </>
  );
}

function LanguageBar({ languages }: { languages: Record<string, number> }) {
  const total = Object.values(languages).reduce((a, b) => a + b, 0);
  if (total === 0) return null;

  const sorted = Object.entries(languages).sort(([, a], [, b]) => b - a);

  return (
    <div className="mt-2">
      <div className="language-bar">
        {sorted.map(([lang, bytes]) => (
          <div
            key={lang}
            className="language-bar-segment"
            style={{ width: `${(bytes / total) * 100}%`, backgroundColor: langColor(lang) }}
            title={`${lang} ${((bytes / total) * 100).toFixed(1)}%`}
          />
        ))}
      </div>
      <div className="d-flex flex-wrap gap-2 mt-1" style={{ fontSize: '0.75rem' }}>
        {sorted.slice(0, 8).map(([lang, bytes]) => (
          <span key={lang}>
            <span className="language-dot" style={{ backgroundColor: langColor(lang) }} />
            {lang} {((bytes / total) * 100).toFixed(1)}%
          </span>
        ))}
      </div>
    </div>
  );
}

const LANG_COLORS: Record<string, string> = {
  Rust: '#dea584',
  TypeScript: '#3178c6',
  JavaScript: '#f1e05a',
  Python: '#3572a5',
  Go: '#00add8',
  Shell: '#89e051',
  HTML: '#e34c26',
  CSS: '#563d7c',
  C: '#555555',
  'C++': '#f34b7d',
  Java: '#b07219',
  Ruby: '#701516',
  Nix: '#7e7eff',
  Makefile: '#427819',
  Dockerfile: '#384d54',
  SCSS: '#c6538c',
};

function langColor(lang: string): string {
  return LANG_COLORS[lang] ?? '#8b8b8b';
}
