import { render, screen } from '@testing-library/react'
import React from 'react'

import { createMockClient } from 'cozy-client'
import flag from 'cozy-flags'

import ShareRecipientsInput from './ShareRecipientsInput'
import AppLike from './SharingBanner/test/AppLike'

jest.mock('cozy-flags', () => ({
  __esModule: true,
  default: jest.fn(() => null)
}))

jest.mock('./ShareAutosuggest', () => ({
  __esModule: true,
  default: ({ contactsAndGroups }) => {
    return (
      <ul>
        {contactsAndGroups.map(contactOrGroup => {
          if (contactOrGroup._type === 'io.cozy.contacts') {
            return (
              <li key={contactOrGroup.id}>
                {contactOrGroup.name.givenName} {contactOrGroup.name.familyName}
              </li>
            )
          } else {
            return (
              <li key={contactOrGroup.id}>
                {contactOrGroup.name} - {contactOrGroup.members.length} members
              </li>
            )
          }
        })}
      </ul>
    )
  }
}))

describe('ShareRecipientsInput component', () => {
  const setup = (
    { contacts, contactGroups, unreachableContact },
    { currentRecipients, recipients } = {}
  ) => {
    const mockClient = createMockClient({
      queries: {
        'io.cozy.contacts/reachable': {
          doctype: 'io.cozy.contacts',
          data: contacts
        },
        'io.cozy.contacts.groups': {
          doctype: 'io.cozy.contacts.groups',
          data: contactGroups
        },
        'io.cozy.contacts/unreachable-with-groups': {
          doctype: 'io.cozy.contacts',
          data: unreachableContact
        }
      }
    })
    render(
      <AppLike client={mockClient}>
        <ShareRecipientsInput
          onPick={() => {}}
          onRemove={() => {}}
          placeholder="Enter recipients here"
          currentRecipients={currentRecipients}
          recipients={recipients}
        />
      </AppLike>
    )
  }

  it('should include groups and contacts when are loaded', async () => {
    const contacts = [
      {
        id: 'df563cc4-6440',
        _id: 'df563cc4-6440',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Michale',
          familyName: 'Russel'
        }
      },
      {
        id: '5a3b4ccf-c257',
        _id: '5a3b4ccf-c257',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Teagan',
          familyName: 'Wolf'
        },
        relationships: {
          groups: {
            data: [
              {
                _id: 'fe86af20-c6c5',
                _type: 'io.cozy.contacts.groups'
              }
            ]
          }
        }
      }
    ]

    const contactGroups = [
      {
        id: 'fe86af20-c6c5',
        name: "The Night's Watch",
        _id: 'fe86af20-c6c5',
        _type: 'io.cozy.contacts.groups'
      }
    ]

    setup({ contacts, contactGroups })

    expect(screen.getByText('Michale Russel')).toBeInTheDocument()
    expect(screen.getByText('Teagan Wolf')).toBeInTheDocument()
    expect(
      screen.getByText("The Night's Watch - 1 members")
    ).toBeInTheDocument()
  })

  it('should exclude current user from suggestions when me is true', async () => {
    const contacts = [
      {
        id: 'df563cc4-6440',
        _id: 'df563cc4-6440',
        _type: 'io.cozy.contacts',
        me: true,
        name: {
          givenName: 'My',
          familyName: 'Self'
        },
        relationships: {
          groups: {
            data: [
              {
                _id: 'group-id',
                _type: 'io.cozy.contacts.groups'
              }
            ]
          }
        }
      },
      {
        id: '5a3b4ccf-c257',
        _id: '5a3b4ccf-c257',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Teagan',
          familyName: 'Wolf'
        },
        relationships: {
          groups: {
            data: [
              {
                _id: 'group-id',
                _type: 'io.cozy.contacts.groups'
              }
            ]
          }
        }
      }
    ]

    const contactGroups = [
      {
        id: 'group-id',
        name: 'Friends',
        _id: 'group-id',
        _type: 'io.cozy.contacts.groups'
      }
    ]

    setup({ contacts, contactGroups })

    expect(screen.queryByText('My Self')).not.toBeInTheDocument()
    expect(screen.getByText('Teagan Wolf')).toBeInTheDocument()
    expect(screen.getByText('Friends - 1 members')).toBeInTheDocument()
  })

  it('should exclude already added recipients from suggestions', async () => {
    const contacts = [
      {
        id: 'df563cc4-6440',
        _id: 'df563cc4-6440',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Michale',
          familyName: 'Russel'
        },
        email: [{ address: 'michale@example.com', primary: true }]
      },
      {
        id: '5a3b4ccf-c257',
        _id: '5a3b4ccf-c257',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Teagan',
          familyName: 'Wolf'
        },
        email: [{ address: 'teagan@example.com', primary: true }]
      }
    ]

    const contactGroups = []
    const currentRecipients = [
      { id: 'recipient-1', email: 'michale@example.com' }
    ]
    const recipients = [{ _id: '5a3b4ccf-c257' }]

    setup({ contacts, contactGroups }, { currentRecipients, recipients })

    // Michale is in currentRecipients by email, should be filtered out
    expect(screen.queryByText('Michale Russel')).not.toBeInTheDocument()
    // Teagan is in recipients by _id, should be filtered out
    expect(screen.queryByText('Teagan Wolf')).not.toBeInTheDocument()
  })

  it('should include unreachable members when flag sharing.show-recipient-groups is activated', async () => {
    flag.mockReturnValue(true)

    const contacts = [
      {
        id: 'df563cc4-6440',
        _id: 'df563cc4-6440',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Michale',
          familyName: 'Russel'
        }
      },
      {
        id: '5a3b4ccf-c257',
        _id: '5a3b4ccf-c257',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Teagan',
          familyName: 'Wolf'
        },
        relationships: {
          groups: {
            data: [
              {
                _id: 'fe86af20-c6c5',
                _type: 'io.cozy.contacts.groups'
              }
            ]
          }
        }
      }
    ]

    const contactGroups = [
      {
        id: 'fe86af20-c6c5',
        name: "The Night's Watch",
        _id: 'fe86af20-c6c5',
        _type: 'io.cozy.contacts.groups'
      }
    ]

    const unreachableContact = [
      {
        id: 'df532cc4-6560',
        _id: 'df532cc4-6560',
        _type: 'io.cozy.contacts',
        name: {
          givenName: 'Tony',
          familyName: 'Stark'
        },
        relationships: {
          groups: {
            data: [
              {
                _id: 'fe86af20-c6c5',
                _type: 'io.cozy.contacts.groups'
              }
            ]
          }
        }
      }
    ]

    setup({ contacts, contactGroups, unreachableContact })

    expect(screen.getByText('Michale Russel')).toBeInTheDocument()
    expect(screen.getByText('Teagan Wolf')).toBeInTheDocument()
    // 3 members because cozy-client replay the query with the new data
    // so the unreachableContact is added to the reachable contact query
    // TODO: improve createMockClient to handle this case
    expect(
      screen.getByText("The Night's Watch - 3 members")
    ).toBeInTheDocument()
  })
})
