"""Integration tests for PEZAJOB core features."""
from django.contrib.auth import get_user_model
from django.core import mail
from django.test import Client, TestCase
from django.urls import reverse

from accounts.models import User
from ats.cv_parser import extract_skills_from_text, parse_text_content
from ats.services import compute_match_score, explain_match_score, parse_application_content, process_application_scoring
from companies.models import Company
from jobs.matching import compute_seeker_job_match
from jobs.models import Job, JobApplication, JobCategory
from seekers.models import SeekerProfile
from subscriptions.models import SeekerSubscription, SubscriptionPlan

UserModel = get_user_model()


class PublicPageTests(TestCase):
    def setUp(self):
        self.client = Client()

    def test_public_pages_load(self):
        pages = [
            'home:index',
            'home:about',
            'home:contact',
            'home:partner',
            'home:services',
            'home:health',
            'jobs:list',
            'seekers:list',
            'companies:list',
            'blog:list',
            'podcast:list',
            'subscriptions:pricing',
            'accounts:login',
            'accounts:register',
        ]
        for name in pages:
            with self.subTest(url=name):
                response = self.client.get(reverse(name))
                self.assertLess(response.status_code, 500, msg=f'{name} returned {response.status_code}')

    def test_api_endpoints(self):
        endpoints = [
            '/api/home/',
            '/api/jobs/',
            '/api/companies/',
            '/api/seekers/',
            '/api/plans/',
        ]
        for path in endpoints:
            with self.subTest(path=path):
                response = self.client.get(path)
                self.assertLess(response.status_code, 500)


class FeatureWorkflowTests(TestCase):
    def setUp(self):
        self.client = Client()
        self.category = JobCategory.objects.create(name='Technology', slug='technology')

        self.employer = UserModel.objects.create_user(
            username='test_employer',
            email='test_employer@pezajob.com',
            password='TestPass123!',
            role=User.Role.COMPANY,
        )
        self.company = Company.objects.create(
            slug='test-co',
            name='Test Company',
            initials='TC',
            industry='Technology',
            industry_slug='technology',
            location='Lusaka',
            owner=self.employer,
        )

        self.seeker = UserModel.objects.create_user(
            username='test_seeker',
            email='test_seeker@pezajob.com',
            password='TestPass123!',
            role=User.Role.SEEKER,
        )
        self.profile = SeekerProfile.objects.create(
            user=self.seeker,
            slug='test-seeker',
            full_name='Test Seeker',
            headline='Python Developer',
            category='Technology',
            category_slug='technology',
            location='Lusaka',
            skills='Python\nDjango\nPostgreSQL\nJavaScript',
            bio='Experienced Python developer.',
            is_public=True,
        )

        self.plan, _ = SubscriptionPlan.objects.get_or_create(
            slug='seeker-professional-plus',
            defaults={
                'name': 'Professional Plus',
                'audience': SubscriptionPlan.Audience.SEEKER,
                'category': SubscriptionPlan.Category.MEMBERSHIP,
                'price_monthly': 20,
                'features': 'Priority job alerts',
            },
        )
        SeekerSubscription.objects.create(user=self.seeker, plan=self.plan, is_active=True)

        self.job = Job.objects.create(
            title='Backend Developer',
            slug='test-backend-developer',
            company_name='Test Company',
            company_slug='test-co',
            company_initials='TC',
            location='Lusaka',
            category=self.category,
            description='Python backend role.',
            responsibilities='Build APIs\nWrite tests',
            requirements='Python\nDjango\n3+ years experience',
            nice_to_have='AWS\nDocker',
            posted_by=self.employer,
            is_active=True,
        )

    def test_seeker_job_matching(self):
        score = compute_seeker_job_match(self.profile, self.job)
        self.assertGreaterEqual(score, 40)
        self.assertLessEqual(score, 100)

    def test_cv_skill_extraction(self):
        skills = extract_skills_from_text(
            'Senior developer with Python, Django, PostgreSQL, and AWS experience.',
            job=self.job,
            profile_skills=self.profile.skill_list,
        )
        self.assertIn('Python', [s.title() if s.lower() == 'python' else s for s in skills] or skills)
        parsed = parse_text_content(self.profile.skills, job=self.job, profile_skills=self.profile.skill_list)
        self.assertTrue(parsed['skills'])

    def test_job_application_and_ats_scoring(self):
        application = JobApplication.objects.create(
            job=self.job,
            applicant=self.seeker,
            cover_letter='I have strong Python and Django experience.',
        )
        process_application_scoring(application, parse_content=True)
        application.refresh_from_db()
        self.assertGreater(application.match_score, 0)
        self.assertTrue(application.cv_parsed_text)

    def test_job_alert_dispatch(self):
        mail.outbox.clear()
        Job.objects.create(
            title='Django Engineer',
            slug='test-django-engineer-alert',
            company_name='Test Company',
            company_slug='test-co',
            company_initials='TC',
            location='Lusaka',
            category=self.category,
            description='Django engineer needed.',
            responsibilities='Develop features',
            requirements='Python\nDjango\nREST APIs',
            posted_by=self.employer,
            is_active=True,
        )
        self.assertGreaterEqual(len(mail.outbox), 1)
        self.assertIn('Job alert', mail.outbox[0].subject)

    def test_authenticated_dashboards(self):
        self.client.login(username='test_seeker', password='TestPass123!')
        for name in ('seekers:dashboard', 'seekers:applications', 'messaging:inbox', 'accounts:settings'):
            with self.subTest(url=name):
                response = self.client.get(reverse(name))
                self.assertLess(response.status_code, 500)

        self.client.logout()
        self.client.login(username='test_employer', password='TestPass123!')
        for name in ('employers:dashboard', 'employers:post_job', 'ats:pipeline', 'accounts:settings'):
            with self.subTest(url=name):
                response = self.client.get(reverse(name))
                self.assertLess(response.status_code, 500)

    def test_job_detail_and_apply_page(self):
        response = self.client.get(self.job.get_absolute_url())
        self.assertEqual(response.status_code, 200)

    def test_compute_match_score_on_application(self):
        application = JobApplication.objects.create(
            job=self.job,
            applicant=self.seeker,
            cover_letter='Python Django developer',
        )
        parse_application_content(application)
        score = compute_match_score(application)
        self.assertGreater(score, 0)

    def test_explain_match_score_breakdown(self):
        application = JobApplication.objects.create(
            job=self.job,
            applicant=self.seeker,
            cover_letter='Python Django developer with REST API experience',
        )
        parse_application_content(application)
        breakdown = explain_match_score(application)
        self.assertIn('score', breakdown)
        self.assertIn('summary', breakdown)
        self.assertEqual(breakdown['score'], compute_match_score(application))
        self.assertTrue(breakdown['summary'])


class AboutPageRealStatsTests(TestCase):
    def test_about_counters_show_real_counts(self):
        import re

        from home.stats import get_platform_stats

        stats = get_platform_stats()
        html = self.client.get(reverse('home:about')).content.decode()
        counters = [tuple(int(x) for x in m) for m in re.findall(r'counter" data-target="(\d+)">(\d+)', html)]
        self.assertEqual(counters, [(stats['jobs'],) * 2, (stats['companies'],) * 2, (stats['seekers'],) * 2])
        self.assertNotIn('150,000', html)


class CategoriesPageTests(TestCase):
    def test_all_categories_page_lists_every_active_category(self):
        from jobs.models import JobCategory

        response = self.client.get(reverse('jobs:categories'))
        self.assertEqual(response.status_code, 200)
        active = JobCategory.active().count()
        self.assertEqual(len(response.context['categories']), active)
        self.assertContains(response, 'All Job Categories')

    def test_homepage_links_to_the_categories_page_and_shows_eight_tiles(self):
        html = self.client.get(reverse('home:index')).content.decode()
        self.assertIn(reverse('jobs:categories'), html)
        self.assertLessEqual(html.count('class="category-card"'), 8)


class CleanContentTests(TestCase):
    def test_strip_emoji_keeps_text_and_turns_leading_emoji_into_list_markers(self):
        from home.textclean import strip_emoji

        self.assertEqual(strip_emoji('\U0001F4E2 Mobile Sales Agents'), 'Mobile Sales Agents')
        self.assertEqual(strip_emoji('\u25aa\ufe0f Meet targets\n\U0001F539 Report weekly', bullets=True), '- Meet targets\n- Report weekly')
        self.assertEqual(strip_emoji('Plain text stays the same.'), 'Plain text stays the same.')

    def test_job_and_notification_text_is_saved_without_emoji(self):
        from accounts.models import User, UserNotification
        from jobs.models import Job, JobCategory

        owner = User.objects.create_user(username='ec', email='ec@x.com', password='pw12345!', role=User.Role.COMPANY)
        cat = JobCategory.objects.create(name='Clean Cat', slug='clean-cat')
        job = Job.objects.create(title='\U0001F4E2 Cashier', slug='cashier-clean', company_name='C', company_slug='c', company_initials='C',
                                 location='Lusaka', category=cat, description='\U0001F539 Handle payments', requirements='r', posted_by=owner, is_active=True)
        self.assertEqual(job.title, 'Cashier')
        self.assertEqual(job.description, '- Handle payments')
        note = UserNotification.objects.create(recipient=owner, title='\u2705 New role', body='\U0001F4E2 Cashier is open')
        self.assertEqual((note.title, note.body), ('New role', 'Cashier is open'))

    def test_public_pages_contain_no_emoji_or_stock_photos(self):
        import re

        from home.textclean import _EMOJI_RUN

        for name in ('home:index', 'home:about', 'home:services', 'home:contact', 'home:faq', 'jobs:list', 'companies:list'):
            html = self.client.get(reverse(name)).content.decode()
            visible = re.sub(r'<(script|style)[^>]*>.*?</\1>', '', html, flags=re.S)
            self.assertFalse(_EMOJI_RUN.search(visible), name)
            self.assertNotIn('unsplash', html, name)
