import type { Template } from '@pdfme/common';
import type {
  DocumentTemplateMappingWithColumns,
  ResolvedDocumentTemplate,
} from '@/features/foundation/document-template/types';
import type { QuotationDocumentData } from '../types';

export type SectionRole =
  | 'customer'
  | 'product_items'
  | 'topics'
  | 'conditions'
  | 'signature'
  | 'attachments'
  | 'appendix'
  | 'warranty'
  | 'cover'
  | 'unknown';

export type PageResolutionStrategy =
  | 'explicit_marker'
  | 'legacy_inference'
  | 'fallback';

export type RuntimeIssueCode =
  | 'MISSING_MARKER'
  | 'DUPLICATE_MARKER'
  | 'INVALID_TEMPLATE'
  | 'MISSING_MAPPING'
  | 'EMPTY_OPTIONAL_SECTION'
  | 'EMPTY_REQUIRED_SECTION'
  | 'LEGACY_COMPAT_MODE'
  | 'INVALID_PRODUCT_ITEM_QUANTITY'
  | 'INVALID_PRODUCT_ITEM_PRICE'
  | 'MISSING_PRODUCT_ITEM_DESCRIPTION'
  | 'INVALID_PRODUCT_ITEM_TOTAL';

export interface RuntimeIssue {
  code: RuntimeIssueCode;
  severity: 'warning' | 'error';
  message: string;
  details?: Record<string, unknown>;
}

export interface ResolvedTemplate {
  documentTemplate: ResolvedDocumentTemplate;
  schema: Template;
}

export interface CompatibleTemplatePage {
  pageIndex: number;
  primaryRole: SectionRole;
  roles: SectionRole[];
  strategy: PageResolutionStrategy;
  schema: Template['schemas'][number];
}

export interface CompatibleTemplate {
  template: ResolvedTemplate;
  pages: CompatibleTemplatePage[];
  issues: RuntimeIssue[];
}

export interface ResolvedPage extends CompatibleTemplatePage {}

export interface ResolvedPages {
  all: ResolvedPage[];
  byRole: Partial<Record<SectionRole, ResolvedPage[]>>;
  issues: RuntimeIssue[];
}

export interface RenderPolicy {
  section: SectionRole;
  enabled: boolean;
  required: boolean;
  visibleWhenEmpty: boolean;
}

export interface BuiltSection<TRole extends SectionRole = SectionRole> {
  role: TRole;
  enabled: boolean;
  rendered: boolean;
  anchorPageIndex: number | null;
  pages: Template['schemas'];
  templateInputPatch: Record<string, unknown>;
  issues: RuntimeIssue[];
}

export type PdfmeTableAlignment = 'left' | 'center' | 'right';

export interface PdfmeTableModel {
  headers: string[];
  rows: string[][];
  columnWidths: number[];
  alignments: PdfmeTableAlignment[];
}

export interface ProductItemRow {
  sourceItemId: string;
  rowIndex: number;
  item: string;
  description: string;
  quantity: string;
  unit: string;
  unitPrice: string;
  discount: string;
  total: string;
  estimatedLineCount: number;
  estimatedRowHeight: number;
  raw: {
    itemNumber: number | null;
    quantity: number | null;
    unitPrice: number | null;
    discount: number | null;
    total: number | null;
  };
}

export interface PaginationModel {
  rowCount: number;
  estimatedPages: number;
  rowsPerPage: number[];
  headerRows: number;
  footerRows: number;
  repeatHeader: boolean;
  orphanRowThreshold: number;
  availableContentHeight: number;
  pageBreakIndices: number[];
}

export interface ProductItemSection
  extends BuiltSection<'product_items'> {
  rows: ProductItemRow[];
  tableModel: PdfmeTableModel;
  pagination: PaginationModel;
}

export interface RenderContext {
  documentData: QuotationDocumentData;
  template: ResolvedTemplate;
  mappings: DocumentTemplateMappingWithColumns[];
  pages: ResolvedPages;
  policies: RenderPolicy[];
  policyBySection: Map<SectionRole, RenderPolicy>;
  issues: RuntimeIssue[];
}

export interface SectionBuilder {
  role: SectionRole;
  build(context: RenderContext): BuiltSection | Promise<BuiltSection>;
}

export interface AssembledTemplate {
  template: Template;
  templateInput: Record<string, unknown>;
  issues: RuntimeIssue[];
}

export interface QuotationPdfRuntimeResult {
  assembled: AssembledTemplate;
  topicInputs: Record<string, string[][]>;
  issues: RuntimeIssue[];
  pages: ResolvedPages;
  policies: RenderPolicy[];
}

export const SECTION_ORDER: SectionRole[] = [
  'customer',
  'product_items',
  'topics',
  'conditions',
  'signature',
  'attachments',
  'appendix',
  'warranty',
  'cover',
];

export const SINGLETON_SECTION_ROLES = new Set<SectionRole>([
  'customer',
  'product_items',
  'topics',
  'conditions',
  'signature',
  'warranty',
  'cover',
]);
