/**
 * 全Entity型定義・共有型
 * functional-design.md のデータモデルに対応。
 * タイムスタンプはISO8601文字列(TEXT)。真偽値はINTEGER(0/1)。
 */

// ===== 列挙型 =====

export type UserRole = 'system_admin' | 'project_admin' | 'member' | 'guest';
export type UserStatus = 'active' | 'inactive';
export type Theme = 'dark' | 'light';
export type Locale = 'en' | 'ja';
export type ProjectStatus = 'active' | 'on_hold' | 'completed' | 'archived';
export type ProjectMemberRole = 'admin' | 'member' | 'guest';
export type BoardCategory =
  | 'notice'
  | 'spec'
  | 'minutes'
  | 'question'
  | 'decision'
  | 'trouble'
  | 'memo';
export type TodoPriority = 'low' | 'normal' | 'high';
export type MilestoneStatus = 'open' | 'closed';
export type CalendarEventType =
  | 'meeting'
  | 'deadline'
  | 'milestone'
  | 'todo'
  | 'reminder'
  | 'custom';
export type MeetingMemberStatus = 'invited' | 'accepted' | 'declined';
export type NotificationType =
  | 'mention'
  | 'todo_assigned'
  | 'todo_due_soon'
  | 'meeting_invited'
  | 'board_commented'
  | 'project_added'
  | 'file_shared'
  | 'note_updated';

// ===== エンティティ =====

export interface User {
  id: number;
  name: string;
  email: string;
  passwordHash: string | null;
  avatarUrl: string | null;
  role: UserRole;
  status: UserStatus;
  theme: Theme;
  locale: Locale;
  createdAt: string;
  updatedAt: string;
}

export interface Project {
  id: number;
  name: string;
  description: string | null;
  status: ProjectStatus;
  ownerId: number;
  createdAt: string;
  updatedAt: string;
}

export interface ProjectMember {
  id: number;
  projectId: number;
  userId: number;
  role: ProjectMemberRole;
  joinedAt: string;
}

export interface BoardThread {
  id: number;
  projectId: number;
  title: string;
  bodyMd: string;
  authorId: number;
  category: BoardCategory | null;
  isPinned: number;
  isImportant: number;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface BoardComment {
  id: number;
  threadId: number;
  authorId: number;
  bodyMd: string;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface ChatMessage {
  id: number;
  projectId: number;
  authorId: number;
  body: string;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface TodoColumn {
  id: number;
  projectId: number;
  name: string;
  orderIndex: number;
  createdAt: string;
  updatedAt: string;
}

export interface TodoItem {
  id: number;
  projectId: number;
  columnId: number;
  title: string;
  description: string | null;
  assigneeId: number | null;
  creatorId: number;
  priority: TodoPriority;
  startDate: string | null;
  dueDate: string | null;
  completedAt: string | null;
  orderIndex: number;
  milestoneId: number | null;
  tags: string | null;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface FileAsset {
  id: number;
  projectId: number;
  uploaderId: number;
  filename: string;
  originalName: string;
  mimeType: string;
  size: number;
  path: string;
  source: FileAssetSource;
  createdAt: string;
  deletedAt: string | null;
}

/** ファイルの来源。library=Files一覧公開、attachment=添付専用(一覧に出さない)。 */
export type FileAssetSource = 'library' | 'attachment';

/** 添付ファイルの関連付け対象。 */
export type AttachmentTargetType =
  | 'chat_message'
  | 'board_thread'
  | 'board_comment'
  | 'todo_item';

/** attachments エンティティ。 */
export interface Attachment {
  id: number;
  projectId: number;
  fileId: number;
  targetType: AttachmentTargetType;
  targetId: number;
  createdAt: string;
  deletedAt: string | null;
}

/** UI表示用の添付ファイルビュー(ダウンロードURLは fileId から組み立てる)。 */
export interface AttachmentView {
  id: number;
  fileId: number;
  targetType: AttachmentTargetType;
  targetId: number;
  originalName: string;
  mimeType: string;
  size: number;
}

/** チャットメッセージ + 添付ファイル。 */
export interface ChatMessageWithAttachments extends ChatMessage {
  attachments: AttachmentView[];
}

export interface ProjectNote {
  id: number;
  projectId: number;
  title: string;
  bodyMd: string;
  tags: string | null;
  isPinned: number;
  createdById: number;
  updatedById: number;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface Milestone {
  id: number;
  projectId: number;
  title: string;
  description: string | null;
  dueDate: string | null;
  status: MilestoneStatus;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface CalendarEvent {
  id: number;
  projectId: number;
  title: string;
  description: string | null;
  type: CalendarEventType;
  startAt: string;
  endAt: string | null;
  createdById: number;
  relatedTodoId: number | null;
  relatedMilestoneId: number | null;
  relatedMeetingId: number | null;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface Meeting {
  id: number;
  projectId: number;
  title: string;
  description: string | null;
  location: string | null;
  meetingUrl: string | null;
  startAt: string;
  endAt: string;
  agendaMd: string | null;
  minutesMd: string | null;
  createdById: number;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface MeetingMember {
  id: number;
  meetingId: number;
  userId: number;
  status: MeetingMemberStatus;
}

export interface Notification {
  id: number;
  userId: number;
  projectId: number | null;
  type: NotificationType;
  title: string;
  body: string | null;
  readAt: string | null;
  createdAt: string;
}

export interface ActivityLog {
  id: number;
  projectId: number;
  actorId: number;
  action: string;
  targetType: string;
  targetId: number | null;
  metadataJson: string | null;
  createdAt: string;
}

export interface SchemaMigration {
  id: number;
  filename: string;
  appliedAt: string;
}

// ===== 通知イベント =====

export interface NotificationEventBase {
  projectId: number | null;
  title: string;
  body: string | null;
}

/**
 * 通知イベントの判別共用体。
 * resolveTargets で type ごとに対象ユーザーを解決する。
 */
export type NotificationEvent =
  | (NotificationEventBase & {
      type: 'mention';
      mentionedUserId: number;
    })
  | (NotificationEventBase & { type: 'todo_assigned'; assigneeId: number })
  | (NotificationEventBase & { type: 'todo_due_soon'; assigneeId: number })
  | (NotificationEventBase & {
      type: 'meeting_invited';
      memberIds: number[];
    })
  | (NotificationEventBase & {
      type: 'board_commented';
      threadAuthorId: number;
    })
  | (NotificationEventBase & { type: 'project_added'; addedUserId: number })
  | (NotificationEventBase & {
      type: 'file_shared';
      projectMemberIds: number[];
    })
  | (NotificationEventBase & {
      type: 'note_updated';
      projectMemberIds: number[];
    });

/** SSE配信イベント(M8でSseHubが扱う)。 */
export type SseEvent =
  | {
      type: 'chat.message.created';
      data: {
        projectId: number;
        message: ChatMessageWithAttachments;
      };
    }
  | {
      type: 'chat.message.updated';
      data: { projectId: number; message: ChatMessage };
    }
  | {
      type: 'chat.message.deleted';
      data: { projectId: number; id: number };
    }
  | { type: 'todo.updated'; data: { projectId: number } }
  | { type: 'file.uploaded'; data: { projectId: number } }
  | { type: 'meeting.created'; data: { projectId: number } }
  | { type: 'note.updated'; data: { projectId: number } }
  | { type: 'notification.created'; data: { projectId: number | null } };

/** SSE配信を行うコンポーネントの抽象(M8のSseHubが実装) */
export interface SseBroadcaster {
  broadcast(projectId: number, event: SseEvent): void;
}
