import {
  User,
  ContributorUser,
  Pagination,
  CardSorting,
  CollectionSorting,
  FeedPagination,
} from './common';
import { CollectionAccessType } from './requests';

// Command response types
export interface AddUrlToLibraryResponse {
  urlCardId: string;
  noteCardId?: string;
}

export interface AddCardToLibraryResponse {
  cardId: string;
}

export interface AddCardToCollectionResponse {
  cardId: string;
}

export interface UpdateNoteCardResponse {
  cardId: string;
}

export interface UpdateUrlCardAssociationsResponse {
  urlCardId: string;
  noteCardId?: string;
  addedToCollections: string[];
  removedFromCollections: string[];
}

export interface RemoveCardFromLibraryResponse {
  cardId: string;
}

export interface RemoveCardFromCollectionResponse {
  cardId: string;
}

export interface CreateCollectionResponse {
  collectionId: string;
}

export interface UpdateCollectionResponse {
  collectionId: string;
}

export interface DeleteCollectionResponse {
  collectionId: string;
}

// Query response types
export interface UrlMetadata {
  url: string;
  title?: string;
  description?: string;
  author?: string;
  publishedDate?: string;
  siteName?: string;
  imageUrl?: string;
  type?: string;
  retrievedAt?: string;
  doi?: string;
  isbn?: string;
}

export interface UrlAggregateStats {
  libraryCount: number;
  noteCount: number;
  collectionCount: number;
  connections: {
    all: {
      total: number;
      [type: string]: number;
    };
    incoming: {
      total: number;
      [type: string]: number;
    };
    outgoing: {
      total: number;
      [type: string]: number;
    };
  };
}

export interface GetUrlMetadataResponse {
  metadata: UrlMetadata;
  stats?: UrlAggregateStats; // Optional, only included when includeStats is true
}

// Unified UrlCard interface - base for all card responses
export interface UrlCard {
  id: string;
  type: 'URL';
  url: string;
  uri?: string;
  cardContent: UrlMetadata;
  libraryCount: number;
  urlLibraryCount: number;
  urlInLibrary?: boolean;
  urlConnectionCount?: number;
  urlIsConnected?: boolean;
  createdAt: string;
  updatedAt: string;
  author: User;
  note?: {
    id: string;
    text: string;
  };
}

// Unified Collection interface - used across all endpoints
export interface Collection {
  id: string;
  uri?: string;
  name: string;
  author: User;
  description?: string;
  accessType?: CollectionAccessType;
  cardCount: number;
  createdAt: string;
  updatedAt: string;
  isFollowing?: boolean; // Whether the calling user follows this collection
  followerCount?: number; // Number of users following this collection
}

// Context-specific variations
export interface UrlCardWithCollections extends UrlCard {
  collections: Collection[];
}

export interface UrlCardWithLibraries extends UrlCard {
  libraries: User[];
}

export interface UrlCardWithCollectionsAndLibraries extends UrlCard {
  collections: Collection[];
  libraries: User[];
}

export interface GetUrlCardViewResponse
  extends UrlCardWithCollectionsAndLibraries {}

export interface GetLibrariesForCardResponse {
  cardId: string;
  users: User[];
  totalCount: number;
}

export interface GetProfileResponse extends User {}

export interface GetUrlCardsResponse {
  cards: UrlCard[];
  pagination: Pagination;
  sorting: CardSorting;
}

export interface GetCollectionPageResponse extends Collection {
  urlCards: UrlCard[];
  pagination: Pagination;
  sorting: CardSorting;
}

export interface GetCollectionsResponse {
  collections: Collection[];
  pagination: Pagination;
  sorting: CollectionSorting;
}

export interface LoginWithAppPasswordResponse {
  accessToken: string;
  refreshToken: string;
}

export interface InitiateOAuthSignInResponse {
  authUrl: string;
}

export interface CompleteOAuthSignInResponse {
  accessToken: string;
  refreshToken: string;
}

export interface RefreshAccessTokenResponse {
  accessToken: string;
  refreshToken: string;
}

export interface GenerateExtensionTokensResponse {
  accessToken: string;
  refreshToken: string;
}

// Feed response types
export enum ActivityType {
  CARD_COLLECTED = 'CARD_COLLECTED',
  CONNECTION_CREATED = 'CONNECTION_CREATED',
}

export interface BaseFeedItem {
  id: string;
  user: User;
  createdAt: Date;
}

export interface CardCollectedFeedItem extends BaseFeedItem {
  activityType: ActivityType.CARD_COLLECTED;
  card: UrlCard;
  collections: Collection[];
}

export interface ConnectionCreatedFeedItem extends BaseFeedItem {
  activityType: ActivityType.CONNECTION_CREATED;
  connection: ConnectionWithSourceAndTarget;
}

export type FeedItem = CardCollectedFeedItem | ConnectionCreatedFeedItem;

export interface GetGlobalFeedResponse {
  activities: FeedItem[];
  pagination: FeedPagination;
}

export interface GetUrlStatusForMyLibraryResponse {
  card?: UrlCard;
  collections?: Collection[];
}

export interface GetLibrariesForUrlResponse {
  libraries: {
    user: User;
    card: UrlCard;
  }[];
  pagination: Pagination;
  sorting: CardSorting;
}

export interface GetNoteCardsForUrlResponse {
  notes: {
    id: string;
    note: string;
    author: User;
    createdAt: string;
    updatedAt: string;
  }[];
  pagination: Pagination;
  sorting: CardSorting;
}

export interface GetCollectionsForUrlResponse {
  collections: Collection[];
  pagination: Pagination;
  sorting: CollectionSorting;
}

// Search response types
export interface UrlView {
  url: string;
  metadata: UrlMetadata;
  urlLibraryCount: number;
  urlInLibrary?: boolean;
  urlConnectionCount?: number;
  urlIsConnected?: boolean;
}

export interface GetSimilarUrlsForUrlResponse {
  urls: UrlView[];
  pagination: Pagination;
}

export interface SemanticSearchUrlsResponse {
  urls: UrlView[];
  pagination: Pagination;
}

// Bluesky search response types
export interface PostView {
  uri: string;
  cid: string;
  author: {
    did: string;
    handle: string;
    displayName?: string;
    avatar?: string;
    associated?: {
      chat?: {
        allowIncoming: 'all' | 'none' | 'following';
      };
    };
    viewer?: {
      muted?: boolean;
      blockedBy?: boolean;
      blocking?: string;
      following?: string;
      followedBy?: string;
    };
    labels?: any[];
    createdAt?: string;
  };
  record: { [key: string]: unknown };
  embed?: any;
  replyCount?: number;
  repostCount?: number;
  likeCount?: number;
  quoteCount?: number;
  indexedAt: string;
  viewer?: {
    repost?: string;
    like?: string;
    threadMuted?: boolean;
    replyDisabled?: boolean;
    embeddingDisabled?: boolean;
    pinned?: boolean;
  };
  labels?: any[];
  threadgate?: any;
}

export interface SearchBskyPostsForUrlResponse {
  cursor?: string;
  hitsTotal?: number;
  posts: PostView[];
}

// AtProto account search response types
export interface ProfileView {
  did: string;
  handle: string;
  displayName?: string;
  description?: string;
  avatar?: string;
  associated?: {
    chat?: {
      allowIncoming: 'all' | 'none' | 'following';
    };
  };
  indexedAt?: string;
  createdAt?: string;
  viewer?: {
    muted?: boolean;
    blockedBy?: boolean;
    blocking?: string;
    following?: string;
    followedBy?: string;
  };
  labels?: any[];
  verification?: any;
  status?: any;
}

export interface SearchAtProtoAccountsResponse {
  cursor?: string;
  actors: ProfileView[];
}

export interface SearchLeafletDocsForUrlResponse {
  urls: UrlView[];
  cursor?: string;
  total: number;
}

// Notification types
export enum NotificationType {
  USER_ADDED_YOUR_CARD = 'USER_ADDED_YOUR_CARD',
  USER_ADDED_YOUR_BSKY_POST = 'USER_ADDED_YOUR_BSKY_POST',
  USER_ADDED_YOUR_COLLECTION = 'USER_ADDED_YOUR_COLLECTION',
  USER_ADDED_TO_YOUR_COLLECTION = 'USER_ADDED_TO_YOUR_COLLECTION',
  USER_FOLLOWED_YOU = 'USER_FOLLOWED_YOU',
  USER_FOLLOWED_YOUR_COLLECTION = 'USER_FOLLOWED_YOUR_COLLECTION',
  USER_CONNECTED_YOUR_URL = 'USER_CONNECTED_YOUR_URL',
  USER_CONNECTED_YOUR_POST = 'USER_CONNECTED_YOUR_POST',
  USER_CONNECTED_YOUR_COLLECTION = 'USER_CONNECTED_YOUR_COLLECTION',
}

export interface BaseNotificationItem {
  id: string;
  user: User;
  createdAt: string;
  type: NotificationType;
  read: boolean;
}

export interface CardCollectionNotificationItem extends BaseNotificationItem {
  type:
    | NotificationType.USER_ADDED_YOUR_CARD
    | NotificationType.USER_ADDED_YOUR_BSKY_POST
    | NotificationType.USER_ADDED_YOUR_COLLECTION
    | NotificationType.USER_ADDED_TO_YOUR_COLLECTION;
  card: UrlCard;
  collections?: Collection[];
}

export interface FollowNotificationItem extends BaseNotificationItem {
  type:
    | NotificationType.USER_FOLLOWED_YOU
    | NotificationType.USER_FOLLOWED_YOUR_COLLECTION;
  followTargetType: 'USER' | 'COLLECTION';
  followTargetId?: string;
  collections?: Collection[];
}

export interface ConnectionCreatedNotificationItem
  extends BaseNotificationItem {
  type:
    | NotificationType.USER_CONNECTED_YOUR_URL
    | NotificationType.USER_CONNECTED_YOUR_POST
    | NotificationType.USER_CONNECTED_YOUR_COLLECTION;
  connection: ConnectionWithSourceAndTarget;
}

export type NotificationItem =
  | CardCollectionNotificationItem
  | FollowNotificationItem
  | ConnectionCreatedNotificationItem;

export interface GetMyNotificationsResponse {
  notifications: NotificationItem[];
  pagination: Pagination;
  unreadCount: number;
}

export interface GetUnreadNotificationCountResponse {
  unreadCount: number;
}

export interface MarkNotificationsAsReadResponse {
  markedCount: number;
}

export interface MarkAllNotificationsAsReadResponse {
  markedCount: number;
}

// Follow response types
export interface FollowTargetResponse {
  followId: string;
}

// Follow query response types
export interface GetFollowingUsersResponse {
  users: User[];
  pagination: Pagination;
}

export interface GetFollowersResponse {
  users: User[];
  pagination: Pagination;
}

export interface GetFollowingCollectionsResponse {
  collections: Collection[];
  pagination: Pagination;
}

export interface GetCollectionFollowersResponse {
  users: User[];
  pagination: Pagination;
}

// Follow count response types
export interface GetFollowCountResponse {
  count: number;
}

// Contributor response types
export interface GetCollectionContributorsResponse {
  users: ContributorUser[];
  pagination: Pagination;
}

// Connection response types
export interface CreateConnectionResponse {
  connectionId: string;
}

export interface UpdateConnectionResponse {
  connectionId: string;
}

export interface DeleteConnectionResponse {
  connectionId: string;
}

export interface ConnectionSorting {
  sortBy: string;
  sortOrder: 'asc' | 'desc';
}

export interface GetConnectionsForUrlResponse {
  connections: ConnectionWithSourceAndTarget[];
  pagination: Pagination;
  sorting: ConnectionSorting;
}

// Search URLs response types
export interface SearchUrlsResponse {
  urls: UrlView[];
  pagination: Pagination;
  sorting: CardSorting;
}

// Get connections response types
export interface ConnectionWithSourceAndTarget {
  connection: {
    id: string;
    type?: string;
    note?: string;
    createdAt: string;
    updatedAt: string;
    curator: User;
  };
  source: UrlView;
  target: UrlView;
}

export interface GetConnectionsResponse {
  connections: ConnectionWithSourceAndTarget[];
  pagination: Pagination;
  sorting: ConnectionSorting;
}

// Graph response types
export interface GraphNode {
  id: string;
  type: 'USER' | 'URL' | 'COLLECTION' | 'NOTE';
  label: string;
  metadata: Record<string, any>;
}

export interface GraphEdge {
  id: string;
  source: string;
  target: string;
  type:
    | 'USER_FOLLOWS_USER'
    | 'USER_FOLLOWS_COLLECTION'
    | 'USER_AUTHORED_URL'
    | 'NOTE_REFERENCES_URL'
    | 'COLLECTION_CONTAINS_URL'
    | 'URL_CONNECTS_URL';
  metadata?: Record<string, any>;
}

export interface GetGraphDataResponse {
  nodes: GraphNode[];
  edges: GraphEdge[];
  pagination: Pagination;
}
