import { useState, useRef } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { queryOptions } from '@tanstack/react-query'
import { repairNoteListOptions, repairNoteMutations, repairNoteKeys } from '@/api/repairs'
import { api } from '@/lib/api-client'
import { useAuthStore } from '@/stores/auth.store'
import { Button } from '@/components/ui/button'
import { Textarea } from '@/components/ui/textarea'
import { Badge } from '@/components/ui/badge'
import { Send, Trash2, Eye, Lock, ImageIcon, X } from 'lucide-react'
import { toast } from 'sonner'
import { useEffect } from 'react'
import type { RepairNote } from '@/types/repair'

const STATUS_LABELS: Record<string, string> = {
  in_transit: 'In Transit',
  intake: 'Intake',
  diagnosing: 'Diagnosing',
  pending_approval: 'Pending Approval',
  approved: 'Approved',
  in_progress: 'In Progress',
  pending_parts: 'Pending Parts',
  ready: 'Ready',
  picked_up: 'Picked Up',
  delivered: 'Delivered',
  cancelled: 'Cancelled',
}

interface FileRecord {
  id: string
  path: string
  filename: string
}

function noteFilesOptions(noteId: string) {
  return queryOptions({
    queryKey: ['files', 'repair_note', noteId],
    queryFn: () => api.get<{ data: FileRecord[] }>('/v1/files', { entityType: 'repair_note', entityId: noteId }),
    enabled: !!noteId,
  })
}

async function openSignedFile(fileId: string) {
  try {
    const res = await api.get<{ url: string }>(`/v1/files/signed-url/${fileId}`)
    window.open(res.url, '_blank')
  } catch {
    toast.error('Failed to open file')
  }
}

/** Image component that fetches via authenticated request and displays as blob */
function AuthImage({ path, alt, className, onClick }: { path: string; alt: string; className?: string; onClick?: () => void }) {
  const token = useAuthStore((s) => s.token)
  const [src, setSrc] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false
    let blobUrl: string | null = null
    async function load() {
      try {
        const res = await fetch(`/v1/files/serve/${path}`, {
          headers: token ? { Authorization: `Bearer ${token}` } : {},
        })
        if (!res.ok || cancelled) return
        const blob = await res.blob()
        if (!cancelled) {
          blobUrl = URL.createObjectURL(blob)
          setSrc(blobUrl)
        }
      } catch { /* ignore */ }
    }
    load()
    return () => {
      cancelled = true
      if (blobUrl) URL.revokeObjectURL(blobUrl)
    }
  }, [path, token])

  if (!src) return <div className={`${className} bg-muted animate-pulse`} />
  return <img src={src} alt={alt} className={className} onClick={onClick} />
}

interface TicketNotesProps {
  ticketId: string
}

export function TicketNotes({ ticketId }: TicketNotesProps) {
  const queryClient = useQueryClient()
  const hasPermission = useAuthStore((s) => s.hasPermission)
  const token = useAuthStore((s) => s.token)
  const [content, setContent] = useState('')
  const [visibility, setVisibility] = useState<'internal' | 'customer'>('internal')
  const [photos, setPhotos] = useState<File[]>([])
  const [posting, setPosting] = useState(false)
  const photoInputRef = useRef<HTMLInputElement>(null)

  const { data } = useQuery(repairNoteListOptions(ticketId))
  const notes = data?.data ?? []

  const deleteMutation = useMutation({
    mutationFn: repairNoteMutations.delete,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: repairNoteKeys.all(ticketId) })
      toast.success('Note removed')
    },
    onError: (err) => toast.error(err.message),
  })

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!content.trim()) return
    setPosting(true)

    try {
      // Create the note
      const note = await repairNoteMutations.create(ticketId, { content: content.trim(), visibility })

      // Upload attached photos to the note
      let uploadFailures = 0
      for (const photo of photos) {
        const formData = new FormData()
        formData.append('entityType', 'repair_note')
        formData.append('entityId', note.id)
        formData.append('category', 'attachment')
        formData.append('file', photo)
        const uploadRes = await fetch('/v1/files', {
          method: 'POST',
          headers: { Authorization: `Bearer ${token}` },
          body: formData,
        })
        if (!uploadRes.ok) {
          uploadFailures++
          const err = await uploadRes.json().catch(() => ({}))
          console.error('Photo upload failed:', err)
        }
      }

      queryClient.invalidateQueries({ queryKey: repairNoteKeys.all(ticketId) })
      setContent('')
      setPhotos([])
      if (uploadFailures > 0) {
        toast.error(`Note added but ${uploadFailures} photo(s) failed to upload`)
      } else {
        toast.success(photos.length > 0 ? `Note added with ${photos.length} photo(s)` : 'Note added')
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to post note')
    } finally {
      setPosting(false)
    }
  }

  function addPhotos(e: React.ChangeEvent<HTMLInputElement>) {
    const files = Array.from(e.target.files ?? [])
    setPhotos((prev) => [...prev, ...files])
    e.target.value = ''
  }

  function removePhoto(index: number) {
    setPhotos((prev) => prev.filter((_, i) => i !== index))
  }

  function formatDate(dateStr: string) {
    const d = new Date(dateStr)
    return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' }) +
      ' ' + d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' })
  }

  return (
    <div className="space-y-4">
      {/* Add note form */}
      {hasPermission('repairs.edit') && (
        <form onSubmit={handleSubmit} className="space-y-2">
          <Textarea
            value={content}
            onChange={(e) => setContent(e.target.value)}
            placeholder="Add a note..."
            rows={3}
          />

          {/* Photo previews */}
          {photos.length > 0 && (
            <div className="flex flex-wrap gap-2">
              {photos.map((photo, i) => (
                <div key={i} className="relative group">
                  <img src={URL.createObjectURL(photo)} alt="" className="h-16 w-16 object-cover rounded-md border" />
                  <button
                    type="button"
                    className="absolute -top-1.5 -right-1.5 h-4 w-4 rounded-full bg-destructive text-destructive-foreground flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
                    onClick={() => removePhoto(i)}
                  >
                    <X className="h-2.5 w-2.5" />
                  </button>
                </div>
              ))}
            </div>
          )}

          <div className="flex items-center justify-between">
            <div className="flex gap-1">
              <button
                type="button"
                onClick={() => setVisibility('internal')}
                className={`flex items-center gap-1 px-2.5 py-1 rounded-md text-xs font-medium border transition-colors ${
                  visibility === 'internal' ? 'bg-primary text-primary-foreground border-primary' : 'bg-background text-muted-foreground border-border'
                }`}
              >
                <Lock className="h-3 w-3" />Internal
              </button>
              <button
                type="button"
                onClick={() => setVisibility('customer')}
                className={`flex items-center gap-1 px-2.5 py-1 rounded-md text-xs font-medium border transition-colors ${
                  visibility === 'customer' ? 'bg-primary text-primary-foreground border-primary' : 'bg-background text-muted-foreground border-border'
                }`}
              >
                <Eye className="h-3 w-3" />Customer Visible
              </button>
              <button
                type="button"
                onClick={() => photoInputRef.current?.click()}
                className="flex items-center gap-1 px-2.5 py-1 rounded-md text-xs font-medium border border-border text-muted-foreground hover:border-primary hover:text-primary transition-colors"
              >
                <ImageIcon className="h-3 w-3" />Attach Photo
              </button>
            </div>
            <Button type="submit" size="sm" disabled={posting || !content.trim()}>
              <Send className="mr-1 h-3 w-3" />
              {posting ? 'Posting...' : 'Post Note'}
            </Button>
          </div>

          <input
            ref={photoInputRef}
            type="file"
            accept="image/jpeg,image/png,image/webp"
            multiple
            className="hidden"
            onChange={addPhotos}
          />
        </form>
      )}

      {/* Notes feed */}
      {notes.length === 0 ? (
        <p className="text-sm text-muted-foreground text-center py-4">No notes yet</p>
      ) : (
        <div className="space-y-3">
          {[...notes].reverse().map((note) => (
            <NoteEntry
              key={note.id}
              note={note}
              formatDate={formatDate}
              canDelete={hasPermission('repairs.admin')}
              onDelete={() => deleteMutation.mutate(note.id)}
            />
          ))}
        </div>
      )}
    </div>
  )
}

function NoteEntry({ note, formatDate, canDelete, onDelete }: {
  note: RepairNote
  formatDate: (d: string) => string
  canDelete: boolean
  onDelete: () => void
}) {
  const { data: filesData } = useQuery(noteFilesOptions(note.id))
  const photos = filesData?.data ?? []

  return (
    <div className={`rounded-md border p-3 ${note.visibility === 'customer' ? 'border-blue-300/50 bg-blue-50/30 dark:border-blue-800/50 dark:bg-blue-950/20' : ''}`}>
      <div className="flex items-start justify-between gap-2">
        <div className="flex items-center gap-2 text-xs text-muted-foreground flex-wrap">
          <span className="font-semibold text-foreground">{note.authorName}</span>
          <span>{formatDate(note.createdAt)}</span>
          {note.ticketStatus && (
            <Badge variant="outline" className="text-[10px] px-1.5 py-0">
              {STATUS_LABELS[note.ticketStatus] ?? note.ticketStatus}
            </Badge>
          )}
          {note.visibility === 'customer' && (
            <Badge variant="secondary" className="text-[10px] px-1.5 py-0 gap-0.5">
              <Eye className="h-2.5 w-2.5" />Customer
            </Badge>
          )}
          {note.visibility === 'internal' && (
            <Badge variant="outline" className="text-[10px] px-1.5 py-0 gap-0.5">
              <Lock className="h-2.5 w-2.5" />Internal
            </Badge>
          )}
        </div>
        {canDelete && (
          <Button variant="ghost" size="sm" className="h-6 w-6 p-0" onClick={onDelete}>
            <Trash2 className="h-3 w-3 text-destructive" />
          </Button>
        )}
      </div>
      <p className="text-sm mt-1.5 whitespace-pre-wrap">{note.content}</p>

      {/* Inline photos */}
      {photos.length > 0 && (
        <div className="flex flex-wrap gap-2 mt-2">
          {photos.map((photo) => (
            <button key={photo.id} type="button" onClick={() => openSignedFile(photo.id)}>
              <AuthImage
                path={photo.path}
                alt={photo.filename}
                className="h-24 w-24 object-cover rounded-md border cursor-pointer hover:opacity-80 transition-opacity"
              />
            </button>
          ))}
        </div>
      )}
    </div>
  )
}
