import { useEffect, useRef } from 'react'
import * as api from '../api'

const PRESETS = [
  { id: 'glyph', name: 'Glyph', desc: '5x5', tag: 'VERY EASY' },
  { id: 'rune', name: 'Rune', desc: '5x5', tag: 'EASY' },
  { id: 'scroll', name: 'Scroll', desc: '9x9', tag: 'MEDIUM' },
  { id: 'codex', name: 'Codex', desc: '15x15', tag: 'HARD' },
  { id: 'grimoire', name: 'Grimoire', desc: '21x21', tag: 'EXPERT' },
]

const W = 2560
const H = 1440

interface GridData {
  width: number
  height: number
  cells: string[][]
}

function renderGrid(ctx: CanvasRenderingContext2D, grid: GridData, x: number, y: number, maxW: number, maxH: number) {
  const cellSize = Math.min(maxW / grid.width, maxH / grid.height)
  const gridW = cellSize * grid.width
  const gridH = cellSize * grid.height
  const ox = x + (maxW - gridW) / 2
  const oy = y + (maxH - gridH) / 2

  for (let r = 0; r < grid.height; r++) {
    for (let c = 0; c < grid.width; c++) {
      const cx = ox + c * cellSize
      const cy = oy + r * cellSize
      const isBlack = grid.cells[r][c] === 'black'
      ctx.fillStyle = isBlack ? '#090909' : '#1e1e1e'
      ctx.fillRect(cx, cy, cellSize, cellSize)
      ctx.strokeStyle = '#555555'
      ctx.lineWidth = 0.5
      ctx.strokeRect(cx, cy, cellSize, cellSize)
    }
  }
}

export default function DailyPreviewRenderer() {
  const canvasRef = useRef<HTMLCanvasElement>(null)

  async function generateImage() {
    const canvas = canvasRef.current
    if (!canvas) return
    const ctx = canvas.getContext('2d')!

    const today = new Date().toISOString().split('T')[0]
    const dateDisplay = new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }).toUpperCase()

    const grids: (GridData | null)[] = await Promise.all(
      PRESETS.map(async (p) => {
        try {
          const res = await api.fetchDaily(today, p.id)
          return { width: res.puzzle.width, height: res.puzzle.height, cells: res.puzzle.cells }
        } catch { return null }
      })
    )

    const cardW = 400
    const cardGap = 32
    const headerH = 240
    const gridPad = 24
    const bottomPad = 24
    const gridAreaW = cardW - gridPad * 2
    const maxGridH = 600

    let tallestCard = headerH + bottomPad
    for (const grid of grids) {
      if (grid) {
        const cellSize = Math.min(gridAreaW / grid.width, maxGridH / grid.height)
        const h = headerH + cellSize * grid.height + bottomPad
        if (h > tallestCard) tallestCard = h
      }
    }

    const topRuleH = 3
    const nameH = 190
    const dateH = 120
    const bottomRuleH = 3
    const gapAfterRule = 80
    const todaysH = 52
    const gapBeforeCards = 40
    const accentGap = 50
    const accentH = 3

    const totalContentH = topRuleH + nameH + dateH + bottomRuleH + gapAfterRule + todaysH + gapBeforeCards + tallestCard + accentGap + accentH
    const offsetY = Math.max(0, (H - totalContentH) / 2)

    ctx.fillStyle = '#111111'
    ctx.fillRect(0, 0, W, H)

    let y = offsetY

    ctx.fillStyle = '#ededed'
    ctx.fillRect(140, y, W - 280, topRuleH)
    y += topRuleH

    ctx.fillStyle = '#ededed'
    ctx.font = '900 180px "Playfair Display", Georgia, serif'
    ctx.textAlign = 'center'
    ctx.letterSpacing = '-5px'
    ctx.fillText('CRUCIVERB', W / 2, y + nameH)
    y += nameH

    ctx.fillStyle = '#ababab'
    ctx.font = '500 32px "JetBrains Mono", monospace'
    ctx.letterSpacing = '8px'
    ctx.fillText(dateDisplay, W / 2, y + 55)
    y += dateH

    ctx.fillStyle = '#ededed'
    ctx.fillRect(140, y, W - 280, bottomRuleH)
    y += bottomRuleH + gapAfterRule

    ctx.fillStyle = '#b5b5b5'
    ctx.font = 'italic 500 52px "Playfair Display", Georgia, serif'
    ctx.letterSpacing = '0px'
    ctx.fillText("Today's puzzles", W / 2, y + todaysH * 0.75)
    y += todaysH + gapBeforeCards

    const cardY = y
    const totalCardsW = 5 * cardW + 4 * cardGap
    const startX = (W - totalCardsW) / 2
    let maxCardBottom = cardY

    for (let i = 0; i < 5; i++) {
      const p = PRESETS[i]
      const grid = grids[i]
      const cx = startX + i * (cardW + cardGap)

      let cardH = headerH + bottomPad
      let gridDrawH = 0
      if (grid) {
        const cellSize = Math.min(gridAreaW / grid.width, maxGridH / grid.height)
        gridDrawH = cellSize * grid.height
        cardH = headerH + gridDrawH + bottomPad
      }

      maxCardBottom = Math.max(maxCardBottom, cardY + cardH)

      ctx.fillStyle = '#1a1a1a'
      ctx.fillRect(cx, cardY, cardW, cardH)
      ctx.strokeStyle = '#2a2a2a'
      ctx.lineWidth = 1
      ctx.strokeRect(cx, cardY, cardW, cardH)

      ctx.fillStyle = '#ededed'
      ctx.font = '700 56px "Playfair Display", Georgia, serif'
      ctx.textAlign = 'center'
      ctx.letterSpacing = '-1px'
      ctx.fillText(p.name, cx + cardW / 2, cardY + 150)

      ctx.fillStyle = '#ababab'
      ctx.font = '500 20px "JetBrains Mono", monospace'
      ctx.letterSpacing = '3px'
      ctx.fillText(`${p.desc} ${p.tag}`, cx + cardW / 2, cardY + 185)

      if (grid) {
        renderGrid(ctx, grid, cx + gridPad, cardY + headerH, gridAreaW, gridDrawH)
      }
    }

    ctx.fillStyle = '#d4432f'
    ctx.fillRect(140, maxCardBottom + accentGap, W - 280, accentH)
    ctx.letterSpacing = '0px'

    // convert to JPEG and upload
    try {
      const jpegData = canvas.toDataURL('image/jpeg', 0.8)
      await fetch('/api/internal/daily-image', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ data: jpegData }),
      })
      document.title = 'daily-image-done'
    } catch (e) {
      console.error('failed to upload daily image', e)
      document.title = 'daily-image-done'
    }
  }

  useEffect(() => {
    generateImage().catch(e => {
      console.error('generateImage failed:', e)
      document.title = 'daily-image-done'
    })
  }, [])

  return (
    <div style={{ position: 'absolute', left: '-9999px', top: '-9999px' }}>
      <canvas ref={canvasRef} width={W} height={H} />
    </div>
  )
}
