import { IsString, IsOptional, IsNumber, IsArray, IsDateString, IsEnum, IsBoolean, ValidateNested } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';

/**
 * ecoDMS API Types and DTOs
 *
 * ecoDMS is a document management system with session-based authentication.
 * API Documentation: https://www.ecodms.de/index.php/en/ecodms-api
 */

// ============ Enums ============

export enum DocumentStatus {
  ARCHIVED = 'archived',
  DELETED = 'deleted',
  PENDING = 'pending',
}

export enum SearchOperator {
  AND = 'and',
  OR = 'or',
}

export enum SortOrder {
  ASC = 'asc',
  DESC = 'desc',
}

// ============ API Response Types ============

export interface EcoDmsSession {
  sessionId: string;
  userId: number;
  userName: string;
  validUntil: string;
}

export interface EcoDmsDocument {
  id: number;
  docId: string;
  version: number;
  title: string;
  fileName: string;
  fileExtension: string;
  fileSize: number;
  mimeType: string;
  createdAt: string;
  modifiedAt: string;
  archivedAt: string;
  classifyId: number;
  classifyName: string;
  folderId: number | null;
  folderPath: string | null;
  status: DocumentStatus;
  checksum: string;
  pageCount: number;
  ocrText: string | null;
  attributes: EcoDmsAttribute[];
  links: EcoDmsDocumentLink[];
}

export interface EcoDmsAttribute {
  id: number;
  name: string;
  value: string | number | boolean | null;
  type: 'text' | 'number' | 'date' | 'boolean' | 'list';
  required: boolean;
}

export interface EcoDmsDocumentLink {
  id: number;
  targetDocId: string;
  linkType: string;
  description: string | null;
}

export interface EcoDmsFolder {
  id: number;
  name: string;
  parentId: number | null;
  path: string;
  children: EcoDmsFolder[];
  documentCount: number;
  createdAt: string;
  modifiedAt: string;
}

export interface EcoDmsClassification {
  id: number;
  name: string;
  description: string | null;
  parentId: number | null;
  attributes: EcoDmsClassificationAttribute[];
  isActive: boolean;
}

export interface EcoDmsClassificationAttribute {
  id: number;
  name: string;
  type: 'text' | 'number' | 'date' | 'boolean' | 'list';
  required: boolean;
  defaultValue: string | null;
  listValues: string[] | null;
  sortOrder: number;
}

export interface EcoDmsSearchResult {
  documents: EcoDmsDocument[];
  totalCount: number;
  page: number;
  pageSize: number;
  searchTime: number;
}

export interface EcoDmsApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
  };
}

// ============ DTOs ============

export class SearchDocumentsDto {
  @ApiPropertyOptional({ description: 'Full-text search query' })
  @IsOptional()
  @IsString()
  query?: string;

  @ApiPropertyOptional({ description: 'Classification ID to filter by' })
  @IsOptional()
  @IsNumber()
  classifyId?: number;

  @ApiPropertyOptional({ description: 'Folder ID to filter by' })
  @IsOptional()
  @IsNumber()
  folderId?: number;

  @ApiPropertyOptional({ description: 'Date from filter (YYYY-MM-DD)' })
  @IsOptional()
  @IsDateString()
  dateFrom?: string;

  @ApiPropertyOptional({ description: 'Date to filter (YYYY-MM-DD)' })
  @IsOptional()
  @IsDateString()
  dateTo?: string;

  @ApiPropertyOptional({ description: 'File extension filter (e.g., pdf, docx)' })
  @IsOptional()
  @IsString()
  fileExtension?: string;

  @ApiPropertyOptional({ description: 'Attribute filters', type: 'object' })
  @IsOptional()
  attributes?: Record<string, string | number | boolean>;

  @ApiPropertyOptional({ description: 'Search operator for multiple criteria', enum: SearchOperator })
  @IsOptional()
  @IsEnum(SearchOperator)
  operator?: SearchOperator;

  @ApiPropertyOptional({ description: 'Sort field', default: 'modifiedAt' })
  @IsOptional()
  @IsString()
  sortBy?: string;

  @ApiPropertyOptional({ description: 'Sort order', enum: SortOrder, default: SortOrder.DESC })
  @IsOptional()
  @IsEnum(SortOrder)
  sortOrder?: SortOrder;

  @ApiPropertyOptional({ description: 'Page number', default: 1 })
  @IsOptional()
  @IsNumber()
  page?: number;

  @ApiPropertyOptional({ description: 'Items per page', default: 50 })
  @IsOptional()
  @IsNumber()
  pageSize?: number;
}

export class UploadDocumentDto {
  @ApiProperty({ description: 'Document title' })
  @IsString()
  title: string;

  @ApiProperty({ description: 'Classification ID' })
  @IsNumber()
  classifyId: number;

  @ApiPropertyOptional({ description: 'Folder ID (optional)' })
  @IsOptional()
  @IsNumber()
  folderId?: number;

  @ApiPropertyOptional({ description: 'Document attributes', type: 'object' })
  @IsOptional()
  attributes?: Record<string, string | number | boolean>;

  @ApiPropertyOptional({ description: 'Custom file name (without extension)' })
  @IsOptional()
  @IsString()
  fileName?: string;

  @ApiPropertyOptional({ description: 'Document date (YYYY-MM-DD)' })
  @IsOptional()
  @IsDateString()
  documentDate?: string;

  @ApiPropertyOptional({ description: 'Enable OCR processing', default: true })
  @IsOptional()
  @IsBoolean()
  enableOcr?: boolean;
}

export class UpdateDocumentDto {
  @ApiPropertyOptional({ description: 'Document title' })
  @IsOptional()
  @IsString()
  title?: string;

  @ApiPropertyOptional({ description: 'Classification ID' })
  @IsOptional()
  @IsNumber()
  classifyId?: number;

  @ApiPropertyOptional({ description: 'Folder ID' })
  @IsOptional()
  @IsNumber()
  folderId?: number;

  @ApiPropertyOptional({ description: 'Document attributes', type: 'object' })
  @IsOptional()
  attributes?: Record<string, string | number | boolean>;
}

export class CreateFolderDto {
  @ApiProperty({ description: 'Folder name' })
  @IsString()
  name: string;

  @ApiPropertyOptional({ description: 'Parent folder ID (null for root)' })
  @IsOptional()
  @IsNumber()
  parentId?: number;
}

export class ListDocumentsDto {
  @ApiPropertyOptional({ description: 'Folder ID to list documents from' })
  @IsOptional()
  @IsNumber()
  folderId?: number;

  @ApiPropertyOptional({ description: 'Classification ID to filter by' })
  @IsOptional()
  @IsNumber()
  classifyId?: number;

  @ApiPropertyOptional({ description: 'Include documents from subfolders', default: false })
  @IsOptional()
  @IsBoolean()
  recursive?: boolean;

  @ApiPropertyOptional({ description: 'Sort field', default: 'modifiedAt' })
  @IsOptional()
  @IsString()
  sortBy?: string;

  @ApiPropertyOptional({ description: 'Sort order', enum: SortOrder })
  @IsOptional()
  @IsEnum(SortOrder)
  sortOrder?: SortOrder;

  @ApiPropertyOptional({ description: 'Page number', default: 1 })
  @IsOptional()
  @IsNumber()
  page?: number;

  @ApiPropertyOptional({ description: 'Items per page', default: 50 })
  @IsOptional()
  @IsNumber()
  pageSize?: number;
}

// ============ Response DTOs ============

export class DocumentResponseDto {
  @ApiProperty()
  id: number;

  @ApiProperty()
  docId: string;

  @ApiProperty()
  version: number;

  @ApiProperty()
  title: string;

  @ApiProperty()
  fileName: string;

  @ApiProperty()
  fileExtension: string;

  @ApiProperty()
  fileSize: number;

  @ApiProperty()
  mimeType: string;

  @ApiProperty()
  createdAt: string;

  @ApiProperty()
  modifiedAt: string;

  @ApiProperty()
  classifyId: number;

  @ApiProperty()
  classifyName: string;

  @ApiPropertyOptional()
  folderId?: number;

  @ApiPropertyOptional()
  folderPath?: string;

  @ApiProperty()
  pageCount: number;

  @ApiPropertyOptional({ type: [Object] })
  attributes?: EcoDmsAttribute[];
}

export class FolderResponseDto {
  @ApiProperty()
  id: number;

  @ApiProperty()
  name: string;

  @ApiPropertyOptional()
  parentId?: number;

  @ApiProperty()
  path: string;

  @ApiProperty()
  documentCount: number;

  @ApiPropertyOptional({ type: [FolderResponseDto] })
  children?: FolderResponseDto[];
}

export class ClassificationResponseDto {
  @ApiProperty()
  id: number;

  @ApiProperty()
  name: string;

  @ApiPropertyOptional()
  description?: string;

  @ApiPropertyOptional()
  parentId?: number;

  @ApiProperty()
  isActive: boolean;

  @ApiPropertyOptional({ type: [Object] })
  attributes?: EcoDmsClassificationAttribute[];
}

export class SearchResultResponseDto {
  @ApiProperty({ type: [DocumentResponseDto] })
  documents: DocumentResponseDto[];

  @ApiProperty()
  totalCount: number;

  @ApiProperty()
  page: number;

  @ApiProperty()
  pageSize: number;

  @ApiProperty()
  totalPages: number;

  @ApiProperty()
  searchTime: number;
}
