import { formatFileSize } from '../utils/format';
import { formatDateTime as defaultFormatDateTime } from '../utils/date';

interface DocumentMetadata {
  page_count?: number | string | null;
}

interface DocumentVersion {
  size_bytes?: number | string | null;
  metadata?: DocumentMetadata | null;
}

interface TagEntry {
  label?: string | null;
}

interface CorrespondentEntry {
  name?: string | null;
}

export interface SummaryDocument {
  title?: string | null;
  original_name?: string | null;
  content_type?: string | null;
  current_version?: DocumentVersion | null;
  created_at?: string | null;
  updated_at?: string | null;
  issued_at?: string | null;
  folder_path?: string | null;
  tags?: TagEntry[] | null;
  correspondents?: CorrespondentEntry[] | null;
}

interface DescribeSummaryOptions {
  formatDateTime?: typeof defaultFormatDateTime;
}

export interface DocumentSummaryRow {
  key: string;
  label: string;
  value: string | null | undefined;
}

export interface DocumentSummary {
  title: string | undefined;
  originalName: string | null | undefined;
  mimeTypeLabel: string;
  sizeLabel: string;
  createdAtLabel: string;
  issuedLabel: string;
  updatedAtLabel: string;
  pageCount: number | null;
  pageCountLabel: string;
  folderLabel: string | null | undefined;
  tags: TagEntry[];
  correspondents: CorrespondentEntry[];
  tagsSummary: string;
  correspondentsSummary: string;
  summaryRows: DocumentSummaryRow[];
}

const coercePageCount = (metadata: DocumentMetadata | null | undefined): number | null => {
  const raw = metadata?.page_count;
  if (typeof raw === 'number') {
    return Number.isFinite(raw) && raw >= 0 ? raw : null;
  }
  if (raw != null && raw !== '') {
    const parsed = Number.parseInt(String(raw), 10);
    if (Number.isFinite(parsed) && parsed >= 0) {
      return parsed;
    }
  }
  return null;
};

const sanitizeArray = <T>(entries: (T | null | undefined)[] | null | undefined): T[] =>
  Array.isArray(entries) ? entries.filter(Boolean) as T[] : [];

export const describeDocumentSummary = (document?: SummaryDocument | null, options: DescribeSummaryOptions = {}): DocumentSummary => {
  const {
    formatDateTime = defaultFormatDateTime,
  } = options;

  if (!document) {
    return {
      title: '',
      originalName: '',
      mimeTypeLabel: '—',
      sizeLabel: '—',
      createdAtLabel: '—',
      issuedLabel: '—',
      updatedAtLabel: '—',
      pageCount: null,
      pageCountLabel: '—',
      folderLabel: null,
      tags: [],
      correspondents: [],
      tagsSummary: '—',
      correspondentsSummary: '—',
      summaryRows: [],
    };
  }

  const originalName = document.original_name;
  const mimeTypeLabel = document.content_type || 'Unknown';

  const sizeBytes = Number(document.current_version?.size_bytes);
  const sizeLabel = Number.isFinite(sizeBytes) && sizeBytes > 0 ? formatFileSize(sizeBytes) : '—';

  const metadata = document.current_version?.metadata || null;
  const pageCount = coercePageCount(metadata);
  const pageCountLabel = Number.isFinite(pageCount) ? String(pageCount) : '—';

  const createdAtLabel = formatDateTime(document.created_at);
  const issuedLabel = formatDateTime(document.issued_at);
  const updatedAtLabel = formatDateTime(document.updated_at);

  const folderLabel = document.folder_path;

  const tags = sanitizeArray<TagEntry>(document.tags);
  const correspondents = sanitizeArray<CorrespondentEntry>(document.correspondents);

  const tagLabels = tags.map((tag) => tag.label).filter(Boolean) as string[];
  const correspondentLabels = correspondents.map((entry) => entry.name).filter(Boolean) as string[];

  const tagsSummary = tagLabels.length ? tagLabels.join(', ') : '—';
  const correspondentsSummary = correspondentLabels.length
    ? correspondentLabels.join(', ')
    : '—';

  const summaryRows: DocumentSummaryRow[] = [
    { key: 'created', label: 'Created', value: createdAtLabel },
    { key: 'size', label: 'Size', value: sizeLabel },
    { key: 'type', label: 'Type', value: mimeTypeLabel },
    { key: 'issued', label: 'Issued', value: issuedLabel },
    { key: 'pages', label: 'Pages', value: pageCountLabel },
    { key: 'updated', label: 'Updated', value: updatedAtLabel },
    { key: 'folder', label: 'Folder', value: folderLabel },
    { key: 'tags', label: 'Tags', value: tagsSummary },
    { key: 'correspondents', label: 'Correspondents', value: correspondentsSummary },
  ];

  return {
    title: document.title,
    originalName,
    mimeTypeLabel,
    sizeLabel,
    createdAtLabel,
    issuedLabel,
    updatedAtLabel,
    pageCount,
    pageCountLabel,
    folderLabel,
    tags,
    correspondents,
    tagsSummary,
    correspondentsSummary,
    summaryRows,
  };
};
