"""Shop + digital magazine tests.  Run:  venv/bin/python manage.py test apps.store"""
import io
import shutil
import tempfile
from decimal import Decimal

from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings

from apps.store import magazine as mag
from apps.store.models import DigitalAccess, Product, StorePageContent, private_storage

TMP = tempfile.mkdtemp()
GIF = (b'GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xff\xff\xff!\xf9\x04\x00\x00\x00\x00\x00,'
       b'\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;')


def sign_in(client, name='buyer'):
    """Buying needs an account: sign this test client in as a reader."""
    user = User.objects.filter(username=name).first() or User.objects.create_user(name, f'{name}@example.com', 'pw-12345678')
    client.force_login(user)
    return user


def make_pdf(pages):
    from pypdf import PdfWriter
    w = PdfWriter()
    for _ in range(pages):
        w.add_blank_page(width=300, height=400)
    buf = io.BytesIO()
    w.write(buf)
    return buf.getvalue()


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='',
                   ALLOWED_HOSTS=['testserver', 'thereversetimes.com', 'www.thereversetimes.com'])
class MagazineTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        shutil.rmtree(TMP, ignore_errors=True)

    def setUp(self):
        self.issue = Product.objects.create(
            product_type='magazine', title='The Mughal Issue', description='Mughal Dhaka.',
            price=Decimal('350'), digital_price=Decimal('150'), preview_pages='1-3', issue_label='Vol. 1 · Issue 1',
            image=SimpleUploadedFile('c.gif', GIF, content_type='image/gif'),
            pdf_file=SimpleUploadedFile('m.pdf', make_pdf(10), content_type='application/pdf'))
        mag.build_preview(self.issue)
        self.issue.refresh_from_db()
        self.tee = Product.objects.create(title='Lalbagh Tee', description='Cotton', price=Decimal('600'),
                                          image=SimpleUploadedFile('t.gif', GIF, content_type='image/gif'))

    def request_access(self, client=None, trx='9A7B6C5D4E'):
        client = client or self.client
        if '_auth_user_id' not in client.session:
            sign_in(client, f'reader{User.objects.count()}')
        return client.post(f'/magazine/{self.issue.slug}/request-access/', {
            'name': 'Rahim', 'phone': '01711111111', 'sender_number': '01711111111', 'trx_id': trx,
            'accept_terms': 'true'})

    def test_preview_has_only_free_pages(self):
        from pypdf import PdfReader
        with self.issue.preview_pdf.open('rb') as fh:
            self.assertEqual(len(PdfReader(fh).pages), 3)
        self.assertEqual(self.issue.page_count, 10)
        self.assertEqual(self.issue.pdf_file.url, '')  # the full PDF has no public address

    def test_full_pdf_locked_until_approved(self):
        pdf_url = f'/magazine/{self.issue.slug}/read/full.pdf'
        self.assertEqual(self.client.get(pdf_url).status_code, 404)
        self.request_access()
        access = DigitalAccess.objects.get()
        self.assertEqual(access.status, 'pending')
        page = self.client.get(self.issue.get_absolute_url())
        self.assertContains(page, 'waiting for approval')
        self.assertContains(page, 'wa.me/8801967286753')
        self.assertEqual(self.client.get(pdf_url).status_code, 404)

        mag.approve(access)
        self.assertEqual(self.client.get(pdf_url).status_code, 200)
        self.assertContains(self.client.get(self.issue.get_absolute_url()), 'Full issue unlocked')

    def test_unlock_on_another_device(self):
        self.request_access()
        mag.approve(DigitalAccess.objects.get())
        other = self.client_class()
        pdf_url = f'/magazine/{self.issue.slug}/read/full.pdf'
        self.assertEqual(other.get(pdf_url).status_code, 404)
        other.post(f'/magazine/{self.issue.slug}/unlock/', {'phone': '01711111111', 'code': '9a7b6c5d4e'})
        self.assertEqual(other.get(pdf_url).status_code, 200)
        stranger = self.client_class()
        stranger.post(f'/magazine/{self.issue.slug}/unlock/', {'phone': '01999999999', 'code': '9A7B6C5D4E'})
        self.assertEqual(stranger.get(pdf_url).status_code, 404)

    def test_validation_and_duplicates(self):
        self.client.post(f'/magazine/{self.issue.slug}/request-access/', {'name': '', 'phone': '123', 'trx_id': 'x'})
        self.assertEqual(DigitalAccess.objects.count(), 0)
        self.request_access()
        self.request_access(client=self.client_class())
        self.assertEqual(DigitalAccess.objects.count(), 1)

    def test_staff_can_always_read(self):
        User.objects.create_superuser('ed', 'e@example.com', 'pw-12345678')
        self.client.login(username='ed', password='pw-12345678')
        self.assertEqual(self.client.get(f'/magazine/{self.issue.slug}/read/full.pdf').status_code, 200)

    def test_urls_and_listings(self):
        self.assertEqual(self.issue.get_absolute_url(), '/magazine/the-mughal-issue/')
        self.assertEqual(self.tee.get_absolute_url(), '/shop/lalbagh-tee/')
        r = self.client.get('/shop/the-mughal-issue/')  # magazine via shop URL → its real page
        self.assertEqual((r.status_code, r['Location']), (301, '/magazine/the-mughal-issue/'))
        shop = self.client.get('/shop/').content.decode()
        self.assertNotIn('The Mughal Issue', shop)  # issues aren't listed in the shop…
        self.assertIn('Read Magazine', shop)        # …one card leads to /magazine/ instead
        grid = shop.split('class="store-grid"', 1)[1]
        self.assertLess(grid.index('Read Magazine'), grid.index('Lalbagh Tee'))
        self.assertNotIn('>Magazine</a>', shop.split('shop-tabs', 1)[1].split('</nav>', 1)[0])
        self.assertIn('Lalbagh Tee', shop)
        mags = self.client.get('/magazine/').content.decode()
        self.assertIn('The Mughal Issue', mags)
        self.assertNotIn('Lalbagh Tee', mags)
        self.assertIn('"@type":"Periodical"', mags)
        self.assertNotIn('The Mughal Issue', self.client.get('/shop/merchandise/').content.decode())

    def test_old_shop_links_redirect(self):
        r = self.client.get('/reverse-collection/')
        self.assertEqual((r.status_code, r['Location']), (301, '/shop/'))
        r = self.client.get('/reverse-collection/lalbagh-tee/?ref=fb')
        self.assertEqual((r.status_code, r['Location']), (301, '/shop/lalbagh-tee/?ref=fb'))

    def test_sitemap_and_games(self):
        sm = self.client.get('/sitemap.xml').content.decode()
        for path in ('/shop/', '/magazine/', '/games/', '/magazine/the-mughal-issue/', '/shop/lalbagh-tee/'):
            self.assertIn(f'<loc>https://thereversetimes.com{path}</loc>', sm)
        self.assertNotIn('reverse-collection', sm)
        self.assertContains(self.client.get('/games/'), 'ইতিহাসের খেলা</h1>')
        home = self.client.get('/').content.decode()
        for link in ('href="/shop/"', 'href="/magazine/"', 'href="/games/"'):
            self.assertIn(link, home)


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='', ALLOWED_HOSTS=['testserver'])
class MagazineEditionTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    def make(self, **kw):
        data = dict(product_type='magazine', title='Issue', description='x', price=Decimal('150'),
                    digital_price=Decimal('50'), image=SimpleUploadedFile('c.gif', GIF, content_type='image/gif'),
                    pdf_file=SimpleUploadedFile('m.pdf', make_pdf(8), content_type='application/pdf'))
        data.update(kw)
        p = Product.objects.create(**data)
        mag.build_preview(p)
        p.refresh_from_db()
        return p

    def test_free_issue_needs_an_account(self):
        p = self.make(slug='free-one', digital_mode='free', preview_pages='1-2')
        self.assertTrue(p.is_free_digital)
        self.assertEqual(p.preview_page_list, [1, 2])  # guests see a short preview
        self.assertEqual(self.client.get(f'/magazine/{p.slug}/read/full.pdf').status_code, 404)
        page = self.client.get(p.get_absolute_url())
        self.assertContains(page, 'সাইন ইন করে পড়ুন')
        self.assertNotContains(page, 'id="buy"')
        User.objects.create_user('reader', 'r@example.com', 'pw-12345678')
        self.client.login(username='reader', password='pw-12345678')
        self.assertEqual(self.client.get(f'/magazine/{p.slug}/read/full.pdf').status_code, 200)
        self.assertContains(self.client.get(p.get_absolute_url()), 'এখনই পড়ুন')

    def test_chosen_preview_pages(self):
        from pypdf import PdfReader
        p = self.make(slug='paid-one', digital_mode='paid', preview_pages='2, 4-5, 99')
        self.assertEqual(p.preview_page_list, [2, 4, 5])
        with p.preview_pdf.open('rb') as fh:
            self.assertEqual(len(PdfReader(fh).pages), 3)
        page = self.client.get(p.get_absolute_url()).content.decode()
        self.assertIn('"pages": [2, 4, 5]', page)
        self.assertIn('"total": 8', page)
        self.assertEqual(self.client.get(f'/magazine/{p.slug}/read/full.pdf').status_code, 404)

    def test_print_only_issue_has_no_reader(self):
        p = self.make(slug='print-only', digital_mode='none')
        page = self.client.get(p.get_absolute_url())
        self.assertNotContains(page, 'id="read"')
        self.assertContains(page, 'কার্টে যোগ করুন')
        self.assertEqual(self.client.get(f'/magazine/{p.slug}/read/full.pdf').status_code, 404)

    def test_fake_pdf_rejected(self):
        from django.core.exceptions import ValidationError
        from apps.store.models import validate_pdf
        with self.assertRaises(ValidationError):
            validate_pdf(SimpleUploadedFile('x.pdf', b'<html>not a pdf</html>'))

    def test_page_list_parser(self):
        from apps.store.models import parse_page_list
        self.assertEqual(parse_page_list('1-3, 7 ,10-9, x, 0', total=9), [1, 2, 3, 7, 9])

    def test_homepage_sections_magazine_card_and_nostalgic(self):
        from apps.articles.models import Article
        from apps.core.models import HomepageBlock
        p = self.make(slug='home-issue', digital_mode='paid', preview_pages='1-2', is_featured=True)
        Product.objects.create(product_type='nostalgic', title='Hurricane lamp', slug='hurricane-lamp',
                               description='Old lamp', price=Decimal('900'),
                               image=SimpleUploadedFile('l.gif', GIF, content_type='image/gif'))
        self.assertTrue(HomepageBlock.objects.filter(kind='magazines').exists())  # seeded by migration
        home = self.client.get('/').content.decode()
        self.assertIn('/magazine/home-issue/', home)
        self.assertIn('Hurricane lamp', home)
        self.assertIn('class="bottom-nav"', home)
        self.assertContains(self.client.get('/shop/nostalgic/'), 'Hurricane lamp')

        a = Article.objects.create(title='Bhisti', slug='bhisti', body='<p>x</p>', excerpt='x', status='published',
                                   featured_image='articles/x.jpg')
        from django.utils import timezone
        Article.objects.filter(pk=a.pk).update(published_at=timezone.now())
        a.magazines.add(p)
        self.assertContains(self.client.get('/articles/bhisti/'), 'The Reverse Times Magazine')
        self.assertContains(self.client.get(p.get_absolute_url()), 'Bhisti')
        self.assertContains(self.client.get('/magazine/'), 'Bhisti')

    def test_admin_pages(self):
        from django.contrib.auth.models import User
        User.objects.create_superuser('boss', 'b@example.com', 'pw-123456789')
        self.client.login(username='boss', password='pw-123456789')
        for url in ('/admin/', '/admin/store/magazineissue/', '/admin/store/magazineissue/add/',
                    '/admin/store/wearablehistoryproduct/', '/admin/store/nostalgicitem/add/',
                    '/admin/core/homepageblock/', '/admin/core/homepageblock/add/'):
            self.assertEqual(self.client.get(url).status_code, 200, url)
        self.assertContains(self.client.get('/admin/'), 'Magazine readers to approve')


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='', ALLOWED_HOSTS=['testserver'])
class CouponTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    def setUp(self):
        import json as _json
        self.json = _json
        img = lambda n: SimpleUploadedFile(n, GIF, content_type='image/gif')
        self.tee = Product.objects.create(product_type='merch', title='Tee', slug='tee', description='x',
                                          price=Decimal('600'), image=img('a.gif'))
        self.lamp = Product.objects.create(product_type='nostalgic', title='Lamp', slug='lamp', description='x',
                                           price=Decimal('400'), image=img('b.gif'))
        self.issue = Product.objects.create(product_type='magazine', title='Issue', slug='issue', description='x',
                                            price=Decimal('150'), digital_price=Decimal('100'), digital_mode='paid',
                                            image=img('c.gif'),
                                            pdf_file=SimpleUploadedFile('m.pdf', make_pdf(4), content_type='application/pdf'))
        mag.build_preview(self.issue)

    def post(self, url, data):
        return self.client.post(url, self.json.dumps(data), content_type='application/json').json()

    def cart(self, *pairs):
        return [{'product_id': p.pk, 'quantity': q} for p, q in pairs]

    def order(self, code, phone='01711111111', items=None):
        sign_in(self.client, 'buyer' + phone)  # one account per phone, like real customers
        return self.post('/shop/place-order/', {'name': 'R', 'phone': phone, 'location': 'Dhaka', 'accept_terms': True,
                                                'items': items or self.cart((self.tee, 1)), 'coupon_code': code})

    def test_percentage_cap_scope_and_min_order(self):
        from apps.store.models import Coupon
        Coupon.objects.create(code='merch50', discount_value=50, max_discount=200, applies_to='merch',
                              min_order_amount=500, per_customer_limit=None)
        r = self.post('/shop/coupon/validate/', {'code': 'MERCH50', 'items': self.cart((self.tee, 1), (self.lamp, 1))})
        self.assertEqual(r['discount_amount'], 200.0)  # 50% of 600 capped at 200; lamp not eligible
        r = self.post('/shop/coupon/validate/', {'code': 'merch50', 'items': self.cart((self.lamp, 2))})
        self.assertFalse(r['success'])
        Product.objects.filter(pk=self.tee.pk).update(price=300)
        r = self.post('/shop/coupon/validate/', {'code': 'merch50', 'items': self.cart((self.tee, 1))})
        self.assertIn('minimum', r['error'])

    def test_total_and_per_customer_limits(self):
        from apps.store.models import Coupon, CouponRedemption, Order
        c = Coupon.objects.create(code='FIX100', discount_type='fixed', discount_value=100, max_uses=2, per_customer_limit=1)
        self.assertTrue(self.order('fix100')['success'])
        self.assertEqual(Order.objects.get().total_amount, Decimal('500'))
        again = self.order('fix100')  # same phone
        self.assertFalse(again['success'])
        self.assertTrue(self.order('fix100', phone='01822222222')['success'])
        self.assertIn('fully used', self.order('fix100', phone='01933333333')['error'])
        c.refresh_from_db()
        self.assertEqual((c.current_uses, CouponRedemption.objects.count()), (2, 2))

    def test_prices_come_from_server(self):
        sign_in(self.client)
        r = self.post('/shop/place-order/', {'name': 'R', 'phone': '01711111111', 'location': 'D', 'accept_terms': True,
                                             'items': [{'product_id': self.tee.pk, 'quantity': 2, 'price': 1}]})
        from apps.store.models import Order
        self.assertTrue(r['success'])
        self.assertEqual(Order.objects.get().total_amount, Decimal('1200'))

    def test_owner_only_coupon_and_digital_magazine(self):
        from apps.store.models import Coupon, DigitalAccess
        u = User.objects.create_user('p', 'p@example.com', 'pw-12345678')
        Coupon.objects.create(code='GAME-ABC', discount_value=100, applies_to='magazine_digital', owner=u)
        self.assertFalse(self.order('GAME-ABC')['success'])  # someone else's coupon
        self.client.logout()
        url = self.issue.get_absolute_url()
        self.assertContains(self.client.get(url + '?coupon=GAME-ABC'), 'Please sign in')
        self.client.login(username='p', password='pw-12345678')
        page = self.client.get(url + '?coupon=game-abc')
        self.assertContains(page, 'এই কুপনে সংখ্যাটি পুরোপুরি ফ্রি')
        self.client.post(f'/magazine/{self.issue.slug}/request-access/',
                         {'name': 'P', 'phone': '01711111111', 'coupon_code': 'game-abc', 'accept_terms': 'true'})
        access = DigitalAccess.objects.get()
        self.assertEqual((access.status, access.amount, access.discount_amount), ('approved', Decimal('0'), Decimal('100')))
        self.assertEqual(self.client.get(f'/magazine/{self.issue.slug}/read/full.pdf').status_code, 200)

    def test_partial_digital_discount_keeps_payment_flow(self):
        from apps.store.models import Coupon, DigitalAccess
        Coupon.objects.create(code='HALF', discount_value=50, applies_to='magazines')
        sign_in(self.client)
        self.client.post(f'/magazine/{self.issue.slug}/request-access/',
                         {'name': 'P', 'phone': '01711111111', 'trx_id': 'ABC123XYZ', 'coupon_code': 'half',
                          'accept_terms': 'true'})
        a = DigitalAccess.objects.get()
        self.assertEqual((a.status, a.amount), ('pending', Decimal('50')))


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='', ALLOWED_HOSTS=['testserver'])
class DigitalCheckoutDrawerTests(TestCase):
    """The buy-digital drawer: pay → details → WhatsApp → success, all without leaving the page."""

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    def setUp(self):
        self.issue = Product.objects.create(
            product_type='magazine', title='Lost Trades', slug='lost-trades', description='x', price=Decimal('150'),
            digital_price=Decimal('50'), digital_mode='paid', image=SimpleUploadedFile('c.gif', GIF, content_type='image/gif'),
            pdf_file=SimpleUploadedFile('m.pdf', make_pdf(4), content_type='application/pdf'))
        mag.build_preview(self.issue)
        self.url = f'/magazine/{self.issue.slug}/request-access/'
        self.user = sign_in(self.client, 'karim')

    def send(self, **data):
        body = {'name': 'Karim', 'phone': '01712345678', 'sender_number': '', 'trx_id': 'ABC123XYZ9', 'accept_terms': 'true', **data}
        return self.client.post(self.url, body, HTTP_X_REQUESTED_WITH='fetch')

    def test_buttons_open_the_drawer(self):
        page = self.client.get('/magazine/')
        self.assertContains(page, 'data-buy-digital=')
        self.assertContains(page, 'id="dgPanel"')
        self.assertContains(page, '01967286753')  # the payment number to copy
        detail = self.client.get(self.issue.get_absolute_url())
        self.assertContains(detail, 'id="rtDigitalProduct"')

    def test_success_returns_whatsapp_link_and_unlock_cookie(self):
        r = self.send()
        self.assertEqual(r.status_code, 200)
        d = r.json()
        self.assertTrue(d['ok'])
        self.assertEqual(d['status'], 'pending')
        self.assertTrue(d['whatsapp'].startswith('https://wa.me/8801967286753?text='))
        from urllib.parse import unquote
        text = unquote(d['whatsapp'])
        for part in ('ABC123XYZ9', 'Lost Trades', '৳50', d['reference'], '01712345678'):
            self.assertIn(part, text)
        access = DigitalAccess.objects.get()
        self.assertEqual((access.sender_number, access.amount), ('01712345678', Decimal('50')))  # blank sender = phone
        self.assertIn(f'{mag.COOKIE_PREFIX}{self.issue.pk}', r.cookies)

    def test_errors_come_back_as_json(self):
        self.send()
        r = self.send(trx_id='ABC123XYZ9')  # same TrxID twice
        self.assertEqual(r.status_code, 400)
        self.assertIn('trx_id', r.json()['errors'])
        r = self.send(phone='123', trx_id='NEW1234567')
        self.assertIn('phone', r.json()['errors'])
        self.assertEqual(DigitalAccess.objects.count(), 1)

    def test_coupon_check_and_free_unlock(self):
        from apps.store.models import Coupon
        Coupon.objects.create(code='HALF', discount_type='percentage', discount_value=50)
        Coupon.objects.create(code='FULL', discount_type='percentage', discount_value=100)
        url = f'/magazine/{self.issue.slug}/coupon/'
        self.assertEqual(self.client.get(url, {'code': 'HALF'}).json()['final'], '25')
        bad = self.client.get(url, {'code': 'NOPE'}).json()
        self.assertFalse(bad['ok'])
        self.assertEqual(self.client.get(url, {'code': 'FULL'}).json()['final'], '0')
        d = self.send(trx_id='', coupon_code='FULL').json()
        self.assertEqual(d['status'], 'approved')

    def test_whatsapp_number_setting(self):
        page = StorePageContent.get_solo()
        self.assertEqual(page.whatsapp_digits, '8801967286753')


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='', ALLOWED_HOSTS=['testserver'])
class AccountAndTermsNeededToBuyTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    def setUp(self):
        import json as _json
        self.json = _json
        self.issue = Product.objects.create(
            product_type='magazine', title='Lost Trades', slug='lost-trades', description='x', price=Decimal('150'),
            digital_price=Decimal('50'), digital_mode='paid', image=SimpleUploadedFile('c.gif', GIF, content_type='image/gif'),
            pdf_file=SimpleUploadedFile('m.pdf', make_pdf(4), content_type='application/pdf'))
        mag.build_preview(self.issue)
        self.tee = Product.objects.create(title='Tee', description='x', price=Decimal('600'),
                                          image=SimpleUploadedFile('t.gif', GIF, content_type='image/gif'))

    def digital(self, **extra):
        body = {'name': 'K', 'phone': '01712345678', 'trx_id': 'ABC123XYZ9', **extra}
        return self.client.post(f'/magazine/{self.issue.slug}/request-access/', body, HTTP_X_REQUESTED_WITH='fetch')

    def order(self, **extra):
        body = {'name': 'K', 'phone': '01712345678', 'location': 'Dhaka', 'items': [{'product_id': self.tee.pk, 'quantity': 1}], **extra}
        return self.client.post('/shop/place-order/', self.json.dumps(body), content_type='application/json')

    def test_guests_cannot_buy(self):
        from apps.store.models import Order
        r = self.digital(accept_terms='true')
        self.assertEqual((r.status_code, r.json()['need']), (403, 'login'))
        r = self.order(accept_terms=True)
        self.assertEqual((r.status_code, r.json()['need']), (403, 'login'))
        self.assertEqual((DigitalAccess.objects.count(), Order.objects.count()), (0, 0))
        # Without JavaScript the issue page sends guests to sign in.
        r = self.client.post(f'/magazine/{self.issue.slug}/request-access/', {'name': 'K'})
        self.assertTrue(r['Location'].startswith('/account/login/'))
        # The drawers show the sign-in box instead of a form.
        page = self.client.get('/magazine/')
        self.assertContains(page, 'কিনতে একটি অ্যাকাউন্ট দরকার')
        self.assertNotContains(page, 'id="dgForm"')

    def test_unticked_terms_blocks_and_ticked_terms_is_recorded(self):
        user = sign_in(self.client)
        self.assertEqual(self.digital().json()['need'], 'terms')
        self.assertEqual(self.order(accept_terms=False).json()['need'], 'terms')
        self.assertIsNone(User.objects.get(pk=user.pk).profile.terms_accepted_at)
        self.assertTrue(self.order(accept_terms=True).json()['success'])
        self.assertIsNotNone(User.objects.get(pk=user.pk).profile.terms_accepted_at)
        page = self.client.get('/magazine/')
        self.assertContains(page, 'id="dgTerms" checked')  # ticked by default

    def test_signup_and_login_need_terms(self):
        data = {'name': 'Rahim', 'email': 'r@example.com', 'password1': 'History-1971-Dhaka',
                'password2': 'History-1971-Dhaka'}
        r = self.client.post('/account/signup/', data)
        self.assertContains(r, 'শর্তাবলী ও গোপনীয়তা নীতি মেনে নিতে হবে')
        self.assertFalse(User.objects.filter(email='r@example.com').exists())
        self.client.post('/account/signup/', {**data, 'accept_terms': 'on'})
        u = User.objects.get(email='r@example.com')
        self.assertIsNotNone(u.profile.terms_accepted_at)
        self.client.logout()
        r = self.client.post('/account/login/', {'identifier': 'r@example.com', 'password': 'History-1971-Dhaka'})
        self.assertEqual(r.status_code, 200)  # stays on the form
        self.assertNotIn('_auth_user_id', self.client.session)
        self.assertContains(self.client.get('/account/signup/'), 'name="accept_terms"')

    def test_terms_pages_exist(self):
        for url, text in (('/terms-and-conditions/', 'ডিজিটাল ম্যাগাজিন'), ('/privacy-policy/', 'কুকি')):
            self.assertContains(self.client.get(url), text)


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='', ALLOWED_HOSTS=['testserver'])
class OwnedIssueButtonsTests(TestCase):
    """Readers who already bought an issue see a read button, not a buy button."""

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    def setUp(self):
        self.issue = Product.objects.create(
            product_type='magazine', title='Lost Trades', slug='lost-trades', description='x', price=Decimal('150'),
            digital_price=Decimal('50'), digital_mode='paid', is_featured=True,
            image=SimpleUploadedFile('c.gif', GIF, content_type='image/gif'),
            pdf_file=SimpleUploadedFile('m.pdf', make_pdf(4), content_type='application/pdf'))
        mag.build_preview(self.issue)

    def buy(self, status):
        user = sign_in(self.client)
        DigitalAccess.objects.create(product=self.issue, user=user, name='K', phone='01712345678',
                                     sender_number='01712345678', trx_id='OWN' + status.upper(), amount=50, status=status)

    def test_owner_sees_read_not_buy(self):
        self.buy('approved')
        for url in ('/magazine/', self.issue.get_absolute_url()):
            page = self.client.get(url)
            self.assertNotContains(page, 'data-buy-digital=')
            self.assertNotContains(page, 'ডিজিটাল সংস্করণ কিনুন')
        self.assertContains(self.client.get('/magazine/'), 'পুরো সংখ্যা পড়ুন')
        self.assertContains(self.client.get(self.issue.get_absolute_url()), 'পূর্ণ সংখ্যা পড়ুন')

    def test_waiting_reader_sees_status(self):
        self.buy('pending')
        page = self.client.get('/magazine/')
        self.assertContains(page, 'অনুমোদনের অপেক্ষায়')
        self.assertNotContains(page, 'data-buy-digital=')

    def test_other_readers_still_see_buy(self):
        self.buy('approved')
        self.client.logout()
        sign_in(self.client, 'someone-else')
        self.assertContains(self.client.get('/magazine/'), 'data-buy-digital=')
        self.client.logout()
        self.assertContains(self.client.get('/magazine/'), 'data-buy-digital=')


@override_settings(MEDIA_ROOT=TMP, TELEGRAM_BOT_TOKEN='', ALLOWED_HOSTS=['testserver'],
                   EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')
class DigitalOrderEmailTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        private_storage.location = TMP

    def test_each_digital_order_is_emailed_to_the_team(self):
        from django.core import mail
        issue = Product.objects.create(
            product_type='magazine', title='Lost Trades', slug='lost-trades', description='x', price=Decimal('150'),
            digital_price=Decimal('50'), digital_mode='paid', image=SimpleUploadedFile('c.gif', GIF, content_type='image/gif'),
            pdf_file=SimpleUploadedFile('m.pdf', make_pdf(4), content_type='application/pdf'))
        mag.build_preview(issue)
        sign_in(self.client)
        r = self.client.post(f'/magazine/{issue.slug}/request-access/',
                             {'name': 'Karim', 'phone': '01712345678', 'trx_id': 'MAIL123XYZ', 'accept_terms': 'true'},
                             HTTP_X_REQUESTED_WITH='fetch')
        self.assertTrue(r.json()['ok'])
        self.assertEqual(len(mail.outbox), 1)
        m = mail.outbox[0]
        self.assertEqual(m.to, ['sazzadbytes@gmail.com'])
        self.assertIn('Lost Trades', m.subject)
        self.assertIn('MAIL123XYZ', m.body)
        self.assertIn('/admin/store/digitalaccess/', m.body)
        # The address can be changed (or switched off) in the admin.
        page = StorePageContent.get_solo()
        page.order_email = ''
        page.save()
        self.client.post(f'/magazine/{issue.slug}/request-access/',
                         {'name': 'Karim', 'phone': '01712345678', 'trx_id': 'MAIL999XYZ', 'accept_terms': 'true'},
                         HTTP_X_REQUESTED_WITH='fetch')
        self.assertEqual(len(mail.outbox), 1)
