'use client'

import { useState, useEffect, useRef, useCallback } from 'react'
import { toast } from 'sonner'
import { formatDateTime } from '@/lib/utils'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Label } from '@/components/ui/label'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog'
import {
  PlayCircle,
  Loader2,
  CheckCircle2,
  XCircle,
  Clock,
  FileText,
  FolderOpen,
  AlertTriangle,
  RefreshCw,
  Zap,
} from 'lucide-react'

const DEFAULT_DRIVE_ID = 'b!OYuzIexQkkOvfEPyMJPzzZHfzTrOCOdPhTWgTlzKs6M0ZWVrAc6LR4LjWl4QFEzm'
const DEFAULT_FOLDER_PATH = 'Claims/SHAPE Accounts'

interface SpDrive  { id: string; name: string; type: string }
interface SpFolder { id: string; name: string }

interface Run {
  id: string
  startedAt: string
  completedAt: string | null
  status: string
  dryRun: boolean
  driveId: string
  stats: Record<string, any> | null
  user?: { displayName: string | null; email: string } | null
}

interface LogLine {
  seq: number
  line: string
}

function StatusBadge({ status }: { status: string }) {
  if (status === 'completed') return <Badge className="bg-green-600">Completed</Badge>
  if (status === 'failed') return <Badge variant="destructive">Failed</Badge>
  if (status === 'running') return <Badge className="bg-blue-600 animate-pulse">Running</Badge>
  return <Badge variant="secondary">Pending</Badge>
}

function StatLine({ label, value }: { label: string; value: number | string }) {
  return (
    <div className="flex justify-between text-sm">
      <span className="text-muted-foreground">{label}</span>
      <span className="font-medium tabular-nums">{value}</span>
    </div>
  )
}

function formatDate(iso: string) {
  return formatDateTime(iso, { timeZoneName: undefined })
}

export function ShapeImportPanel({ initialRuns }: { initialRuns: Run[] }) {
  const [mounted, setMounted] = useState(false)
  useEffect(() => setMounted(true), [])
  const [runs, setRuns] = useState<Run[]>(initialRuns)

  // SharePoint picker state
  const [drives, setDrives] = useState<SpDrive[]>([])
  const [folders, setFolders] = useState<SpFolder[]>([])
  const [selectedDriveId, setSelectedDriveId] = useState<string>(DEFAULT_DRIVE_ID)
  const [selectedFolderId, setSelectedFolderId] = useState<string>('')
  const [folderPath, setFolderPath] = useState<string>(DEFAULT_FOLDER_PATH)
  const [loadingDrives, setLoadingDrives] = useState(false)
  const [loadingFolders, setLoadingFolders] = useState(false)
  const [pickerError, setPickerError] = useState<string | null>(null)

  const [activeRunId, setActiveRunId] = useState<string | null>(null)
  const [activeRunStatus, setActiveRunStatus] = useState<string>('idle')
  const [logLines, setLogLines] = useState<LogLine[]>([])
  const [lastSeq, setLastSeq] = useState(-1)
  const [viewingRunId, setViewingRunId] = useState<string | null>(null)
  const [confirmOpen, setConfirmOpen] = useState(false)
  const [starting, setStarting] = useState(false)
  const [gapFillRunning, setGapFillRunning] = useState(false)
  const [gapFillResult, setGapFillResult] = useState<Record<string, any> | null>(null)
  const logRef = useRef<HTMLPreElement>(null)
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null)

  const scrollToBottom = useCallback(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight
  }, [])

  useEffect(() => {
    scrollToBottom()
  }, [logLines, scrollToBottom])

  const stopPolling = useCallback(() => {
    if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null }
  }, [])

  const pollRun = useCallback(async (runId: string, currentSeq: number) => {
    try {
      const res = await fetch(`/api/admin/shape-import/${runId}?after=${currentSeq}`)
      if (!res.ok) return
      const data = await res.json()

      if (data.logs && data.logs.length > 0) {
        setLogLines((prev) => {
          const existing = new Set(prev.map((l) => l.seq))
          const newLines = (data.logs as LogLine[]).filter((l) => !existing.has(l.seq))
          return [...prev, ...newLines]
        })
        const maxSeq = Math.max(...(data.logs as LogLine[]).map((l) => l.seq))
        setLastSeq(maxSeq)
        currentSeq = maxSeq
      }

      if (data.run?.status === 'completed' || data.run?.status === 'failed') {
        setActiveRunStatus(data.run.status)
        stopPolling()
        setRuns((prev) =>
          prev.map((r) => (r.id === runId ? { ...r, status: data.run.status, completedAt: data.run.completedAt, stats: data.run.stats } : r))
        )
      }
    } catch {
      // transient — keep polling
    }
  }, [stopPolling])

  const startPolling = useCallback((runId: string) => {
    stopPolling()
    let seq = -1
    pollRef.current = setInterval(async () => {
      try {
        const res = await fetch(`/api/admin/shape-import/${runId}?after=${seq}`)
        if (!res.ok) return
        const data = await res.json()
        if (data.logs && data.logs.length > 0) {
          setLogLines((prev) => {
            const existing = new Set(prev.map((l) => l.seq))
            const newLines = (data.logs as LogLine[]).filter((l) => !existing.has(l.seq))
            return [...prev, ...newLines]
          })
          seq = Math.max(...(data.logs as LogLine[]).map((l) => l.seq))
          setLastSeq(seq)
        }
        if (data.run?.status === 'completed' || data.run?.status === 'failed') {
          setActiveRunStatus(data.run.status)
          stopPolling()
          setRuns((prev) =>
            prev.map((r) => (r.id === runId ? { ...r, status: data.run.status, completedAt: data.run.completedAt, stats: data.run.stats } : r))
          )
          if (data.run.status === 'completed') toast.success('Import completed')
          else toast.error('Import failed — check the log for details')
        }
      } catch { /* keep polling */ }
    }, 2000)
  }, [stopPolling])

  useEffect(() => () => stopPolling(), [stopPolling])

  // Load document libraries on mount (site is fixed to Commercial)
  useEffect(() => {
    setLoadingDrives(true)
    setPickerError(null)
    fetch('/api/admin/shape-import/browse?level=drives')
      .then((r) => r.json())
      .then((d) => { if (d.drives) setDrives(d.drives); else setPickerError(d.error ?? 'Failed to load document libraries') })
      .catch((e) => setPickerError(e.message))
      .finally(() => setLoadingDrives(false))
  }, [])

  const handleDriveChange = async (driveId: string) => {
    setSelectedDriveId(driveId)
    setSelectedFolderId('')
    setFolderPath(DEFAULT_FOLDER_PATH)
    setFolders([])
    setLoadingFolders(true)
    setPickerError(null)
    try {
      const res = await fetch(`/api/admin/shape-import/browse?level=folders&driveId=${encodeURIComponent(driveId)}`)
      const d = await res.json()
      if (d.folders) setFolders(d.folders)
      else setPickerError(d.error ?? 'Failed to load folders')
    } catch (e: any) { setPickerError(e.message) }
    finally { setLoadingFolders(false) }
  }

  const handleFolderChange = async (folderId: string) => {
    setSelectedFolderId(folderId)
    const folderName = folders.find((f) => f.id === folderId)?.name ?? ''
    // Build path: drill one level into selected folder
    const newPath = folderName ? folderName : DEFAULT_FOLDER_PATH
    setFolderPath(newPath)
    // Load subfolders so user can go deeper if needed
    setLoadingFolders(true)
    try {
      const res = await fetch(`/api/admin/shape-import/browse?level=folders&driveId=${encodeURIComponent(selectedDriveId)}&itemId=${encodeURIComponent(folderId)}`)
      const d = await res.json()
      if (d.folders && d.folders.length > 0) setFolders(d.folders)
    } catch { /* ignore */ }
    finally { setLoadingFolders(false) }
  }

  const startRun = async (dryRun: boolean) => {
    setStarting(true)
    setLogLines([])
    setLastSeq(-1)
    try {
      const res = await fetch('/api/admin/shape-import', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ dryRun, driveId: selectedDriveId, folderPath }),
      })
      const data = await res.json()
      if (!res.ok) throw new Error(data.error || 'Failed to start')
      const newRun: Run = { id: data.runId, startedAt: new Date().toISOString(), completedAt: null, status: 'running', dryRun, driveId: selectedDriveId, stats: null }
      setRuns((prev) => [newRun, ...prev])
      setActiveRunId(data.runId)
      setViewingRunId(data.runId)
      setActiveRunStatus('running')
      startPolling(data.runId)
      toast.info(dryRun ? 'Dry run started — results will appear in the log' : 'Import started')
    } catch (err: any) {
      toast.error(err.message || 'Failed to start import')
    } finally {
      setStarting(false)
    }
  }

  const loadRunLog = async (runId: string) => {
    setViewingRunId(runId)
    setLogLines([])
    setLastSeq(-1)
    try {
      const res = await fetch(`/api/admin/shape-import/${runId}?after=-1`)
      if (!res.ok) return
      const data = await res.json()
      setLogLines(data.logs || [])
      if (data.logs?.length) setLastSeq(data.logs[data.logs.length - 1].seq)
    } catch { /* ignore */ }
  }

  const isRunning = activeRunStatus === 'running' && activeRunId !== null
  const canRun = !!selectedDriveId && !isRunning && !starting

  return (
    <div className="space-y-6">
      {/* Configuration */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2 text-base">
            <FileText className="h-4 w-4" />
            SHAPE Historical Import
          </CardTitle>
        </CardHeader>
        <CardContent className="space-y-5">
          <p className="text-sm text-muted-foreground">
            Import historical task completion data from SHAPE Excel files on SharePoint into Horizon.
            Always run a <strong>dry run first</strong> — it reads SharePoint and shows what would be
            created/updated without writing anything to the database.
          </p>

          {/* SharePoint location picker */}
          <div className="space-y-3 p-4 border rounded-lg bg-muted/20">
            <div className="flex items-center justify-between">
              <p className="text-sm font-medium flex items-center gap-1.5">
                <FolderOpen className="h-4 w-4" /> SharePoint Location
              </p>
              {pickerError && (
                <p className="text-xs text-destructive">{pickerError}</p>
              )}
            </div>

            <div className="text-xs text-muted-foreground">
              Site: <span className="font-medium text-foreground">seubert365.sharepoint.com/sites/Commercial</span>
            </div>

            {/* Document library (drive) */}
            <div className="space-y-1">
              <Label className="text-xs">Document Library</Label>
              <Select
                value={selectedDriveId}
                onValueChange={handleDriveChange}
                disabled={isRunning || loadingDrives}
              >
                <SelectTrigger className="h-8 text-sm">
                  {loadingDrives ? (
                    <span className="flex items-center gap-2 text-muted-foreground">
                      <Loader2 className="h-3 w-3 animate-spin" /> Loading libraries…
                    </span>
                  ) : (
                    <SelectValue placeholder="Select a document library…" />
                  )}
                </SelectTrigger>
                <SelectContent>
                  {drives.map((d) => (
                    <SelectItem key={d.id} value={d.id}>{d.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            {/* Folder */}
            {folders.length > 0 && (
              <div className="space-y-1">
                <Label className="text-xs">Folder</Label>
                <Select
                  value={selectedFolderId}
                  onValueChange={handleFolderChange}
                  disabled={isRunning || loadingFolders}
                >
                  <SelectTrigger className="h-8 text-sm">
                    {loadingFolders ? (
                      <span className="flex items-center gap-2 text-muted-foreground">
                        <Loader2 className="h-3 w-3 animate-spin" /> Loading folders…
                      </span>
                    ) : (
                      <SelectValue placeholder="Select a folder…" />
                    )}
                  </SelectTrigger>
                  <SelectContent>
                    {folders.map((f) => (
                      <SelectItem key={f.id} value={f.id}>{f.name}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            )}

            {/* Summary line */}
            <div className="flex items-center justify-between pt-1">
              <p className="text-xs text-muted-foreground">
                Path: <code className="bg-background px-1 py-0.5 rounded">{folderPath}</code>
              </p>
              <Button
                variant="ghost"
                size="sm"
                className="h-6 text-xs gap-1"
                onClick={() => {
                  setSelectedDriveId(DEFAULT_DRIVE_ID)
                  setSelectedFolderId(''); setFolderPath(DEFAULT_FOLDER_PATH)
                  setFolders([])
                }}
                disabled={isRunning}
              >
                <RefreshCw className="h-3 w-3" /> Reset to default
              </Button>
            </div>
          </div>

          <div className="flex gap-3">
            <Button
              onClick={() => startRun(true)}
              disabled={!canRun}
              variant="outline"
              className="gap-2"
            >
              {isRunning && viewingRunId === activeRunId ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <PlayCircle className="h-4 w-4" />
              )}
              Run Dry Run
            </Button>

            <Button
              onClick={() => setConfirmOpen(true)}
              disabled={!canRun}
              variant="destructive"
              className="gap-2"
            >
              <AlertTriangle className="h-4 w-4" />
              Execute Import
            </Button>

            <Button
              onClick={async () => {
                setGapFillRunning(true)
                setGapFillResult(null)
                try {
                  const res = await fetch('/api/admin/gap-fill', { method: 'POST' })
                  const data = await res.json()
                  if (!res.ok) throw new Error(data.error || 'Gap fill failed')
                  setGapFillResult(data.summary)
                  toast.success(`Gap Fill: ${data.summary.totalCreated} tasks created`)
                } catch (err: any) {
                  toast.error(err.message)
                } finally {
                  setGapFillRunning(false)
                }
              }}
              disabled={gapFillRunning || isRunning}
              variant="outline"
              className="gap-2"
            >
              {gapFillRunning ? <Loader2 className="h-4 w-4 animate-spin" /> : <Zap className="h-4 w-4" />}
              Gap Fill
            </Button>
          </div>

          {gapFillResult && (
            <div className="text-sm p-3 rounded-lg bg-muted/40 space-y-1">
              <p className="font-medium">Gap Fill complete</p>
              <p className="text-muted-foreground">Group tasks: {gapFillResult.groupTasksCreated} · Policy tasks: {gapFillResult.policyTasksCreated} · Client tasks: {gapFillResult.clientTasksCreated} · Total: {gapFillResult.totalCreated}</p>
              {gapFillResult.errors > 0 && <p className="text-destructive">{gapFillResult.errors} errors</p>}
            </div>
          )}

          {isRunning && (
            <div className="flex items-center gap-2 text-sm text-blue-600">
              <Loader2 className="h-4 w-4 animate-spin" />
              Import running — log updating live below…
            </div>
          )}
        </CardContent>
      </Card>

      {/* Log viewer */}
      {viewingRunId && (
        <Card>
          <CardHeader>
            <CardTitle className="flex items-center justify-between text-base">
              <span className="flex items-center gap-2">
                <FileText className="h-4 w-4" />
                Import Log
                {isRunning && viewingRunId === activeRunId && (
                  <Badge className="bg-blue-600 animate-pulse text-xs">Live</Badge>
                )}
              </span>
              {(() => {
                const run = runs.find((r) => r.id === viewingRunId)
                return run ? <StatusBadge status={run.status} /> : null
              })()}
            </CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            {/* Stats summary (completed runs) */}
            {(() => {
              const run = runs.find((r) => r.id === viewingRunId)
              if (!run?.stats || run.status === 'running') return null
              const s = run.stats
              return (
                <div className="grid grid-cols-2 md:grid-cols-4 gap-3 p-3 bg-muted/40 rounded-lg">
                  <div className="space-y-1">
                    <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Clients</p>
                    <StatLine label="Matched" value={s.clientsMatched ?? 0} />
                    <StatLine label="Unmatched" value={s.clientsUnmatched ?? 0} />
                  </div>
                  <div className="space-y-1">
                    <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Tasks</p>
                    <StatLine label="Created" value={s.tasksCreated ?? 0} />
                    <StatLine label="Updated" value={s.tasksUpdated ?? 0} />
                    <StatLine label="Assigned" value={s.tasksAssigned ?? 0} />
                  </div>
                  <div className="space-y-1">
                    <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Other</p>
                    <StatLine label="Ad-hoc" value={s.adHocCreated ?? 0} />
                    <StatLine label="Duplicates deleted" value={s.duplicatesDeleted ?? 0} />
                    <StatLine label="Files" value={s.filesProcessed ?? 0} />
                  </div>
                  <div className="space-y-1">
                    <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">Issues</p>
                    <StatLine label="Errors" value={(s.errors as any[])?.length ?? 0} />
                    <StatLine label="Fuzzy matches" value={(s.fuzzyMatches as any[])?.length ?? 0} />
                  </div>
                </div>
              )
            })()}

            {/* Log */}
            <pre
              ref={logRef}
              className="bg-zinc-950 text-zinc-100 text-xs font-mono rounded-lg p-4 overflow-auto max-h-[500px] whitespace-pre-wrap leading-relaxed"
            >
              {logLines.length === 0
                ? '(waiting for output...)'
                : logLines.map((l) => l.line).join('\n')}
            </pre>
          </CardContent>
        </Card>
      )}

      {/* Run history */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2 text-base">
            <Clock className="h-4 w-4" />
            Run History
          </CardTitle>
        </CardHeader>
        <CardContent>
          {runs.length === 0 ? (
            <p className="text-sm text-muted-foreground text-center py-4">No runs yet</p>
          ) : (
            <div className="space-y-2">
              {runs.map((run) => (
                <button
                  key={run.id}
                  onClick={() => loadRunLog(run.id)}
                  className={`w-full text-left p-3 rounded-lg border transition-colors hover:bg-accent ${viewingRunId === run.id ? 'bg-accent border-primary' : ''}`}
                >
                  <div className="flex items-center justify-between gap-3">
                    <div className="flex items-center gap-2 min-w-0">
                      {run.status === 'completed' ? (
                        <CheckCircle2 className="h-4 w-4 text-green-600 shrink-0" />
                      ) : run.status === 'failed' ? (
                        <XCircle className="h-4 w-4 text-red-600 shrink-0" />
                      ) : (
                        <Loader2 className="h-4 w-4 text-blue-600 animate-spin shrink-0" />
                      )}
                      <div className="min-w-0">
                        <p className="text-sm font-medium truncate">
                          {run.dryRun ? 'Dry Run' : 'Execute'} — {mounted ? formatDate(run.startedAt) : ''}
                        </p>
                        {run.user && (
                          <p className="text-xs text-muted-foreground">by {run.user.displayName || run.user.email}</p>
                        )}
                      </div>
                    </div>
                    <div className="flex items-center gap-2 shrink-0">
                      <StatusBadge status={run.status} />
                      {run.stats && (
                        <span className="text-xs text-muted-foreground tabular-nums">
                          {(run.stats as any).tasksCreated ?? 0} created · {(run.stats as any).errors?.length ?? 0} errors
                        </span>
                      )}
                    </div>
                  </div>
                </button>
              ))}
            </div>
          )}
        </CardContent>
      </Card>

      {/* Execute confirmation dialog */}
      <Dialog open={confirmOpen} onOpenChange={setConfirmOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2 text-destructive">
              <AlertTriangle className="h-5 w-5" />
              Execute SHAPE Import
            </DialogTitle>
          </DialogHeader>
          <div className="space-y-3 text-sm">
            <p>This will <strong>write data to the database</strong>:</p>
            <ul className="list-disc pl-5 space-y-1 text-muted-foreground">
              <li>Create or update tasks for matched SHAPE clients</li>
              <li>Mark historical tasks as Completed or N/A</li>
              <li>Assign claims advocates to clients (if not already set)</li>
              <li>Delete duplicate tasks</li>
            </ul>
            <p className="text-muted-foreground">
              Run a <strong>dry run first</strong> and review the log if you haven't already.
              This action cannot be automatically undone.
            </p>
          </div>
          <DialogFooter>
            <Button variant="ghost" onClick={() => setConfirmOpen(false)}>Cancel</Button>
            <Button
              variant="destructive"
              onClick={() => { setConfirmOpen(false); startRun(false) }}
            >
              Yes, Execute Import
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}
