import type { Account } from 'src/lib/api-types'
import {
  isSyntheticRemoteId,
  mapOrderedCollectionPage,
  type OrderedCollectionPage,
  syntheticRemoteId,
} from 'src/lib/remote-outbox'

const account = {
  id: 'home-1',
  acct: 'foo@other.example',
  url: 'https://other.example/@foo',
  username: 'foo',
  display_name: 'Foo',
  avatar: '',
  emojis: [],
} as unknown as Account

function note(overrides: Record<string, unknown> = {}) {
  return {
    type: 'Create',
    id: 'https://other.example/users/foo/activities/1',
    published: '2026-01-01T00:00:00Z',
    object: {
      id: 'https://other.example/users/foo/statuses/1',
      type: 'Note',
      url: 'https://other.example/@foo/1',
      content: '<p>hello</p>',
      published: '2026-01-01T00:00:00Z',
      ...overrides,
    },
  }
}

describe('remote-outbox', () => {
  describe('synthetic id helpers', () => {
    test('round-trips a canonical url through the prefix', () => {
      const id = syntheticRemoteId('https://x.example/statuses/1')
      expect(isSyntheticRemoteId(id)).toBe(true)
      expect(isSyntheticRemoteId('https://x.example/statuses/1')).toBe(false)
      expect(isSyntheticRemoteId(undefined)).toBe(false)
      expect(isSyntheticRemoteId(null)).toBe(false)
    })
  })

  describe('mapOrderedCollectionPage', () => {
    test('maps a Create{Note} into a synthetic Status', () => {
      const page: OrderedCollectionPage = { orderedItems: [note() as any] }
      const out = mapOrderedCollectionPage(page, account)
      expect(out).toHaveLength(1)
      const s = out[0]
      expect(isSyntheticRemoteId(s.id)).toBe(true)
      expect(s.uri).toBe('https://other.example/users/foo/statuses/1')
      expect(s.url).toBe('https://other.example/@foo/1')
      expect(s.content).toBe('<p>hello</p>')
      expect(s.account).toBe(account)
      expect(s.created_at).toBe('2026-01-01T00:00:00Z')
      expect(s.media_attachments).toEqual([])
      expect(s.reblog).toBeNull()
      expect(s.visibility).toBe('public')
    })

    test('skips Announce and Like activities', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          { type: 'Announce', id: 'a1', object: 'https://elsewhere/abc' } as any,
          { type: 'Like', id: 'l1', object: 'https://elsewhere/def' } as any,
          note() as any,
        ],
      }
      expect(mapOrderedCollectionPage(page, account)).toHaveLength(1)
    })

    test('skips replies (objects with inReplyTo)', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          note({ inReplyTo: 'https://other.example/statuses/parent' }) as any,
          note() as any,
        ],
      }
      const out = mapOrderedCollectionPage(page, account)
      expect(out).toHaveLength(1)
      expect(out[0].uri).toBe('https://other.example/users/foo/statuses/1')
    })

    test('skips unsupported object types', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [note({ type: 'Tombstone' }) as any, note() as any],
      }
      expect(mapOrderedCollectionPage(page, account)).toHaveLength(1)
    })

    test('maps attachments with mediaType, alt text, and dimensions', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          note({
            attachment: [
              {
                type: 'Document',
                mediaType: 'image/jpeg',
                url: 'https://other.example/media/a.jpg',
                name: 'a sunset',
                width: 800,
                height: 600,
                blurhash: 'L6PZfSi_.AyE',
              },
              {
                type: 'Document',
                mediaType: 'video/mp4',
                url: 'https://other.example/media/b.mp4',
              },
            ],
          }) as any,
        ],
      }
      const [s] = mapOrderedCollectionPage(page, account)
      expect(s.media_attachments).toHaveLength(2)
      const [img, vid] = s.media_attachments
      expect(img.type).toBe('image')
      expect(img.url).toBe('https://other.example/media/a.jpg')
      expect(img.description).toBe('a sunset')
      expect(img.blurhash).toBe('L6PZfSi_.AyE')
      expect(img.meta?.original).toEqual({ width: 800, height: 600 })
      expect(vid.type).toBe('video')
      expect(vid.description).toBeNull()
      expect(vid.blurhash).toBeNull()
    })

    test('drops attachments without a usable url', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          note({
            attachment: [
              { type: 'Document', mediaType: 'image/jpeg' },
              {
                type: 'Document',
                mediaType: 'image/jpeg',
                url: 'https://other.example/media/ok.jpg',
              },
            ],
          }) as any,
        ],
      }
      const [s] = mapOrderedCollectionPage(page, account)
      expect(s.media_attachments).toHaveLength(1)
      expect(s.media_attachments[0].url).toBe('https://other.example/media/ok.jpg')
    })

    test('accepts a single attachment object (not just arrays)', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          note({
            attachment: {
              type: 'Document',
              mediaType: 'image/png',
              url: 'https://other.example/media/single.png',
            },
          }) as any,
        ],
      }
      const [s] = mapOrderedCollectionPage(page, account)
      expect(s.media_attachments).toHaveLength(1)
    })

    test('falls back to object.url and activity.id for the canonical id', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          {
            type: 'Create',
            id: 'https://other.example/activity/2',
            object: { type: 'Note', url: 'https://other.example/note/2', content: 'x' },
          } as any,
        ],
      }
      const [s] = mapOrderedCollectionPage(page, account)
      expect(s.uri).toBe('https://other.example/note/2')
      expect(s.url).toBe('https://other.example/note/2')
      expect(s.id).toBe(syntheticRemoteId('https://other.example/note/2'))
    })

    test('returns [] on empty / malformed page', () => {
      expect(mapOrderedCollectionPage({}, account)).toEqual([])
      expect(
        mapOrderedCollectionPage({ orderedItems: [] }, account)
      ).toEqual([])
      expect(
        mapOrderedCollectionPage(
          { orderedItems: [{ type: 'Create' } as any] },
          account
        )
      ).toEqual([])
    })

    test('preserves spoiler_text from object.summary', () => {
      const page: OrderedCollectionPage = {
        orderedItems: [
          note({ summary: 'CW: politics', sensitive: true }) as any,
        ],
      }
      const [s] = mapOrderedCollectionPage(page, account)
      expect(s.spoiler_text).toBe('CW: politics')
      expect(s.sensitive).toBe(true)
    })
  })
})
