import { useCallback } from 'react'
import { jsPDF } from 'jspdf'
import type { DrawFeature, Project } from '@/types'

interface UseMapExportOptions {
  mapRef: React.MutableRefObject<any>
  featuresRef: React.MutableRefObject<DrawFeature[]>
  currentProject: Project | null
  tenant: { id: string; name: string } | null
  addAudit: (action: string) => void
  toast: (opts: { title: string; description?: string; variant?: string }) => void
}

export function useMapExport({
  mapRef,
  featuresRef,
  currentProject,
  tenant,
  addAudit,
  toast,
}: UseMapExportOptions) {
  const handleExport = useCallback(async (format: 'png' | 'pdf') => {
    const mapInstance = mapRef.current
    if (!mapInstance) {
      toast({ title: 'Fehler', description: 'Karte nicht bereit.', variant: 'destructive' })
      return
    }

    try {
      // 1. Get the MapLibre canvas (tiles + vector drawings)
      const mapCanvas = mapInstance.getCanvas() as HTMLCanvasElement
      const w = mapCanvas.width
      const h = mapCanvas.height

      // 2. Create composite canvas
      const exportCanvas = document.createElement('canvas')
      exportCanvas.width = w
      exportCanvas.height = h
      const ctx = exportCanvas.getContext('2d')!
      ctx.drawImage(mapCanvas, 0, 0)

      // 3. Draw symbols manually at correct size/rotation
      const currentFeatures = featuresRef.current
      // Derive actual pixel ratio from canvas vs container (more reliable than window.devicePixelRatio)
      const container = mapInstance.getContainer()
      const dpr = mapCanvas.width / container.offsetWidth
      const zoom = mapInstance.getZoom()
      // Symbol sizing: match the map rendering logic exactly
      // In map-view.tsx: size = baseSize * scale * Math.pow(2, currentZoom - placementZoom)
      const currentZoom = zoom

      // Helper: load image as promise
      const loadImage = (src: string): Promise<HTMLImageElement> => new Promise((resolve, reject) => {
        const img = new Image()
        img.crossOrigin = 'anonymous'
        img.onload = () => resolve(img)
        img.onerror = reject
        img.src = src
      })

      // Draw symbol features
      for (const f of currentFeatures.filter(f => f.type === 'symbol')) {
        if (f.geometry.type !== 'Point') continue
        const coords = f.geometry.coordinates as [number, number]
        const pixel = mapInstance.project(coords)
        const px = pixel.x * dpr
        const py = pixel.y * dpr

        const scale = (f.properties.scale as number) || 1
        const rotation = (f.properties.rotation as number) || 0
        const baseSize = 32
        const placementZoom = (f.properties.placementZoom as number) || 17
        const zoomFactor = Math.pow(2, currentZoom - placementZoom)
        const size = Math.max(8, Math.min(400, baseSize * scale * zoomFactor)) * dpr

        // Determine image source
        const iconId = f.properties.iconId as string
        const imageUrl = f.properties.imageUrl as string
        let imgSrc = imageUrl || ''
        if (!imgSrc && iconId) {
          const { getSymbolById, getSymbolDataUri } = await import('@/lib/fw-symbols')
          const sym = getSymbolById(iconId)
          if (sym) imgSrc = getSymbolDataUri(sym)
        }

        if (imgSrc) {
          try {
            const img = await loadImage(imgSrc)
            // Replicate CSS background-size: contain (preserve aspect ratio)
            const imgAspect = img.naturalWidth / img.naturalHeight
            let drawW = size
            let drawH = size
            if (imgAspect > 1) {
              drawH = size / imgAspect
            } else {
              drawW = size * imgAspect
            }
            ctx.save()
            ctx.translate(px, py)
            ctx.rotate((rotation * Math.PI) / 180)
            ctx.drawImage(img, -drawW / 2, -drawH / 2, drawW, drawH)
            ctx.restore()
          } catch (e) {
            console.warn('[Export] Failed to load symbol image:', iconId, e)
          }
        }
      }

      // Draw arrowheads for arrow features
      for (const f of currentFeatures.filter(f => f.type === 'arrow')) {
        if (f.geometry.type !== 'LineString') continue
        const lineCoords = f.geometry.coordinates as number[][]
        if (lineCoords.length < 2) continue
        const p1 = lineCoords[lineCoords.length - 2]
        const p2 = lineCoords[lineCoords.length - 1]
        const px1 = mapInstance.project(p1 as [number, number])
        const px2 = mapInstance.project(p2 as [number, number])
        const angle = Math.atan2(px2.y - px1.y, px2.x - px1.x)
        const color = (f.properties.color as string) || '#000000'
        const arrowSize = 14 * dpr

        ctx.save()
        ctx.translate(px2.x * dpr, px2.y * dpr)
        ctx.rotate(angle + Math.PI / 2)
        ctx.beginPath()
        ctx.moveTo(0, -arrowSize)
        ctx.lineTo(-arrowSize * 0.7, arrowSize * 0.3)
        ctx.lineTo(arrowSize * 0.7, arrowSize * 0.3)
        ctx.closePath()
        ctx.fillStyle = color
        ctx.fill()
        ctx.restore()
      }

      // Draw line/polygon label markers at midpoints
      for (const f of currentFeatures.filter(f => f.properties.label && (f.geometry.type === 'LineString' || f.geometry.type === 'Polygon'))) {
        const label = f.properties.label as string
        let midpoint: [number, number]

        if (f.geometry.type === 'LineString') {
          const coords = f.geometry.coordinates as number[][]
          const midIdx = Math.floor(coords.length / 2)
          if (coords.length === 2) {
            midpoint = [(coords[0][0] + coords[1][0]) / 2, (coords[0][1] + coords[1][1]) / 2]
          } else {
            midpoint = coords[midIdx] as [number, number]
          }
        } else {
          // Polygon: centroid of first ring
          const ring = (f.geometry.coordinates as number[][][])[0]
          const len = ring.length - 1
          let cx = 0, cy = 0
          for (let i = 0; i < len; i++) { cx += ring[i][0]; cy += ring[i][1] }
          midpoint = [cx / len, cy / len]
        }

        const pixel = mapInstance.project(midpoint)
        const px = pixel.x * dpr
        const py = pixel.y * dpr
        const fontSize = 13 * dpr
        const isDanger = f.type === 'dangerzone'
        const bgColor = isDanger ? 'rgba(220,38,38,0.85)' : 'rgba(0,0,0,0.75)'
        const borderColor = isDanger ? '#dc2626' : 'rgba(255,255,255,0.5)'

        ctx.save()
        ctx.font = `bold ${fontSize}px system-ui, sans-serif`
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        const metrics = ctx.measureText(label)
        const padX = 7 * dpr
        const padY = 3 * dpr
        const boxW = metrics.width + padX * 2
        const boxH = fontSize + padY * 2
        const radius = 4 * dpr

        // Background pill
        ctx.fillStyle = bgColor
        ctx.beginPath()
        ctx.roundRect(px - boxW / 2, py - boxH / 2, boxW, boxH, radius)
        ctx.fill()

        // Border
        ctx.strokeStyle = borderColor
        ctx.lineWidth = 1.5 * dpr
        ctx.beginPath()
        ctx.roundRect(px - boxW / 2, py - boxH / 2, boxW, boxH, radius)
        ctx.stroke()

        // Text
        ctx.fillStyle = '#ffffff'
        ctx.fillText(label, px, py)
        ctx.restore()
      }

      // Draw text features
      for (const f of currentFeatures.filter(f => f.type === 'text')) {
        if (f.geometry.type !== 'Point') continue
        const coords = f.geometry.coordinates as [number, number]
        const pixel = mapInstance.project(coords)
        const px = pixel.x * dpr
        const py = pixel.y * dpr

        const text = (f.properties.text as string) || ''
        const fontSize = ((f.properties.fontSize as number) || 14) * dpr
        const color = (f.properties.color as string) || '#000000'

        ctx.save()
        ctx.font = `bold ${fontSize}px system-ui, sans-serif`
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        // White outline
        ctx.strokeStyle = '#ffffff'
        ctx.lineWidth = 3 * dpr
        ctx.lineJoin = 'round'
        ctx.strokeText(text, px, py)
        // Fill
        ctx.fillStyle = color
        ctx.fillText(text, px, py)
        ctx.restore()
      }

      const title = currentProject?.title || 'Lageplan'
      const safeName = title.replace(/[^a-z0-9äöüÄÖÜß]/gi, '_')

      if (format === 'png') {
        const link = document.createElement('a')
        link.download = `${safeName}.png`
        link.href = exportCanvas.toDataURL('image/png')
        link.click()
        addAudit(`Export: ${safeName}.png`)
        toast({ title: 'Exportiert', description: `${safeName}.png wurde heruntergeladen.` })
      } else {
        // PDF Export — rapport-style clean layout
        const imgData = exportCanvas.toDataURL('image/png')
        const now = new Date()
        const dateStr = now.toLocaleDateString('de-CH', { day: '2-digit', month: '2-digit', year: 'numeric' })
        const timeStr = now.toLocaleTimeString('de-CH', { hour: '2-digit', minute: '2-digit' })
        const locationStr = currentProject?.location || ''
        const einsatzNr = (currentProject as any)?.einsatzNr || ''
        const tenantLabel = tenant?.name || ''

        // A4 landscape (mm)
        const pdf = new jsPDF('l', 'mm', 'a4')
        const pageW = pdf.internal.pageSize.getWidth()   // 297
        const pageH = pdf.internal.pageSize.getHeight()   // 210
        const m = 10 // margin

        // ── Header section ──
        const headerY = m
        pdf.setFontSize(18)
        pdf.setFont('helvetica', 'bold')
        pdf.setTextColor(26, 26, 26)
        pdf.text('Einsatz-Lageplan', m, headerY + 6)

        pdf.setFontSize(9)
        pdf.setFont('helvetica', 'normal')
        pdf.setTextColor(107, 114, 128) // gray-500
        pdf.text(`${tenantLabel}${tenantLabel ? '  ·  ' : ''}${title}`, m, headerY + 12)

        // Right side: Einsatz-Nr + date
        pdf.setFontSize(14)
        pdf.setFont('helvetica', 'bold')
        pdf.setTextColor(185, 28, 28) // red-700
        if (einsatzNr) {
          const nrW = pdf.getTextWidth(einsatzNr)
          pdf.text(einsatzNr, pageW - m - nrW, headerY + 6)
        }
        pdf.setFontSize(9)
        pdf.setFont('helvetica', 'normal')
        pdf.setTextColor(107, 114, 128)
        const dateLabel = `${dateStr}  ·  ${timeStr}`
        const dlW = pdf.getTextWidth(dateLabel)
        pdf.text(dateLabel, pageW - m - dlW, headerY + 12)

        // Divider line + red accent
        const divY = headerY + 15
        pdf.setDrawColor(26, 26, 26)
        pdf.setLineWidth(0.8)
        pdf.line(m, divY, pageW - m, divY)
        pdf.setFillColor(185, 28, 28)
        pdf.rect(m, divY, (pageW - 2 * m) * 0.3, 1, 'F')

        // ── Map image ──
        const mapTop = divY + 3
        const mapBottom = pageH - m - 12 // leave space for footer
        const mapAreaW = pageW - 2 * m
        const mapAreaH = mapBottom - mapTop

        // Fit map image into area while preserving aspect ratio
        const imgAspect = w / h
        const areaAspect = mapAreaW / mapAreaH
        let drawW = mapAreaW
        let drawH = mapAreaH
        if (imgAspect > areaAspect) {
          drawH = mapAreaW / imgAspect
        } else {
          drawW = mapAreaH * imgAspect
        }
        const mapX = m + (mapAreaW - drawW) / 2
        const mapY = mapTop + (mapAreaH - drawH) / 2

        // Light border around map
        pdf.setDrawColor(229, 231, 235)
        pdf.setLineWidth(0.3)
        pdf.rect(mapX, mapY, drawW, drawH)
        pdf.addImage(imgData, 'PNG', mapX, mapY, drawW, drawH)

        // ── Footer ──
        const footerY = pageH - m - 4
        pdf.setFontSize(7)
        pdf.setFont('helvetica', 'normal')
        pdf.setTextColor(156, 163, 175) // gray-400
        pdf.text(`Erstellt: ${dateStr} ${timeStr}${locationStr ? '  ·  Standort: ' + locationStr : ''}  ·  Projekt: ${title}`, m, footerY)
        const footerR = 'app.lageplan.ch'
        const frW = pdf.getTextWidth(footerR)
        pdf.text(footerR, pageW - m - frW, footerY)

        pdf.save(`${safeName}.pdf`)
        addAudit(`Export: ${safeName}.pdf`)
        toast({ title: 'Exportiert', description: `${safeName}.pdf wurde heruntergeladen.` })
      }
    } catch (error) {
      console.error('Export error:', error)
      toast({ title: 'Fehler', description: 'Export fehlgeschlagen.', variant: 'destructive' })
    }
  }, [currentProject, tenant, toast, addAudit, mapRef, featuresRef])

  return { handleExport }
}
