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

/**
 * Nextcloud API Types and DTOs
 */

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

export enum ShareType {
  USER = 0,
  GROUP = 1,
  PUBLIC_LINK = 3,
  EMAIL = 4,
  FEDERATED_CLOUD = 6,
  CIRCLE = 7,
  TALK_CONVERSATION = 10,
}

export enum SharePermission {
  READ = 1,
  UPDATE = 2,
  CREATE = 4,
  DELETE = 8,
  SHARE = 16,
  ALL = 31,
}

export enum FileType {
  FILE = 'file',
  DIRECTORY = 'directory',
}

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

export interface NextcloudFile {
  basename: string;
  filename: string;
  fileid: number;
  type: FileType;
  mime: string | null;
  size: number;
  etag: string;
  lastmod: string;
  permissions: string;
  favorite: boolean;
  hasPreview: boolean;
  path: string;
}

export interface NextcloudQuota {
  free: number;
  used: number;
  total: number;
  relative: number;
}

export interface NextcloudUser {
  id: string;
  displayName: string;
  email: string;
  quota: NextcloudQuota;
  enabled: boolean;
  lastLogin: number;
  groups: string[];
}

export interface NextcloudShare {
  id: number;
  shareType: ShareType;
  shareWith: string | null;
  shareWithDisplayname: string | null;
  permissions: number;
  url: string | null;
  token: string | null;
  path: string;
  itemType: FileType;
  expiration: string | null;
  password: boolean;
  note: string | null;
}

export interface NextcloudCalendarEvent {
  id: string;
  calendarId: string;
  summary: string;
  description: string | null;
  location: string | null;
  start: string;
  end: string;
  allDay: boolean;
  status: string;
  rrule: string | null;
  attendees: NextcloudAttendee[];
  organizer: NextcloudAttendee | null;
  created: string;
  lastModified: string;
}

export interface NextcloudAttendee {
  email: string;
  name: string | null;
  status: string;
  role: string;
}

export interface NextcloudCalendar {
  id: string;
  displayName: string;
  color: string;
  owner: string;
  permissions: string[];
  isWritable: boolean;
  isShared: boolean;
}

export interface WebDAVResponse {
  href: string;
  propstat: {
    prop: {
      resourcetype?: { collection?: unknown };
      getcontentlength?: string;
      getcontenttype?: string;
      getetag?: string;
      getlastmodified?: string;
      displayname?: string;
      fileid?: number;
      permissions?: string;
      favorite?: number;
      'has-preview'?: boolean;
    };
    status: string;
  }[];
}

export interface OCSResponse<T> {
  ocs: {
    meta: {
      status: string;
      statuscode: number;
      message: string;
      totalitems?: string;
      itemsperpage?: string;
    };
    data: T;
  };
}

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

export class ListFilesDto {
  @ApiPropertyOptional({ description: 'Path to list files from (default: root)', default: '/' })
  @IsOptional()
  @IsString()
  path?: string;

  @ApiPropertyOptional({ description: 'Include only files (exclude directories)' })
  @IsOptional()
  @IsBoolean()
  filesOnly?: boolean;

  @ApiPropertyOptional({ description: 'Include only directories' })
  @IsOptional()
  @IsBoolean()
  dirsOnly?: boolean;

  @ApiPropertyOptional({ description: 'Depth of listing (0=current only, 1=immediate children, infinity=all)' })
  @IsOptional()
  @IsNumber()
  depth?: number;
}

export class UploadFileDto {
  @ApiProperty({ description: 'Destination path including filename' })
  @IsString()
  path: string;

  @ApiPropertyOptional({ description: 'Overwrite existing file', default: false })
  @IsOptional()
  @IsBoolean()
  overwrite?: boolean;
}

export class CreateFolderDto {
  @ApiProperty({ description: 'Path of the new folder' })
  @IsString()
  path: string;
}

export class MoveFileDto {
  @ApiProperty({ description: 'Source path' })
  @IsString()
  source: string;

  @ApiProperty({ description: 'Destination path' })
  @IsString()
  destination: string;

  @ApiPropertyOptional({ description: 'Overwrite if exists', default: false })
  @IsOptional()
  @IsBoolean()
  overwrite?: boolean;
}

export class CopyFileDto {
  @ApiProperty({ description: 'Source path' })
  @IsString()
  source: string;

  @ApiProperty({ description: 'Destination path' })
  @IsString()
  destination: string;

  @ApiPropertyOptional({ description: 'Overwrite if exists', default: false })
  @IsOptional()
  @IsBoolean()
  overwrite?: boolean;
}

export class CreateShareDto {
  @ApiProperty({ description: 'Path to share' })
  @IsString()
  path: string;

  @ApiProperty({ description: 'Share type', enum: ShareType })
  @IsEnum(ShareType)
  shareType: ShareType;

  @ApiPropertyOptional({ description: 'User/group ID or email to share with' })
  @IsOptional()
  @IsString()
  shareWith?: string;

  @ApiPropertyOptional({ description: 'Permissions (bitmask)', default: SharePermission.READ })
  @IsOptional()
  @IsNumber()
  permissions?: number;

  @ApiPropertyOptional({ description: 'Password for public link' })
  @IsOptional()
  @IsString()
  password?: string;

  @ApiPropertyOptional({ description: 'Expiration date (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  expireDate?: string;

  @ApiPropertyOptional({ description: 'Note for the share' })
  @IsOptional()
  @IsString()
  note?: string;
}

export class ListEventsDto {
  @ApiPropertyOptional({ description: 'Calendar ID (default: personal)' })
  @IsOptional()
  @IsString()
  calendarId?: string;

  @ApiPropertyOptional({ description: 'Start date filter (ISO 8601)' })
  @IsOptional()
  @IsDateString()
  start?: string;

  @ApiPropertyOptional({ description: 'End date filter (ISO 8601)' })
  @IsOptional()
  @IsDateString()
  end?: string;
}

export class CreateEventDto {
  @ApiProperty({ description: 'Calendar ID' })
  @IsString()
  calendarId: string;

  @ApiProperty({ description: 'Event summary/title' })
  @IsString()
  summary: string;

  @ApiPropertyOptional({ description: 'Event description' })
  @IsOptional()
  @IsString()
  description?: string;

  @ApiPropertyOptional({ description: 'Event location' })
  @IsOptional()
  @IsString()
  location?: string;

  @ApiProperty({ description: 'Start date/time (ISO 8601)' })
  @IsDateString()
  start: string;

  @ApiProperty({ description: 'End date/time (ISO 8601)' })
  @IsDateString()
  end: string;

  @ApiPropertyOptional({ description: 'All-day event', default: false })
  @IsOptional()
  @IsBoolean()
  allDay?: boolean;

  @ApiPropertyOptional({ description: 'Attendee emails', type: [String] })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  attendees?: string[];
}

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

export class FileResponseDto {
  @ApiProperty()
  basename: string;

  @ApiProperty()
  filename: string;

  @ApiProperty()
  fileid: number;

  @ApiProperty({ enum: FileType })
  type: FileType;

  @ApiPropertyOptional()
  mime?: string;

  @ApiProperty()
  size: number;

  @ApiProperty()
  lastmod: string;

  @ApiProperty()
  path: string;
}

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

  @ApiProperty({ enum: ShareType })
  shareType: ShareType;

  @ApiPropertyOptional()
  shareWith?: string;

  @ApiProperty()
  permissions: number;

  @ApiPropertyOptional()
  url?: string;

  @ApiProperty()
  path: string;

  @ApiPropertyOptional()
  expiration?: string;
}

export class UserResponseDto {
  @ApiProperty()
  id: string;

  @ApiProperty()
  displayName: string;

  @ApiProperty()
  email: string;

  @ApiProperty()
  enabled: boolean;
}

export class CalendarEventResponseDto {
  @ApiProperty()
  id: string;

  @ApiProperty()
  calendarId: string;

  @ApiProperty()
  summary: string;

  @ApiPropertyOptional()
  description?: string;

  @ApiPropertyOptional()
  location?: string;

  @ApiProperty()
  start: string;

  @ApiProperty()
  end: string;

  @ApiProperty()
  allDay: boolean;
}
