import { useEffect, useState } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { Copy, Check, Eye, Save, Share2, CheckCircle2, AlertTriangle, ArrowUpRight, HelpCircle, Flag } from 'lucide-react'
import { sessionsApi } from '@/api/sessions'
import { stepsApi } from '@/api/steps'
import { ExportPreviewModal } from '@/components/session/ExportPreviewModal'
import { SaveSessionAsTreeModal } from '@/components/session/SaveSessionAsTreeModal'
import { ShareSessionModal } from '@/components/session/ShareSessionModal'
import { SessionOutcomeModal } from '@/components/session/SessionOutcomeModal'
import { SessionTimeline } from '@/components/session/SessionTimeline'
import { StepRatingModal } from '@/components/session/StepRatingModal'
import { ActionMenu } from '@/components/common/ActionMenu'
import type { MenuAction } from '@/components/common/ActionMenu'
import type { SessionOutcome } from '@/types'
import { useUserPreferencesStore } from '@/store/userPreferencesStore'
import type { Session, SessionExport, SaveAsTreeRequest, Step, RedactionSummary } from '@/types'
import { hasRatedSession, markSessionRated } from '@/lib/sessionRatings'
import { Spinner } from '@/components/common/Spinner'
import { cn } from '@/lib/utils'
import { toast } from '@/lib/toast'

export function SessionDetailPage() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()
  const { defaultExportFormat } = useUserPreferencesStore()
  const [session, setSession] = useState<Session | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [isExporting, setIsExporting] = useState(false)
  const [exportFormat, setExportFormat] = useState<'markdown' | 'text' | 'html' | 'psa'>(defaultExportFormat)
  const [exportContent, setExportContent] = useState<string | null>(null)
  const [showPreview, setShowPreview] = useState(false)
  const [copied, setCopied] = useState(false)
  const [copiedPsa, setCopiedPsa] = useState(false)
  const [showSaveAsTreeModal, setShowSaveAsTreeModal] = useState(false)
  const [isSavingTree, setIsSavingTree] = useState(false)
  const [showRatingModal, setShowRatingModal] = useState(false)
  const [isSavingRatings, setIsSavingRatings] = useState(false)
  const [librarySteps, setLibrarySteps] = useState<Step[]>([])
  const [showShareModal, setShowShareModal] = useState(false)
  const [showOutcomeModal, setShowOutcomeModal] = useState(false)
  const [isCompleting, setIsCompleting] = useState(false)
  const [maxStepIndex, setMaxStepIndex] = useState<number | null>(null)
  const [detailLevel, setDetailLevel] = useState<'standard' | 'full'>('standard')
  const [includeSummary, setIncludeSummary] = useState(false)
  const [redactionMode, setRedactionMode] = useState<'none' | 'mask'>('none')
  const [redactionSummary, setRedactionSummary] = useState<RedactionSummary | null>(null)

  useEffect(() => {
    if (id) {
      loadSession()
    }
  }, [id])

  // Auto-show rating modal for completed sessions with library steps
  useEffect(() => {
    if (!session || !session.completed_at) return

    // Check if already rated
    if (hasRatedSession(session.id)) return

    // Extract library steps from custom_steps
    const stepsFromLibrary = session.custom_steps?.filter(
      (customStep) => {
        // Check if step_data is a Step (from library) by checking if it has an id
        const stepData = customStep.step_data
        return 'id' in stepData && stepData.id
      }
    ) || []

    if (stepsFromLibrary.length === 0) return

    // Extract the Step objects
    const steps = stepsFromLibrary.map((cs) => cs.step_data as Step)
    setLibrarySteps(steps)

    // Show modal after 1 second delay
    const timer = setTimeout(() => {
      setShowRatingModal(true)
    }, 1000)

    return () => clearTimeout(timer)
  }, [session])

  const loadSession = async () => {
    setIsLoading(true)
    setError(null)
    try {
      const data = await sessionsApi.get(id!)
      setSession(data)
    } catch (err) {
      setError('Failed to load session')
      console.error(err)
    } finally {
      setIsLoading(false)
    }
  }

  const getFilename = () => {
    if (!session) return 'export.txt'
    const ext = exportFormat === 'markdown' ? 'md' : exportFormat === 'html' ? 'html' : 'txt'  // psa and text both use .txt
    return `session-${session.ticket_number || session.id}.${ext}`
  }

  const buildExportOptions = (overrides?: Partial<SessionExport>): SessionExport => ({
    format: exportFormat,
    include_timestamps: true,
    include_tree_info: true,
    ...(maxStepIndex !== null && { max_step_index: maxStepIndex }),
    detail_level: detailLevel,
    include_summary: includeSummary,
    redaction_mode: redactionMode,
    ...overrides,
  })

  const fetchExportContent = async () => {
    if (!session) return null
    const result = await sessionsApi.exportWithMeta(session.id, buildExportOptions())
    setRedactionSummary(result.redactionSummary)
    return result.content
  }

  const handlePreview = async () => {
    setIsExporting(true)
    try {
      const content = await fetchExportContent()
      if (content) {
        setExportContent(content)
        setShowPreview(true)
      }
    } catch (err) {
      console.error('Export failed:', err)
      toast.error('Failed to generate export preview')
    } finally {
      setIsExporting(false)
    }
  }

  const handleCopy = async () => {
    setIsExporting(true)
    try {
      const content = await fetchExportContent()
      if (content) {
        await navigator.clipboard.writeText(content)
        setCopied(true)
        setTimeout(() => setCopied(false), 2000)
        toast.success('Copied to clipboard')
      }
    } catch (err) {
      console.error('Copy failed:', err)
      toast.error('Failed to copy to clipboard')
    } finally {
      setIsExporting(false)
    }
  }

  const handleCopyForTicket = async () => {
    if (!session) return
    try {
      const content = await sessionsApi.export(session.id, buildExportOptions({ format: 'psa' }))
      if (content) {
        await navigator.clipboard.writeText(content)
        setCopiedPsa(true)
        setTimeout(() => setCopiedPsa(false), 2000)
        toast.success('Copied ticket notes to clipboard')
      }
    } catch (err) {
      console.error('Copy for ticket failed:', err)
      toast.error('Failed to copy ticket notes')
    }
  }

  const handleDownload = (content: string) => {
    if (!session) return
    const blob = new Blob([content], { type: 'text/plain' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = getFilename()
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  }

  const handleToggleSummary = async (include: boolean) => {
    setIncludeSummary(include)
    if (!session) return
    try {
      const result = await sessionsApi.exportWithMeta(session.id, buildExportOptions({ include_summary: include }))
      setExportContent(result.content)
      setRedactionSummary(result.redactionSummary)
      toast.success(include ? 'Summary added' : 'Summary removed')
    } catch (err) {
      console.error('Failed to re-fetch export:', err)
      toast.error('Failed to update export')
      setIncludeSummary(!include)
    }
  }

  const handleToggleRedaction = async (enabled: boolean) => {
    const mode = enabled ? 'mask' as const : 'none' as const
    setRedactionMode(mode)
    if (!session) return
    try {
      const result = await sessionsApi.exportWithMeta(session.id, buildExportOptions({ redaction_mode: mode }))
      setExportContent(result.content)
      setRedactionSummary(result.redactionSummary)
      toast.success(enabled ? 'Sensitive data masked' : 'Redaction removed')
    } catch (err) {
      console.error('Failed to re-fetch export:', err)
      toast.error('Failed to update export')
      setRedactionMode(enabled ? 'none' : 'mask')
    }
  }

  const handleSaveAsTree = async (data: SaveAsTreeRequest) => {
    if (!session) return
    setIsSavingTree(true)
    try {
      const result = await sessionsApi.saveAsTree(session.id, data)
      toast.success(result.message)
      setShowSaveAsTreeModal(false)
      // Navigate to tree editor with the new tree
      navigate(`/trees/${result.tree_id}/edit`)
    } catch (err) {
      console.error('Failed to save session as tree:', err)
      toast.error('Failed to save session as tree')
    } finally {
      setIsSavingTree(false)
    }
  }

  const handleCompleteSession = async (data: { outcome: SessionOutcome; outcome_notes?: string; next_steps?: string }) => {
    if (!session) return
    setIsCompleting(true)
    try {
      const updated = await sessionsApi.complete(session.id, data)
      setSession(updated)
      setShowOutcomeModal(false)
      toast.success('Session completed')
    } catch {
      toast.error('Failed to complete session')
    } finally {
      setIsCompleting(false)
    }
  }

  const getDefaultTreeName = () => {
    if (!session) return ''
    const treeName = session.tree_snapshot?.name || 'Tree'
    const ticket = session.ticket_number ? ` - ${session.ticket_number}` : ''
    return `${treeName}${ticket}`
  }

  const handleSubmitRatings = async (ratings: Map<string, { rating: number; helpful: boolean | null; review: string }>) => {
    if (!session) return
    setIsSavingRatings(true)
    try {
      // Submit each rating individually
      const ratingPromises = Array.from(ratings.entries()).map(([stepId, data]) =>
        stepsApi.rate(stepId, {
          rating: data.rating,
          review_text: data.review || undefined,
          was_helpful: data.helpful !== null ? data.helpful : undefined,
          session_id: session.id
        })
      )

      await Promise.all(ratingPromises)

      toast.success(`Submitted ${ratings.size} rating${ratings.size > 1 ? 's' : ''}!`)
      markSessionRated(session.id)
      setShowRatingModal(false)
    } catch (err) {
      console.error('Failed to submit ratings:', err)
      toast.error('Failed to submit ratings')
    } finally {
      setIsSavingRatings(false)
    }
  }

  const formatDuration = (durationSeconds: number | null | undefined) => {
    if (durationSeconds == null || durationSeconds < 0) return null
    if (durationSeconds < 60) return `${durationSeconds}s`
    const hours = Math.floor(durationSeconds / 3600)
    const minutes = Math.floor((durationSeconds % 3600) / 60)
    const seconds = durationSeconds % 60
    if (hours > 0) return seconds > 0 ? `${hours}h ${minutes}m ${seconds}s` : `${hours}h ${minutes}m`
    return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`
  }

  const getTotalDuration = () => {
    if (!session?.completed_at) return 'In progress'
    const startedAtMs = new Date(session.started_at).getTime()
    const completedAtMs = new Date(session.completed_at).getTime()
    if (Number.isNaN(startedAtMs) || Number.isNaN(completedAtMs)) return 'Unknown'
    const seconds = Math.max(0, Math.floor((completedAtMs - startedAtMs) / 1000))
    return formatDuration(seconds) || '0s'
  }

  const outcomeLabel = session?.outcome
    ? session.outcome === 'workaround'
      ? 'Workaround'
      : session.outcome.charAt(0).toUpperCase() + session.outcome.slice(1)
    : null

  if (isLoading) {
    return (
      <div className="flex h-64 items-center justify-center">
        <Spinner />
      </div>
    )
  }

  if (error || !session) {
    return (
      <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
        <div className="rounded-md border border-red-400/20 bg-red-400/10 p-4 text-red-400">
          {error || 'Session not found'}
        </div>
        <button
          onClick={() => navigate('/sessions')}
          className="mt-4 text-foreground hover:underline"
        >
          Back to sessions
        </button>
      </div>
    )
  }

  // Outcome display config
  const OUTCOME_CONFIG: Record<string, { icon: React.ReactNode; color: string; bg: string; border: string }> = {
    resolved: { icon: <CheckCircle2 className="h-5 w-5" />, color: 'text-emerald-400', bg: 'bg-emerald-500/10', border: 'border-emerald-500/20' },
    workaround: { icon: <AlertTriangle className="h-5 w-5" />, color: 'text-amber-400', bg: 'bg-amber-500/10', border: 'border-amber-500/20' },
    escalated: { icon: <ArrowUpRight className="h-5 w-5" />, color: 'text-red-400', bg: 'bg-red-500/10', border: 'border-red-500/20' },
    unresolved: { icon: <HelpCircle className="h-5 w-5" />, color: 'text-muted-foreground', bg: 'bg-muted', border: 'border-border' },
  }
  const outcomeConfig = session.outcome ? OUTCOME_CONFIG[session.outcome] : null

  return (
    <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
      {/* Back nav */}
      <button
        onClick={() => navigate('/sessions')}
        className="mb-4 text-sm text-muted-foreground hover:text-foreground"
      >
        ← Back to sessions
      </button>

      {/* Page title row */}
      <div className="mb-6 flex items-start justify-between gap-4">
        <div>
          <h1 className="text-2xl font-heading font-bold text-foreground sm:text-3xl">
            {session.ticket_number || 'Session Details'}
          </h1>
          <p className="mt-1 text-sm text-muted-foreground">
            {session.tree_snapshot?.name}
            {session.client_name && <> · Client: {session.client_name}</>}
            {' · '}{new Date(session.started_at).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })}
          </p>
        </div>
        <ActionMenu
          actions={[
            { label: 'Share', icon: Share2, onClick: () => setShowShareModal(true) },
            ...(session.completed_at ? [{ label: 'Save as Tree', icon: Save, onClick: () => setShowSaveAsTreeModal(true) }] as MenuAction[] : []),
          ]}
        />
      </div>

      {/* Session summary card */}
      {session.completed_at && outcomeConfig ? (
        <div className={cn('mb-6 rounded-xl border p-5', outcomeConfig.border, outcomeConfig.bg)}>
          <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
            <div className="flex items-start gap-3">
              <span className={outcomeConfig.color}>{outcomeConfig.icon}</span>
              <div>
                <div className="flex items-center gap-2">
                  <span className={cn('text-base font-semibold', outcomeConfig.color)}>{outcomeLabel}</span>
                  <span className="text-sm text-muted-foreground">· {getTotalDuration()}</span>
                </div>
                {session.outcome_notes && (
                  <p className="mt-1 text-sm text-muted-foreground">{session.outcome_notes}</p>
                )}
                {session.next_steps && (
                  <div className="mt-2">
                    <span className="font-label text-[0.6875rem] uppercase tracking-wide text-muted-foreground">Next Steps</span>
                    <p className="mt-0.5 text-sm text-muted-foreground whitespace-pre-wrap">{session.next_steps}</p>
                  </div>
                )}
              </div>
            </div>
            {/* Primary action: Copy for Ticket */}
            <button
              onClick={handleCopyForTicket}
              className="flex shrink-0 items-center gap-2 rounded-lg bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
            >
              {copiedPsa ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
              {copiedPsa ? 'Copied!' : 'Copy for Ticket'}
            </button>
          </div>
        </div>
      ) : !session.completed_at ? (
        /* In-progress banner */
        <div className="mb-6 flex items-center justify-between gap-4 rounded-xl border border-amber-500/20 bg-amber-500/5 px-5 py-4">
          <div className="flex items-center gap-3">
            <Flag className="h-4 w-4 shrink-0 text-amber-400" />
            <div>
              <p className="text-sm font-medium text-amber-300">Session in progress</p>
              <p className="text-xs text-muted-foreground">Set an outcome to finalize this session and generate documentation.</p>
            </div>
          </div>
          <button
            onClick={() => setShowOutcomeModal(true)}
            className="shrink-0 rounded-lg bg-gradient-brand px-4 py-2 text-sm font-medium text-white shadow-lg shadow-primary/20 hover:opacity-90"
          >
            Complete Session
          </button>
        </div>
      ) : null}

      {/* Export toolbar (secondary) */}
      <div className="mb-6 flex flex-wrap items-center gap-2">
        <select
          value={exportFormat}
          onChange={(e) => setExportFormat(e.target.value as typeof exportFormat)}
          aria-label="Export format"
          className="rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
        >
          <option value="markdown">Markdown</option>
          <option value="text">Plain Text</option>
          <option value="html">HTML</option>
          <option value="psa">PSA / Ticket Note</option>
        </select>
        {session.decisions.length > 1 && (
          <select
            value={maxStepIndex ?? ''}
            onChange={(e) => setMaxStepIndex(e.target.value ? Number(e.target.value) : null)}
            aria-label="Export through step"
            className="rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
          >
            <option value="">All steps</option>
            {session.decisions.map((_, idx) => (
              <option key={idx + 1} value={idx + 1}>Through step {idx + 1}</option>
            ))}
          </select>
        )}
        <select
          value={detailLevel}
          onChange={(e) => setDetailLevel(e.target.value as 'standard' | 'full')}
          aria-label="Detail level"
          className="rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
        >
          <option value="standard">Standard</option>
          <option value="full">Full Detail</option>
        </select>
        <button
          onClick={handleCopy}
          disabled={isExporting}
          title="Copy to clipboard"
          className="rounded-md border border-border bg-card p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50"
        >
          {copied ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
        </button>
        <button
          onClick={handlePreview}
          disabled={isExporting}
          className="flex items-center gap-1.5 rounded-md border border-border bg-card px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50"
        >
          <Eye className="h-4 w-4" />
          {isExporting ? 'Loading...' : 'Preview'}
        </button>
        {/* Copy for ticket (secondary position when session is complete) */}
        {session.completed_at && (
          <button
            onClick={handleCopyForTicket}
            className="flex items-center gap-1.5 rounded-md border border-border bg-card px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
          >
            {copiedPsa ? <Check className="h-4 w-4 text-emerald-400" /> : <Copy className="h-4 w-4" />}
            {copiedPsa ? 'Copied!' : 'Copy for Ticket'}
          </button>
        )}
      </div>

      {/* Timeline / Step Checklist */}
      <SessionTimeline
        decisions={session.decisions}
        treeType={(session.tree_snapshot as unknown as Record<string, unknown>).tree_type as string}
        startedAt={session.started_at}
        completedAt={session.completed_at}
      />

      {/* Export Preview Modal */}
      <ExportPreviewModal
        isOpen={showPreview}
        onClose={() => setShowPreview(false)}
        content={exportContent || ''}
        filename={getFilename()}
        format={exportFormat}
        onDownload={handleDownload}
        includeSummary={includeSummary}
        onToggleSummary={handleToggleSummary}
        redactionEnabled={redactionMode === 'mask'}
        onToggleRedaction={handleToggleRedaction}
        redactionSummary={redactionSummary}
      />

      {/* Save as Tree Modal */}
      <SaveSessionAsTreeModal
        isOpen={showSaveAsTreeModal}
        onClose={() => setShowSaveAsTreeModal(false)}
        onSave={handleSaveAsTree}
        defaultTreeName={getDefaultTreeName()}
        isSaving={isSavingTree}
      />

      {/* Step Rating Modal */}
      <StepRatingModal
        isOpen={showRatingModal}
        onClose={() => setShowRatingModal(false)}
        onSubmit={handleSubmitRatings}
        librarySteps={librarySteps}
        isSaving={isSavingRatings}
      />

      {/* Share Session Modal */}
      <ShareSessionModal
        sessionId={session.id}
        sessionLabel={session.ticket_number || 'Session Details'}
        isOpen={showShareModal}
        onClose={() => setShowShareModal(false)}
      />

      {/* Complete Session Modal (in-progress sessions) */}
      <SessionOutcomeModal
        isOpen={showOutcomeModal}
        onClose={() => setShowOutcomeModal(false)}
        onSubmit={handleCompleteSession}
        isSubmitting={isCompleting}
      />
    </div>
  )
}

export default SessionDetailPage
