import { useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import {
  getCourtAssignments,
  getReceivingPlayer,
  getServiceCourt,
  getServingPlayer,
  getTeamDisplayName,
} from '../lib/match'
import type {
  CourtSide,
  GroupTeam,
  Matchup,
  PlayerSlot,
  RoundGroup,
  ScoreSide,
  ScoreState,
} from '../types'

type ScoreboardPageProps = {
  finishDialogError: string
  finishDialogOpen: boolean
  finishDialogUploading: boolean
  groupSource: 'idle' | 'db' | 'manual'
  hasRecordedPoint: boolean
  leftTeam: GroupTeam | null
  matchup: Matchup
  rightTeam: GroupTeam | null
  scoreState: ScoreState
  selectedGroup: RoundGroup | null
  targetDate: string
  onApplyMatchup: (leftTeamId: number, rightTeamId: number) => void
  onCloseFinishDialog: () => void
  onConfirmUpload: () => void
  onOpenFinishDialog: () => void
  onRecordPoint: (side: ScoreSide) => void
  onSetServing: (side: ScoreSide) => void
  onSkipUpload: () => void
  onSwapMatchup: () => void
  onSwapTeamPlayers: (side: ScoreSide) => void
  onUndoLastPoint: () => void
}

export function ScoreboardPage({
  finishDialogError,
  finishDialogOpen,
  finishDialogUploading,
  groupSource,
  hasRecordedPoint,
  leftTeam,
  matchup,
  rightTeam,
  scoreState,
  selectedGroup,
  targetDate,
  onApplyMatchup,
  onCloseFinishDialog,
  onConfirmUpload,
  onOpenFinishDialog,
  onRecordPoint,
  onSetServing,
  onSkipUpload,
  onSwapMatchup,
  onSwapTeamPlayers,
  onUndoLastPoint,
}: ScoreboardPageProps) {
  const [pickerOpen, setPickerOpen] = useState(false)
  const [draftTeamIds, setDraftTeamIds] = useState<number[]>([])
  const [clock, setClock] = useState(() => formatClock())

  useEffect(() => {
    const timer = window.setInterval(() => {
      setClock(formatClock())
    }, 1000)

    return () => window.clearInterval(timer)
  }, [])

  const canArrangeMatch = !hasRecordedPoint
  const canScore = scoreState.serving !== null

  const servingScore =
    scoreState.serving === 'left' ? scoreState.scoreLeft : scoreState.scoreRight
  const servingCourt =
    scoreState.serving === null ? null : getServiceCourt(servingScore)

  const leftAssignments = useMemo(
    () =>
      leftTeam ? getCourtAssignments(leftTeam, scoreState.leftRightCourtPlayer) : [],
    [leftTeam, scoreState.leftRightCourtPlayer],
  )
  const rightAssignments = useMemo(
    () =>
      rightTeam ? getCourtAssignments(rightTeam, scoreState.rightRightCourtPlayer) : [],
    [rightTeam, scoreState.rightRightCourtPlayer],
  )

  const currentServer =
    scoreState.serving === 'left'
      ? leftTeam
        ? getServingPlayer(leftTeam, scoreState.leftRightCourtPlayer, scoreState.scoreLeft)
        : null
      : scoreState.serving === 'right'
        ? rightTeam
          ? getServingPlayer(
              rightTeam,
              scoreState.rightRightCourtPlayer,
              scoreState.scoreRight,
            )
          : null
        : null

  const currentReceiver =
    scoreState.serving === 'left'
      ? rightTeam
        ? getReceivingPlayer(
            rightTeam,
            scoreState.rightRightCourtPlayer,
            scoreState.scoreLeft,
          )
        : null
      : scoreState.serving === 'right'
        ? leftTeam
          ? getReceivingPlayer(
              leftTeam,
              scoreState.leftRightCourtPlayer,
              scoreState.scoreRight,
            )
          : null
        : null

  if (!selectedGroup) {
    return (
      <section className="page-grid">
        <article className="panel panel-hero">
          <p className="panel-kicker">Step 3</p>
          <h2>先到選隊伍頁面建立對戰組合</h2>
          <p className="panel-copy">
            目前還沒有可用的組別。先載入指定日期資料，或手動建立分組後，再回來開始記分。
          </p>
          <Link className="primary-button inline-link" to="/teams">
            前往選隊伍
          </Link>
        </article>
      </section>
    )
  }

  const matchupLabel =
    leftTeam && rightTeam
      ? `${getTeamDisplayName(leftTeam)} vs ${getTeamDisplayName(rightTeam)}`
      : '尚未設定對戰隊伍'

  const openPicker = () => {
    const next = [matchup.leftTeamId, matchup.rightTeamId].filter(
      (value): value is number => value !== null,
    )

    setDraftTeamIds(next)
    setPickerOpen(true)
  }

  const toggleDraftTeam = (teamId: number) => {
    setDraftTeamIds((current) => {
      if (current.includes(teamId)) {
        return current.filter((value) => value !== teamId)
      }

      if (current.length >= 2) {
        return [current[1], teamId]
      }

      return [...current, teamId]
    })
  }

  const confirmDraftTeams = () => {
    if (draftTeamIds.length !== 2) {
      return
    }

    onApplyMatchup(draftTeamIds[0], draftTeamIds[1])
    setPickerOpen(false)
  }

  const autoPickDraftTeams = () => {
    const shuffled = [...selectedGroup.teams]

    for (let index = shuffled.length - 1; index > 0; index -= 1) {
      const swapIndex = Math.floor(Math.random() * (index + 1))
      ;[shuffled[index], shuffled[swapIndex]] = [shuffled[swapIndex], shuffled[index]]
    }

    setDraftTeamIds(shuffled.slice(0, 2).map((team) => team.id))
  }

  return (
    <>
      <section className="scoreboard-screen">
        <div className="scoreboard-court">
          <ScoreboardTeamPanel
            assignments={leftAssignments}
            canArrangeMatch={canArrangeMatch}
            canScore={canScore}
            currentReceiver={scoreState.serving === 'right' ? currentReceiver?.name ?? null : null}
            currentServer={scoreState.serving === 'left' ? currentServer?.name ?? null : null}
            onRecordPoint={() => onRecordPoint('left')}
            onSetServing={() => onSetServing('left')}
            onSwapPlayers={() => onSwapTeamPlayers('left')}
            onSwapTeams={onSwapMatchup}
            score={scoreState.scoreLeft}
            serviceCourt={scoreState.serving === 'left' ? servingCourt : null}
            team={leftTeam}
            teamSlot="top"
          />

          <div className="scoreboard-center-banner">
            <p>{scoreState.serving === null ? '請設定發球方' : '點擊分數開始計分'}</p>
            <small>
              {scoreState.serving === null
                ? '先在上方或下方按下先攻'
                : `目前發球：${currentServer?.name ?? '-'}${
                    currentReceiver ? ` / 接發：${currentReceiver.name}` : ''
                  }`}
            </small>
          </div>

          <ScoreboardTeamPanel
            assignments={rightAssignments}
            canArrangeMatch={canArrangeMatch}
            canScore={canScore}
            currentReceiver={scoreState.serving === 'left' ? currentReceiver?.name ?? null : null}
            currentServer={scoreState.serving === 'right' ? currentServer?.name ?? null : null}
            onRecordPoint={() => onRecordPoint('right')}
            onSetServing={() => onSetServing('right')}
            onSwapPlayers={() => onSwapTeamPlayers('right')}
            onSwapTeams={onSwapMatchup}
            score={scoreState.scoreRight}
            serviceCourt={scoreState.serving === 'right' ? servingCourt : null}
            team={rightTeam}
            teamSlot="bottom"
          />
        </div>

        <aside className="scoreboard-rail">
          <div className="rail-icon-grid">
            {hasRecordedPoint ? (
              <button className="rail-square-button" type="button" onClick={onUndoLastPoint}>
                上一步
              </button>
            ) : (
              <button className="rail-square-button" type="button" onClick={openPicker}>
                設定隊伍
              </button>
            )}
          </div>

          <div className="rail-clock">{clock}</div>

          <button className="rail-pill rail-pill-danger" type="button" onClick={onOpenFinishDialog}>
            比賽結算
          </button>
        </aside>
      </section>

      {pickerOpen ? (
        <TeamPickerModal
          currentLeftTeamId={matchup.leftTeamId}
          currentRightTeamId={matchup.rightTeamId}
          draftTeamIds={draftTeamIds}
          group={selectedGroup}
          selectionCount={draftTeamIds.length}
          sourceLabel={groupSource === 'db' ? 'DB' : groupSource === 'manual' ? '手動' : '-'}
          targetDate={targetDate}
          onAutoPick={autoPickDraftTeams}
          onClear={() => setDraftTeamIds([])}
          onClose={() => setPickerOpen(false)}
          onConfirm={confirmDraftTeams}
          onToggleTeam={toggleDraftTeam}
        />
      ) : null}

      {finishDialogOpen ? (
        <FinishDialog
          error={finishDialogError}
          leftScore={scoreState.scoreLeft}
          leftTeamName={leftTeam ? getTeamDisplayName(leftTeam) : '未設定'}
          matchupLabel={matchupLabel}
          rightScore={scoreState.scoreRight}
          rightTeamName={rightTeam ? getTeamDisplayName(rightTeam) : '未設定'}
          uploading={finishDialogUploading}
          onClose={onCloseFinishDialog}
          onConfirm={onConfirmUpload}
          onSkip={onSkipUpload}
        />
      ) : null}
    </>
  )
}

type ScoreboardTeamPanelProps = {
  assignments: Array<{ slot: PlayerSlot; name: string; court: CourtSide }>
  canArrangeMatch: boolean
  canScore: boolean
  currentReceiver: string | null
  currentServer: string | null
  onRecordPoint: () => void
  onSetServing: () => void
  onSwapPlayers: () => void
  onSwapTeams: () => void
  score: number
  serviceCourt: CourtSide | null
  team: GroupTeam | null
  teamSlot: 'top' | 'bottom'
}

function ScoreboardTeamPanel({
  assignments,
  canArrangeMatch,
  canScore,
  currentReceiver,
  currentServer,
  onRecordPoint,
  onSetServing,
  onSwapPlayers,
  onSwapTeams,
  score,
  serviceCourt,
  team,
  teamSlot,
}: ScoreboardTeamPanelProps) {
  const orderedAssignments = [...assignments].sort((left, right) => {
    if (left.court === right.court) {
      return 0
    }

    return left.court === 'left' ? -1 : 1
  })

  const header = (
    <div className="scoreboard-team-head">
      <div className="team-head-main">
        {orderedAssignments.map((assignment) => (
          <div
            className={
              assignment.name === currentServer
                ? 'scoreboard-name-chip scoreboard-name-chip-serving'
                : 'scoreboard-name-chip'
            }
            key={assignment.slot}
          >
            <span className="team-number">{getPlayerNumber(teamSlot, assignment.slot)}</span>
            <strong>{assignment.name}</strong>
          </div>
        ))}
      </div>

      <div className="team-head-buttons">
        <button
          aria-label="上下交換隊伍"
          className="team-icon-button"
          disabled={!canArrangeMatch}
          type="button"
          onClick={onSwapTeams}
        >
          ↕
        </button>
        <button
          aria-label="左右交換隊員"
          className="team-icon-button"
          disabled={!canArrangeMatch}
          type="button"
          onClick={onSwapPlayers}
        >
          ↔
        </button>
      </div>
    </div>
  )

  const serveBar = (
    <button
      className={
        currentServer && !canArrangeMatch ? 'serve-lane serve-lane-locked' : 'serve-lane'
      }
      disabled={!canArrangeMatch || !team}
      type="button"
      onClick={onSetServing}
    >
      <span className="serve-lane-box" />
      <span>先攻</span>
      {currentServer ? (
        <small>
          發球位 {serviceCourt === 'left' ? '左' : serviceCourt === 'right' ? '右' : '-'}
          {currentReceiver ? ` / 接發 ${currentReceiver}` : ''}
        </small>
      ) : (
        <small>選擇這一隊先攻</small>
      )}
    </button>
  )

  const scoreBoard = (
    <button
      className={canScore ? 'score-panel-surface score-panel-surface-live' : 'score-panel-surface'}
      disabled={!canScore || !team}
      type="button"
      onClick={onRecordPoint}
    >
      <span className="score-panel-value">{score}</span>
    </button>
  )

  return (
    <section className="scoreboard-team-section">
      {teamSlot === 'top' ? (
        <>
          {header}
          {serveBar}
          {scoreBoard}
        </>
      ) : (
        <>
          {scoreBoard}
          {serveBar}
          {header}
        </>
      )}
    </section>
  )
}

type TeamPickerModalProps = {
  currentLeftTeamId: number | null
  currentRightTeamId: number | null
  draftTeamIds: number[]
  group: RoundGroup
  selectionCount: number
  sourceLabel: string
  targetDate: string
  onAutoPick: () => void
  onClear: () => void
  onClose: () => void
  onConfirm: () => void
  onToggleTeam: (teamId: number) => void
}

function TeamPickerModal({
  currentLeftTeamId,
  currentRightTeamId,
  draftTeamIds,
  group,
  selectionCount,
  sourceLabel,
  targetDate,
  onAutoPick,
  onClear,
  onClose,
  onConfirm,
  onToggleTeam,
}: TeamPickerModalProps) {
  return (
    <div className="team-picker-overlay" role="presentation" onClick={onClose}>
      <div
        aria-label="設定對戰隊伍"
        aria-modal="true"
        className="team-picker-shell"
        onClick={(event) => event.stopPropagation()}
        role="dialog"
      >
        <button aria-label="關閉選隊視窗" className="team-picker-close" type="button" onClick={onClose}>
          ×
        </button>

        <div className="team-picker-ribbon">
          <span>{selectionCount >= 2 ? '已完成選擇' : '請選擇 2 隊'}</span>
        </div>

        <div className="team-picker-layout">
          <section className="team-picker-panel team-picker-list-panel">
            <div className="team-picker-title">
              <span className="team-picker-count">{selectionCount}/2</span>
              <div>
                <strong>從這一組挑選要對打的隊伍</strong>
                <p>
                  第 {group.id} 組 / {sourceLabel} / {targetDate || '-'}
                </p>
              </div>
            </div>

            <div className="team-picker-list">
              {group.teams.map((team) => {
                const checked = draftTeamIds.includes(team.id)
                const selectedOrder = checked ? draftTeamIds.indexOf(team.id) + 1 : null

                return (
                  <button
                    className={
                      checked
                        ? 'team-picker-option team-picker-option-active'
                        : 'team-picker-option'
                    }
                    key={`team-option-${team.id}`}
                    type="button"
                    onClick={() => onToggleTeam(team.id)}
                  >
                    <span className="team-picker-checkbox">
                      {checked ? String(selectedOrder) : ''}
                    </span>
                    <div className="team-picker-option-text">
                      <strong>{getTeamDisplayName(team)}</strong>
                      <small>隊伍編號 {team.id}</small>
                    </div>
                  </button>
                )
              })}
            </div>

            <div className="team-picker-actions">
              <button className="team-picker-ghost" type="button" onClick={onAutoPick}>
                自動選擇
              </button>
              <button
                className="team-picker-confirm"
                disabled={draftTeamIds.length !== 2}
                type="button"
                onClick={onConfirm}
              >
                確認
              </button>
            </div>
          </section>

          <aside className="team-picker-panel team-picker-side-panel">
            <div className="picked-team-list">
              {[0, 1].map((slotIndex) => {
                const teamId = draftTeamIds[slotIndex] ?? null
                const team = group.teams.find((item) => item.id === teamId) ?? null
                const isCurrent =
                  teamId !== null &&
                  teamId === (slotIndex === 0 ? currentLeftTeamId : currentRightTeamId)

                return (
                  <div className="picked-team-card" key={`picked-${slotIndex}`}>
                    <span className="picked-team-index">{slotIndex + 1}</span>
                    <div>
                      <strong>{team ? getTeamDisplayName(team) : '尚未選擇'}</strong>
                      <small>
                        {slotIndex === 0 ? '上方隊伍' : '下方隊伍'}
                        {isCurrent ? ' / 目前使用中' : ''}
                      </small>
                    </div>
                  </div>
                )
              })}
            </div>

            <label className="picker-mode-toggle">
              <input disabled type="checkbox" />
              <span>單打模式</span>
            </label>

            <button className="team-picker-clear" type="button" onClick={onClear}>
              清空
            </button>

            <p className="picker-side-hint">
              選好 2 隊後按確認，會直接帶入記分板的上方與下方位置。
            </p>
          </aside>
        </div>
      </div>
    </div>
  )
}

type FinishDialogProps = {
  error: string
  leftScore: number
  leftTeamName: string
  matchupLabel: string
  rightScore: number
  rightTeamName: string
  uploading: boolean
  onClose: () => void
  onConfirm: () => void
  onSkip: () => void
}

function FinishDialog({
  error,
  leftScore,
  leftTeamName,
  matchupLabel,
  rightScore,
  rightTeamName,
  uploading,
  onClose,
  onConfirm,
  onSkip,
}: FinishDialogProps) {
  return (
    <div className="finish-dialog-overlay" role="presentation">
      <div aria-modal="true" className="finish-dialog" role="dialog">
        <button
          aria-label="關閉結算視窗"
          className="finish-dialog-close"
          disabled={uploading}
          type="button"
          onClick={onClose}
        >
          ×
        </button>

        <p className="panel-kicker">比賽結算</p>
        <h3>{matchupLabel}</h3>

        <div className="finish-score">
          <div>
            <strong>{leftScore}</strong>
            <span>{leftTeamName}</span>
          </div>
          <div className="finish-score-divider">:</div>
          <div>
            <strong>{rightScore}</strong>
            <span>{rightTeamName}</span>
          </div>
        </div>

        <p className="finish-dialog-copy">要把這場戰績上傳到 DB 嗎？</p>

        {error ? <p className="finish-dialog-error">{error}</p> : null}

        <div className="finish-dialog-actions">
          <button
            className="team-picker-ghost"
            disabled={uploading}
            type="button"
            onClick={onSkip}
          >
            不上傳
          </button>
          <button
            className="team-picker-confirm"
            disabled={uploading}
            type="button"
            onClick={onConfirm}
          >
            {uploading ? '上傳中...' : '上傳戰績'}
          </button>
        </div>
      </div>
    </div>
  )
}

function getPlayerNumber(teamSlot: 'top' | 'bottom', slot: PlayerSlot) {
  if (teamSlot === 'top') {
    return slot === 'playerA' ? 1 : 2
  }

  return slot === 'playerA' ? 4 : 3
}

function formatClock() {
  return new Date().toLocaleTimeString('zh-TW', {
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  })
}
