import React, { useEffect, useMemo, useState } from 'react'
import {
  CategoryScale,
  Chart,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from 'chart.js'
import { ChartData } from 'chart.js'
import { Line } from 'react-chartjs-2'
import { bids as sampleBids } from '../../lib/simulator/sample-bids'
import { Entry, makeEntries } from '../../lib/simulator/entries'
import { Header } from '../../components/header'

// Auto import doesn't work for some reason...
// So we manually register ChartJS components instead:
Chart.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
)

function TableBody(props: { entries: Entry[] }) {
  return (
    <tbody>
      {props.entries.map((entry, i) => (
        <tr key={i}>
          <th>{i + 1}</th>
          <TableRowStart entry={entry} />
          <TableRowEnd entry={entry} />
        </tr>
      ))}
    </tbody>
  )
}

function TableRowStart(props: { entry: Entry }) {
  const { entry } = props
  if (entry.yesBid && entry.noBid) {
    return (
      <>
        <td>
          <div className="badge">SEED</div>
        </td>
        <td>
          {entry.yesBid} / {entry.noBid}
        </td>
      </>
    )
  } else if (entry.yesBid) {
    return (
      <>
        <td>
          <div className="badge badge-success">YES</div>
        </td>
        <td>{entry.yesBid}</td>
      </>
    )
  } else {
    return (
      <>
        <td>
          <div className="badge badge-error">NO</div>
        </td>
        <td>{entry.noBid}</td>
      </>
    )
  }
}

function TableRowEnd(props: { entry: Entry | null }) {
  const { entry } = props
  if (!entry) {
    return (
      <>
        <td>N/A</td>
        <td>N/A</td>
        <td>N/A</td>
        <td>N/A</td>
      </>
    )
  } else if (entry.yesBid && entry.noBid) {
    return (
      <>
        <td>N/A</td>
        <td>{entry.prob.toFixed(2)}</td>
        <td>N/A</td>
        <td>N/A</td>
      </>
    )
  } else if (entry.yesBid) {
    return (
      <>
        <td>{entry.yesWeight.toFixed(2)}</td>
        <td>{entry.prob.toFixed(2)}</td>
        <td>{entry.yesPayout.toFixed(2)}</td>
        <td>{(entry.yesReturn * 100).toFixed(2)}%</td>
      </>
    )
  } else {
    return (
      <>
        <td>{entry.noWeight.toFixed(2)}</td>
        <td>{entry.prob.toFixed(2)}</td>
        <td>{entry.noPayout.toFixed(2)}</td>
        <td>{(entry.noReturn * 100).toFixed(2)}%</td>
      </>
    )
  }
}

function NewBidTable(props: {
  steps: number
  bids: any[]
  setSteps: (steps: number) => void
  setBids: (bids: any[]) => void
}) {
  const { steps, bids, setSteps, setBids } = props
  // Prepare for new bids
  const [newBid, setNewBid] = useState(0)
  const [newBidType, setNewBidType] = useState('YES')

  function makeBid(type: string, bid: number) {
    return {
      yesBid: type == 'YES' ? bid : 0,
      noBid: type == 'YES' ? 0 : bid,
    }
  }

  function submitBid() {
    if (newBid <= 0) return
    const bid = makeBid(newBidType, newBid)
    bids.splice(steps, 0, bid)
    setBids(bids)
    setSteps(steps + 1)
    setNewBid(0)
  }

  function toggleBidType() {
    setNewBidType(newBidType === 'YES' ? 'NO' : 'YES')
  }

  const nextEntry = useMemo(() => {
    if (newBid) {
      const nextBid = makeBid(newBidType, newBid)
      const fakeBids = [...bids.slice(0, steps), nextBid]
      const entries = makeEntries(fakeBids)
      return entries[entries.length - 1]
    }
    return null
  }, [newBid, newBidType, steps])

  return (
    <table className="table table-compact my-8 w-full text-center">
      <thead>
        <tr>
          <th>Order #</th>
          <th>Type</th>
          <th>Bid</th>
          <th>Weight</th>
          <th>Prob</th>
          <th>Payout</th>
          <th>Return</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th>{steps + 1}</th>
          <td>
            <div
              className={
                `badge hover:cursor-pointer ` +
                (newBidType == 'YES' ? 'badge-success' : 'badge-ghost')
              }
              onClick={toggleBidType}
            >
              YES
            </div>
            <br />
            <div
              className={
                `badge hover:cursor-pointer ` +
                (newBidType == 'NO' ? 'badge-error' : 'badge-ghost')
              }
              onClick={toggleBidType}
            >
              NO
            </div>
          </td>
          <td>
            <input
              type="number"
              placeholder="0"
              className="input input-bordered"
              style={{ maxWidth: 100 }}
              value={newBid}
              onChange={(e) => setNewBid(parseInt(e.target.value) || 0)}
              onKeyUp={(e) => {
                if (e.key === 'Enter') {
                  submitBid()
                }
              }}
              onFocus={(e) => e.target.select()}
            />
          </td>
          <TableRowEnd entry={nextEntry} />
          <td>
            <button
              className="btn btn-primary"
              onClick={() => submitBid()}
              disabled={newBid <= 0}
            >
              Submit
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  )
}

// Show a hello world React page
export default function Simulator() {
  const [steps, setSteps] = useState(10)
  const [bids, setBids] = useState(sampleBids)

  const entries = useMemo(
    () => makeEntries(bids.slice(0, steps)),
    [bids, steps]
  )
  const probs = entries.map((entry) => entry.prob)

  // Set up chart
  const [chartData, setChartData] = useState({ datasets: [] } as ChartData)

  useEffect(() => {
    setChartData({
      labels: Array.from({ length: steps }, (_, i) => i + 1),
      datasets: [
        {
          label: 'Implied probability',
          data: probs,
          borderColor: 'rgb(75, 192, 192)',
        },
      ],
    })
  }, [steps])

  return (
    <div className="relative overflow-hidden h-screen bg-gray-900">
      <Header />
      <div className="grid grid-cols-1 xl:grid-cols-2 gap-4 mt-8 max-w-7xl mx-auto text-center">
        {/* Left column */}
        <div>
          <h1 className="text-2xl font-bold mb-8">
            Dynamic Parimutuel Market Simulator
          </h1>
          {/* Range slider that sets the current step */}
          <label>Simulation step: {steps}</label>
          <input
            type="range"
            className="range"
            min="1"
            max={bids.length}
            value={steps}
            onChange={(e) => setSteps(parseInt(e.target.value))}
          />

          <NewBidTable {...{ steps, bids, setSteps, setBids }} />

          {/* History of bids */}
          <div className="overflow-x-auto">
            <table className="table w-full text-center">
              <thead>
                <tr>
                  <th>Order #</th>
                  <th>Type</th>
                  <th>Bid</th>
                  <th>Weight</th>
                  <th>Prob</th>
                  <th>Max Payout</th>
                  <th>Return</th>
                </tr>
              </thead>

              <TableBody entries={entries} />
            </table>
          </div>
        </div>

        {/* Right column */}
        <div>
          <h1 className="text-2xl font-bold mb-8">
            Probability of
            <div className="badge badge-success text-2xl h-8 w-18">YES</div>
          </h1>
          <Line data={chartData as any} height={200} />
        </div>
      </div>
    </div>
  )
}
