"""Tests for seeker profile privacy and CV viewing."""
import io

from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import Client, TestCase
from django.urls import reverse

from companies.models import Company
from seekers.models import SeekerProfile
from subscriptions.models import CompanySubscription, SubscriptionPlan

User = get_user_model()


def _starter_plan():
    plan, _ = SubscriptionPlan.objects.get_or_create(
        slug='company-starter',
        defaults={
            'name': 'Starter',
            'audience': SubscriptionPlan.Audience.COMPANY,
            'category': SubscriptionPlan.Category.RECRUITMENT,
            'price_monthly': 500,
            'features': 'Profile views',
        },
    )
    plan.category = SubscriptionPlan.Category.RECRUITMENT
    plan.save(update_fields=['category'])
    return plan


def _professional_plan():
    plan, _ = SubscriptionPlan.objects.get_or_create(
        slug='company-professional',
        defaults={
            'name': 'Professional',
            'audience': SubscriptionPlan.Audience.COMPANY,
            'category': SubscriptionPlan.Category.RECRUITMENT,
            'price_monthly': 1000,
            'features': 'CV downloads',
        },
    )
    plan.category = SubscriptionPlan.Category.RECRUITMENT
    plan.save(update_fields=['category'])
    return plan


class SeekerProfilePrivacyTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.seeker_a = User.objects.create_user(
            username='seeker_a',
            email='seeker-a@test.com',
            password='pass12345',
            role='seeker',
        )
        cls.seeker_b_user = User.objects.create_user(
            username='seeker_b',
            email='seeker-b@test.com',
            password='pass12345',
            role='seeker',
        )
        cls.profile_b = SeekerProfile.objects.create(
            user=cls.seeker_b_user,
            slug='privacy-candidate',
            full_name='Hidden Candidate',
            headline='Accountant',
            category='Finance',
            category_slug='finance',
            location='Lusaka',
            skills='Excel\nQuickBooks',
            bio='Detailed bio that should stay hidden from other seekers.',
            is_public=True,
            cv_file=SimpleUploadedFile(
                'hidden_cv.pdf',
                b'%PDF-1.4 test content',
                content_type='application/pdf',
            ),
        )

        cls.employer = User.objects.create_user(
            username='sub_employer',
            email='employer@test.com',
            password='pass12345',
            role='company',
        )
        cls.company = Company.objects.create(
            owner=cls.employer,
            name='Subscribed Co',
            slug='subscribed-co',
            industry='Finance',
            industry_slug='finance',
            location='Lusaka',
            is_active=True,
        )
        cls.starter_plan = _starter_plan()
        CompanySubscription.objects.create(
            company=cls.company,
            plan=cls.starter_plan,
            is_active=True,
        )

        cls.pro_employer = User.objects.create_user(
            username='pro_employer',
            email='pro-employer@test.com',
            password='pass12345',
            role='company',
        )
        cls.pro_company = Company.objects.create(
            owner=cls.pro_employer,
            name='Pro Co',
            slug='pro-co',
            industry='Finance',
            industry_slug='finance',
            location='Lusaka',
            is_active=True,
        )
        cls.pro_plan = _professional_plan()
        CompanySubscription.objects.create(
            company=cls.pro_company,
            plan=cls.pro_plan,
            is_active=True,
        )

    def setUp(self):
        self.client = Client()

    def test_seeker_sees_profession_only_on_detail(self):
        self.client.login(username='seeker_a', password='pass12345')
        response = self.client.get(
            reverse('seekers:detail', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'Accountant')
        self.assertContains(response, 'Finance')
        self.assertNotContains(response, 'Hidden Candidate')
        self.assertNotContains(response, 'Detailed bio that should stay hidden')

    def test_seeker_list_hides_full_name(self):
        self.client.login(username='seeker_a', password='pass12345')
        response = self.client.get(reverse('seekers:list'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'Accountant')
        self.assertNotContains(response, 'Hidden Candidate')

    def test_subscribed_company_sees_full_profile(self):
        self.client.login(username='sub_employer', password='pass12345')
        response = self.client.get(
            reverse('seekers:detail', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'Hidden Candidate')
        self.assertContains(response, 'Detailed bio that should stay hidden')

    def test_subscribed_company_can_view_cv_in_browser(self):
        self.client.login(username='sub_employer', password='pass12345')
        response = self.client.get(
            reverse('seekers:view_cv', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'Back to profile')
        self.assertContains(response, 'cv-view-frame')

        file_response = self.client.get(
            reverse('seekers:serve_cv', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(file_response.status_code, 200)
        self.assertIn('inline', file_response['Content-Disposition'])
        self.assertIn('hidden_cv', file_response['Content-Disposition'])

    def test_seeker_cannot_access_cv_file(self):
        self.client.login(username='seeker_a', password='pass12345')
        response = self.client.get(
            reverse('seekers:serve_cv', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(response.status_code, 404)

    def test_starter_plan_can_view_but_not_download_cv(self):
        self.client.login(username='sub_employer', password='pass12345')
        view_response = self.client.get(
            reverse('seekers:view_cv', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(view_response.status_code, 200)

        download_response = self.client.get(
            reverse('seekers:download_cv', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(download_response.status_code, 302)
        self.assertRedirects(
            download_response,
            reverse('seekers:detail', kwargs={'slug': self.profile_b.slug}),
        )

    def test_professional_plan_can_download_cv(self):
        self.client.login(username='pro_employer', password='pass12345')
        response = self.client.get(
            reverse('seekers:download_cv', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(response.status_code, 200)
        self.assertIn('attachment', response['Content-Disposition'])

    def test_unsubscribed_company_sees_profession_only(self):
        unsubscribed = User.objects.create_user(
            username='free_employer',
            email='free@test.com',
            password='pass12345',
            role='company',
        )
        Company.objects.create(
            owner=unsubscribed,
            name='Free Co',
            slug='free-co',
            industry='Finance',
            industry_slug='finance',
            location='Lusaka',
            is_active=True,
        )
        self.client.login(username='free_employer', password='pass12345')
        response = self.client.get(
            reverse('seekers:detail', kwargs={'slug': self.profile_b.slug})
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'Accountant')
        self.assertNotContains(response, 'Hidden Candidate')
