import { ClockIcon } from '@heroicons/react/outline'
import { UsersIcon } from '@heroicons/react/solid'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
import timezone from 'dayjs/plugin/timezone'
import utc from 'dayjs/plugin/utc'
import { zip } from 'lodash'
import Image, { ImageProps, StaticImageData } from 'next/image'
import Link from 'next/link'
import { useState } from 'react'
import { ContractCard } from 'web/components/contract/contract-card'
import { DateTimeTooltip } from 'web/components/datetime-tooltip'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { Page } from 'web/components/page'
import { SEO } from 'web/components/SEO'
import { tournamentContractsByGroupSlugQuery } from 'web/lib/firebase/contracts'
import { getGroup, groupPath } from 'web/lib/firebase/groups'
import elon_pic from './_cspi/Will_Elon_Buy_Twitter.png'
import china_pic from './_cspi/Chinese_Military_Action_against_Taiwan.png'
import mpox_pic from './_cspi/Monkeypox_Cases.png'
import race_pic from './_cspi/Supreme_Court_Ban_Race_in_College_Admissions.png'
import { SiteLink } from 'web/components/site-link'
import { Carousel } from 'web/components/carousel'
import { usePagination } from 'web/hooks/use-pagination'
import { LoadingIndicator } from 'web/components/loading-indicator'
import { Title } from 'web/components/title'

dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(customParseFormat)
const toDate = (d: string) =>
  dayjs(d, 'MMM D, YYYY').tz('America/Los_Angeles').valueOf()

type MarketImage = {
  marketUrl: string
  image: StaticImageData
}

type Tourney = {
  title: string
  blurb: string // actual description in the click-through
  award?: string
  endTime?: number
  groupId: string
}

const Salem = {
  title: 'CSPI/Salem Forecasting Tournament',
  blurb: 'Top 5 traders qualify for a UT Austin research fellowship.',
  url: 'https://salemcenter.manifold.markets/',
  award: 'US$25,000',
  endTime: toDate('Jul 31, 2023'),
  contractIds: [],
  images: [
    {
      marketUrl:
        'https://salemcenter.manifold.markets/SalemCenter/will-elon-musk-buy-twitter',
      image: elon_pic,
    },
    {
      marketUrl:
        'https://salemcenter.manifold.markets/SalemCenter/chinese-military-action-against-tai',
      image: china_pic,
    },
    {
      marketUrl:
        'https://salemcenter.manifold.markets/SalemCenter/over-100000-monkeypox-cases-in-2022',
      image: mpox_pic,
    },
    {
      marketUrl:
        'https://salemcenter.manifold.markets/SalemCenter/supreme-court-ban-race-in-college-a',
      image: race_pic,
    },
  ],
}

const tourneys: Tourney[] = [
  {
    title: 'CCP 20th National Party Congress',
    blurb:
      "Forecast the outcome of the Chinese Communist Party's 20th National Party Congress.",
    award: 'US$200',
    endTime: toDate('Oct 20, 2022'),
    groupId: 'YfcYoy7TWbZtUOs0GLfq',
  },
  {
    title: 'Fantasy Football Stock Exchange',
    blurb: 'How many points will each NFL player score this season?',
    award: 'US$2,500',
    endTime: toDate('Jan 6, 2023'),
    groupId: 'SxGRqXRpV3RAQKudbcNb',
  },
  {
    title: 'Clearer Thinking Regrant Project',
    blurb: 'Which projects will Clearer Thinking give a grant to?',
    award: 'US$13,000',
    endTime: toDate('Sep 30, 2022'),
    groupId: 'fhksfIgqyWf7OxsV9nkM',
  },

  {
    title: 'Cause Exploration Prizes',
    blurb:
      'Which new charity ideas will Open Philanthropy find most promising?',
    award: 'M$100k',
    endTime: toDate('Sep 9, 2022'),
    groupId: 'cMcpBQ2p452jEcJD2SFw',
  },
  {
    title: 'Manifold F2P Tournament',
    blurb:
      'Who can amass the most mana starting from a free-to-play (F2P) account?',
    award: 'Poem',
    endTime: toDate('Sep 15, 2022'),
    groupId: '6rrIja7tVW00lUVwtsYS',
  },

  // Tournaments without awards get featured below
  {
    title: 'Criticism and Red Teaming Contest',
    blurb:
      'Which criticisms of Effective Altruism have been the most valuable?',
    endTime: toDate('Sep 30, 2022'),
    groupId: 'K86LmEmidMKdyCHdHNv4',
  },
  {
    title: 'SF 2022 Ballot',
    blurb: 'Which ballot initiatives will pass this year in SF and CA?',
    endTime: toDate('Nov 8, 2022'),
    groupId: 'VkWZyS5yxs8XWUJrX9eq',
  },

  {
    title: '2024 Democratic Nominees',
    blurb: 'How would different Democratic candidates fare in 2024?',
    endTime: toDate('Nov 2, 2024'),
    groupId: 'gFhjgFVrnYeFYfxhoLNn',
  },
  {
    title: 'Private Tech Companies',
    blurb: 'What will these companies exit for?',
    endTime: toDate('Dec 31, 2030'),
    groupId: 'faNUnphw6Eoq7OJBRJds',
  },
]

type SectionInfo = {
  tourney: Tourney
  slug: string
  numPeople: number
}

export async function getStaticProps() {
  const groupIds = tourneys.map((data) => data.groupId)
  const groups = await Promise.all(groupIds.map(getGroup))
  const sections = zip(tourneys, groups)
    .filter(([_tourney, group]) => group != null)
    .map(([tourney, group]) => ({
      tourney,
      slug: group!.slug, // eslint-disable-line
      numPeople: group!.totalMembers, // eslint-disable-line
    }))
  return { props: { sections } }
}

export default function TournamentPage(props: { sections: SectionInfo[] }) {
  const { sections } = props

  const description = `Win real prizes (including cash!) by participating in forecasting
            tournaments on current events, sports, science, and more.`
  return (
    <Page>
      <SEO title="Tournaments" description={description} />
      <Col className="m-4 gap-10 sm:mx-10 sm:gap-24 xl:w-[125%]">
        <Col>
          <Title text="🏆 Manifold tournaments" />
          <div>{description}</div>
        </Col>

        {sections.map(
          ({ tourney, slug, numPeople }) =>
            tourney.award &&
            (tourney.endTime ?? 0) > Date.now() && (
              <div key={slug}>
                <SectionHeader
                  url={groupPath(slug, 'about')}
                  title={tourney.title}
                  ppl={numPeople}
                  award={tourney.award}
                  endTime={tourney.endTime}
                />
                <span className="text-gray-500">{tourney.blurb}</span>
                <MarketCarousel slug={slug} />
              </div>
            )
        )}
        {/* Salem center */}
        <div>
          <SectionHeader
            url={Salem.url}
            title={Salem.title}
            award={Salem.award}
            endTime={Salem.endTime}
          />
          <span className="text-gray-500">{Salem.blurb}</span>
          <ImageCarousel url={Salem.url} images={Salem.images} />
        </div>

        {/* Title break */}
        <div className="relative">
          <div
            className="absolute inset-0 flex items-center"
            aria-hidden="true"
          >
            <div className="w-full border-t border-gray-300" />
          </div>
          <div className="relative flex justify-center">
            <span className="bg-gray-50 px-3 text-lg font-medium text-gray-900">
              Past tournaments
            </span>
          </div>
        </div>

        {sections.map(
          ({ tourney, slug, numPeople }) =>
            tourney.award &&
            (tourney.endTime ?? 0) <= Date.now() && (
              <div key={slug}>
                <SectionHeader
                  url={groupPath(slug, 'about')}
                  title={tourney.title}
                  ppl={numPeople}
                  award={tourney.award}
                  endTime={tourney.endTime}
                />
                <span className="text-gray-500">{tourney.blurb}</span>
                <MarketCarousel slug={slug} />
              </div>
            )
        )}

        {/* Title break */}
        <div className="relative">
          <div
            className="absolute inset-0 flex items-center"
            aria-hidden="true"
          >
            <div className="w-full border-t border-gray-300" />
          </div>
          <div className="relative flex justify-center">
            <span className="bg-gray-50 px-3 text-lg font-medium text-gray-900">
              Featured Groups
            </span>
          </div>
        </div>

        {sections.map(
          ({ tourney, slug, numPeople }) =>
            !tourney.award && (
              <div key={slug}>
                <SectionHeader
                  url={groupPath(slug, 'about')}
                  title={tourney.title}
                  ppl={numPeople}
                  award={tourney.award}
                  endTime={tourney.endTime}
                />
                <span className="text-gray-500">{tourney.blurb}</span>
                <MarketCarousel slug={slug} />
              </div>
            )
        )}

        <p className="pb-10 italic text-gray-500">
          We'd love to sponsor more tournaments and groups. Have an idea? Ping{' '}
          <SiteLink
            className="font-semibold"
            href="https://discord.com/invite/eHQBNBqXuh"
          >
            Austin on Discord
          </SiteLink>
          !
        </p>
      </Col>
    </Page>
  )
}

const SectionHeader = (props: {
  url: string
  title: string
  ppl?: number
  award?: string
  endTime?: number
}) => {
  const { url, title, ppl, award, endTime } = props
  return (
    <Link href={url}>
      <a className="group mb-3 flex flex-wrap justify-between">
        <h2 className="text-xl group-hover:underline md:text-3xl">{title}</h2>
        <Row className="my-2 items-center gap-4 whitespace-nowrap rounded-full bg-gray-200 px-6">
          {!!award && <span className="flex items-center">🏆 {award}</span>}
          {!!ppl && (
            <span className="flex items-center gap-1">
              <UsersIcon className="h-4" />
              {ppl}
            </span>
          )}
          {endTime && (
            <DateTimeTooltip time={endTime} text="Ends">
              <span className="flex items-center gap-1">
                <ClockIcon className="h-4" />
                {dayjs(endTime).format('MMM D')}
              </span>
            </DateTimeTooltip>
          )}
        </Row>
      </a>
    </Link>
  )
}

const ImageCarousel = (props: { images: MarketImage[]; url: string }) => {
  const { images, url } = props
  return (
    <Carousel className="-mx-4 mt-4 sm:-mx-10">
      <div className="shrink-0 sm:w-6" />
      {images.map(({ marketUrl, image }) => (
        <a key={marketUrl} href={marketUrl} className="hover:brightness-95">
          <NaturalImage src={image} />
        </a>
      ))}
      <SiteLink
        className="ml-6 mr-10 flex shrink-0 items-center text-indigo-700"
        href={url}
      >
        See more
      </SiteLink>
    </Carousel>
  )
}

const MarketCarousel = (props: { slug: string }) => {
  const { slug } = props
  const q = tournamentContractsByGroupSlugQuery(slug)
  const { allItems, getNext } = usePagination({ q, pageSize: 6 })
  const items = allItems()

  // todo: would be nice to have indicator somewhere when it loads next page
  return items.length === 0 ? (
    <LoadingIndicator className="mt-10" />
  ) : (
    <Carousel className="-mx-4 mt-4 sm:-mx-10" loadMore={getNext}>
      <div className="shrink-0 sm:w-6" />
      {items.map((m) => (
        <ContractCard
          key={m.id}
          contract={m}
          hideGroupLink
          className="mb-2 max-h-[200px] w-96 shrink-0 snap-start scroll-m-4 md:snap-align-none"
          questionClass="line-clamp-3"
          trackingPostfix=" tournament"
        />
      ))}
    </Carousel>
  )
}

// stole: https://stackoverflow.com/questions/66845889/next-js-image-how-to-maintain-aspect-ratio-and-add-letterboxes-when-needed
const NaturalImage = (props: ImageProps) => {
  const [ratio, setRatio] = useState(4 / 1)

  return (
    <Image
      {...props}
      width={148 * ratio}
      height={148}
      layout="fixed"
      onLoadingComplete={({ naturalWidth, naturalHeight }) =>
        setRatio(naturalWidth / naturalHeight)
      }
    />
  )
}