import { useState, useEffect } from 'react'
import { Download, FileSpreadsheet, Loader2, Plus, Trash2 } from 'lucide-react'
import api from '@/services/api'
import type { ReportMeta } from '@/types'
import { useAuth } from '@/context/AuthContext'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Checkbox } from '@/components/ui/checkbox'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
  Table, TableBody, TableCell, TableHead, TableHeader, TableRow,
} from '@/components/ui/table'
import { Skeleton } from '@/components/ui/skeleton'
import { Alert, AlertDescription } from '@/components/ui/alert'

export function ReportsPage() {
  const { isAdmin } = useAuth()
  const currentYear = new Date().getFullYear()
  const currentKw = getISOWeek(new Date())

  const [reports, setReports] = useState<ReportMeta[]>([])
  const [totalReports, setTotalReports] = useState(0)
  const [loading, setLoading] = useState(true)

  // Report generation state
  const [genJahr, setGenJahr] = useState(currentYear)
  const [genKw, setGenKw] = useState(currentKw)
  const [generating, setGenerating] = useState(false)
  const [genError, setGenError] = useState('')
  const [genSuccess, setGenSuccess] = useState('')

  // Selection state for deletion
  const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set())
  const [deleting, setDeleting] = useState(false)

  // Fetch reports list
  const fetchReports = () => {
    setLoading(true)
    api.get<{ items: ReportMeta[]; total: number }>('/reports/list')
      .then((res) => {
        setReports(res.data.items)
        setTotalReports(res.data.total)
      })
      .catch(() => {
        setReports([])
        setTotalReports(0)
      })
      .finally(() => setLoading(false))
  }

  useEffect(() => {
    fetchReports()
  }, [])

  const generateReport = async () => {
    setGenerating(true)
    setGenError('')
    setGenSuccess('')
    try {
      const res = await api.post<ReportMeta>('/reports/generate', null, {
        params: { jahr: genJahr, kw: genKw },
      })
      setGenSuccess(`Bericht für KW ${res.data.kw}/${res.data.jahr} wurde generiert.`)
      fetchReports()
    } catch {
      setGenError('Fehler beim Generieren des Berichts.')
    } finally {
      setGenerating(false)
    }
  }

  const downloadReport = (reportId: number) => {
    const token = localStorage.getItem('access_token')
    const url = `/api/reports/download/${reportId}`
    api.get(url, { responseType: 'blob' })
      .then((res) => {
        const blob = new Blob([res.data as BlobPart], {
          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        })
        const blobUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = blobUrl
        const contentDisposition = res.headers['content-disposition']
        let filename = `bericht_${reportId}.xlsx`
        if (contentDisposition) {
          const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
          if (match) filename = match[1].replace(/['"]/g, '')
        }
        link.download = filename
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(blobUrl)
      })
      .catch(() => {
        if (token) {
          window.open(`${url}?token=${encodeURIComponent(token)}`, '_blank')
        }
      })
  }

  const toggleSelect = (id: number) => {
    setSelectedIds((prev) => {
      const next = new Set(prev)
      if (next.has(id)) {
        next.delete(id)
      } else {
        next.add(id)
      }
      return next
    })
  }

  const toggleSelectAll = () => {
    if (selectedIds.size === reports.length) {
      setSelectedIds(new Set())
    } else {
      setSelectedIds(new Set(reports.map((r) => r.id)))
    }
  }

  const deleteSelected = async () => {
    if (selectedIds.size === 0) return
    setDeleting(true)
    try {
      await api.delete('/reports/delete', { data: Array.from(selectedIds) })
      setSelectedIds(new Set())
      fetchReports()
    } catch {
      setGenError('Fehler beim Löschen der Berichte.')
    } finally {
      setDeleting(false)
    }
  }

  return (
    <div className="p-6 space-y-6">
      <h1 className="text-2xl font-bold">Berichte</h1>

      {/* Report generation (admin only) */}
      {isAdmin && (
        <Card>
          <CardHeader>
            <CardTitle className="text-lg flex items-center gap-2">
              <FileSpreadsheet className="h-5 w-5" />
              Bericht generieren
            </CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="flex flex-wrap items-end gap-4">
              <div className="space-y-1">
                <Label htmlFor="gen-jahr">Jahr</Label>
                <Input
                  id="gen-jahr"
                  type="number"
                  value={genJahr}
                  onChange={(e) => setGenJahr(Number(e.target.value))}
                  className="w-28"
                  min={2020}
                  max={2030}
                />
              </div>
              <div className="space-y-1">
                <Label htmlFor="gen-kw">Kalenderwoche</Label>
                <Input
                  id="gen-kw"
                  type="number"
                  value={genKw}
                  onChange={(e) => setGenKw(Number(e.target.value))}
                  className="w-28"
                  min={1}
                  max={53}
                />
              </div>
              <Button onClick={generateReport} disabled={generating}>
                {generating ? (
                  <>
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    Wird generiert...
                  </>
                ) : (
                  <>
                    <Plus className="mr-2 h-4 w-4" />
                    Bericht generieren
                  </>
                )}
              </Button>
            </div>
            {genError && (
              <Alert variant="destructive">
                <AlertDescription>{genError}</AlertDescription>
              </Alert>
            )}
            {genSuccess && (
              <Alert>
                <AlertDescription>{genSuccess}</AlertDescription>
              </Alert>
            )}
          </CardContent>
        </Card>
      )}

      {/* Reports table */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle className="text-lg">
              Bisherige Berichte ({totalReports})
            </CardTitle>
            {isAdmin && selectedIds.size > 0 && (
              <Button
                variant="destructive"
                size="sm"
                onClick={deleteSelected}
                disabled={deleting}
              >
                {deleting ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Trash2 className="mr-2 h-4 w-4" />
                )}
                {selectedIds.size} Bericht{selectedIds.size > 1 ? 'e' : ''} löschen
              </Button>
            )}
          </div>
        </CardHeader>
        <CardContent>
          {loading ? (
            <div className="space-y-2">
              {Array.from({ length: 5 }).map((_, i) => (
                <Skeleton key={i} className="h-10 w-full" />
              ))}
            </div>
          ) : reports.length > 0 ? (
            <Table>
              <TableHeader>
                <TableRow>
                  {isAdmin && (
                    <TableHead className="w-10">
                      <Checkbox
                        checked={reports.length > 0 && selectedIds.size === reports.length}
                        onCheckedChange={toggleSelectAll}
                      />
                    </TableHead>
                  )}
                  <TableHead>Berichtsdatum</TableHead>
                  <TableHead>Jahr</TableHead>
                  <TableHead>KW</TableHead>
                  <TableHead>Erstellt am</TableHead>
                  <TableHead className="text-right">Aktion</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {reports.map((r) => (
                  <TableRow key={r.id}>
                    {isAdmin && (
                      <TableCell>
                        <Checkbox
                          checked={selectedIds.has(r.id)}
                          onCheckedChange={() => toggleSelect(r.id)}
                        />
                      </TableCell>
                    )}
                    <TableCell>{formatDate(r.report_date)}</TableCell>
                    <TableCell>{r.jahr}</TableCell>
                    <TableCell>KW {r.kw}</TableCell>
                    <TableCell>{formatDateTime(r.generated_at)}</TableCell>
                    <TableCell className="text-right">
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={() => downloadReport(r.id)}
                      >
                        <Download className="mr-1.5 h-4 w-4" />
                        Download
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          ) : (
            <p className="py-8 text-center text-muted-foreground">
              Keine Berichte vorhanden.
            </p>
          )}
        </CardContent>
      </Card>
    </div>
  )
}

function getISOWeek(date: Date): number {
  const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))
  const dayNum = d.getUTCDay() || 7
  d.setUTCDate(d.getUTCDate() + 4 - dayNum)
  const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1))
  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86_400_000 + 1) / 7)
}

function formatDate(dateStr: string): string {
  try {
    return new Date(dateStr).toLocaleDateString('de-DE', {
      day: '2-digit', month: '2-digit', year: 'numeric',
    })
  } catch {
    return dateStr
  }
}

function formatDateTime(dateStr: string): string {
  try {
    return new Date(dateStr).toLocaleString('de-DE', {
      day: '2-digit', month: '2-digit', year: 'numeric',
      hour: '2-digit', minute: '2-digit',
    })
  } catch {
    return dateStr
  }
}
