import type { ComponentType } from 'react'
import { BookOpen, Building2, CalendarClock, FileText, Folder, FolderOpen, Image as ImageIcon, Pencil, UserRound } from 'lucide-react'
import type { CaseDocument, Evidence, EvidenceType, SourceFileType } from './types'
import { folderIsOpen } from './boardDomain'

export type ExhibitWidgetProps = {
  exhibit: Evidence
  documents: CaseDocument[]
  onOpenSource: (id: string) => void
  onToggleFolder: (id: string) => void
  onEditFolder: (id: string) => void
  onEditEvent: (id: string) => void
  onEditParty: (id: string) => void
}

export type ExhibitWidgetDefinition = {
  visualType: Exclude<EvidenceType, 'evidence'>
  heading: (exhibit: Evidence, documents: CaseDocument[]) => string
  connectionPoint: (exhibit: Evidence) => { x: number; y: number }
  Component: ComponentType<ExhibitWidgetProps>
}

function FolderWidget({ exhibit, documents, onOpenSource, onToggleFolder, onEditFolder }: ExhibitWidgetProps) {
  return <div className="card-content"><h3>{exhibit.title}</h3><p>{exhibit.content}</p>
    {!folderIsOpen(exhibit) && <div className="folder-documents">{documents.slice(0, 3).map(document => <button key={document.id} onClick={() => onOpenSource(document.id)} title={document.title}><FileText size={12}/><span>{document.title}</span>{(document.publishedAt || document.date) && <time>{(document.publishedAt || document.date).slice(0, 10)}</time>}</button>)}{documents.length > 3 && <small>+ {documents.length - 3} MORE FILES</small>}</div>}
    <div className="folder-actions"><button onClick={() => onToggleFolder(exhibit.id)}>{folderIsOpen(exhibit) ? <Folder size={12}/> : <FolderOpen size={12}/>} {folderIsOpen(exhibit) ? 'CLOSE' : 'OPEN'}</button><button onClick={() => onEditFolder(exhibit.id)}><Pencil size={12}/> EDIT</button></div>
  </div>
}

function StandardWidget({ exhibit, onOpenSource }: ExhibitWidgetProps) {
  return <div className="card-content"><h3>{exhibit.title}</h3><p>{exhibit.content}</p>
    {exhibit.eventDate && <time>{exhibit.eventDate.replaceAll('-', ' / ')}</time>}
    {exhibit.sourceDocumentId && <button onClick={() => onOpenSource(exhibit.sourceDocumentId!)}><BookOpen size={13}/> VIEW SOURCE</button>}
  </div>
}

function EventWidget({ exhibit, onEditEvent }: ExhibitWidgetProps) {
  const supportCount = exhibit.supportingEvidenceIds?.length || 0
  return <div className="card-content"><h3>{exhibit.title}</h3><p>{exhibit.content}</p>
    {exhibit.eventDate && <time>{new Date(exhibit.eventDate).toLocaleString()}</time>}
    <div className="event-actions"><span>{supportCount} SUPPORTING EXHIBIT{supportCount === 1 ? '' : 'S'}</span><button onClick={() => onEditEvent(exhibit.id)}><CalendarClock size={12}/> EDIT EVENT</button></div>
  </div>
}

function PartyWidget({ exhibit, onEditParty }: ExhibitWidgetProps) {
  const person = exhibit.partyKind === 'person'
  return <div className="card-content"><div className="party-identity">{person ? <UserRound size={28}/> : <Building2 size={28}/>}<div><h3>{exhibit.title}</h3><small>{person ? 'PERSON' : (exhibit.organizationKind || 'ORGANIZATION').replaceAll('_', ' ').toUpperCase()}</small></div></div>
    <p>{exhibit.content || 'No dossier summary yet.'}</p>
    {(exhibit.aliases?.length || 0) > 0 && <div className="party-aliases">AKA · {exhibit.aliases!.join(' · ')}</div>}
    <div className="event-actions"><span>{exhibit.relatedEvidenceIds?.length || 0} ASSOCIATED EXHIBITS</span><button onClick={() => onEditParty(exhibit.id)}><Pencil size={12}/> EDIT DOSSIER</button></div>
  </div>
}

const standardPoint = (exhibit: Evidence) => ({ x: exhibit.x + exhibit.width / 2, y: exhibit.y + 68 })
const folderDefinition: ExhibitWidgetDefinition = {
  visualType: 'folder', heading: (_exhibit, documents) => `EVIDENCE FOLDER / ${documents.length}`,
  connectionPoint: standardPoint, Component: FolderWidget,
}

export const exhibitWidgetRegistry: Record<EvidenceType, ExhibitWidgetDefinition> = {
  folder: folderDefinition,
  evidence: folderDefinition,
  note: { visualType: 'note', heading: () => 'INVESTIGATOR / NOTE', connectionPoint: exhibit => ({ x: exhibit.x + 54, y: exhibit.y + 12 }), Component: StandardWidget },
  event: { visualType: 'event', heading: () => 'EVENT / THIS HAPPENED', connectionPoint: standardPoint, Component: EventWidget },
  party: { visualType: 'party', heading: exhibit => exhibit.partyKind === 'person' ? 'PARTY / PERSON DOSSIER' : 'PARTY / ORGANIZATION DOSSIER', connectionPoint: standardPoint, Component: PartyWidget },
}

export function exhibitWidget(type: EvidenceType) {
  return exhibitWidgetRegistry[type] || exhibitWidgetRegistry.note
}

type DocumentWidgetProps = { document: CaseDocument; source: string }
export type DocumentWidgetDefinition = {
  label: string
  Preview: ComponentType<DocumentWidgetProps>
  Asset: ComponentType<DocumentWidgetProps>
}

function ImagePreview({ document, source }: DocumentWidgetProps) {
  return document.assetId ? <img draggable={false} src={source} alt=""/> : <GenericPreview document={document} source={source}/>
}
function GenericPreview({ document }: DocumentWidgetProps) {
  return <div><ImageIcon size={35}/><small>{document.kind}</small></div>
}
function ImageAsset({ document, source }: DocumentWidgetProps) {
  return <img className="document-image" src={source} alt={document.fileName || document.title}/>
}
function FrameAsset({ document, source }: DocumentWidgetProps) {
  return <iframe className="document-frame" src={source} title={document.fileName || document.title} sandbox="allow-same-origin"/>
}
function GenericAsset({ document, source }: DocumentWidgetProps) {
  return <div className="unsupported-file"><FileText size={42}/><b>{document.fileName || document.title}</b><span>{document.mimeType || 'Unknown file type'} · {document.fileSize ? `${Math.ceil(document.fileSize / 1024)} KB` : ''}</span><a href={source} download={document.fileName}>DOWNLOAD ORIGINAL</a></div>
}

const genericDocument = (label: string): DocumentWidgetDefinition => ({ label, Preview: GenericPreview, Asset: GenericAsset })
export const documentWidgetRegistry: Record<SourceFileType, DocumentWidgetDefinition> = {
  image: { label: 'Image', Preview: ImagePreview, Asset: ImageAsset },
  pdf: { label: 'PDF', Preview: GenericPreview, Asset: FrameAsset },
  text: { label: 'Text document', Preview: GenericPreview, Asset: FrameAsset },
  web_capture: genericDocument('Web capture'),
  email: genericDocument('Email'),
  article: genericDocument('Article'),
  filing: genericDocument('Company filing'),
  price_list: genericDocument('Price list'),
  file: genericDocument('Generic file'),
}

export function documentWidget(type: SourceFileType) {
  return documentWidgetRegistry[type] || documentWidgetRegistry.file
}
