"""Subscription limit checks and monthly usage tracking."""
from django.utils import timezone

from jobs.models import Job

from .models import SubscriptionUsageEvent
from .plan_limits import DEFAULT_COMPANY_NO_SUB, DEFAULT_SEEKER_FREE


def month_start(now=None):
    now = now or timezone.now()
    return now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)


def get_seeker_benefits(user):
    if not user or not getattr(user, 'is_authenticated', False):
        return DEFAULT_SEEKER_FREE
    if user.is_platform_admin:
        from .plan_limits import get_seeker_plan_benefits
        from django.conf import settings
        return get_seeker_plan_benefits(settings.SEEKER_PLUS_PLAN_SLUG)

    subscription = getattr(user, 'seeker_subscription', None)
    if subscription and subscription.is_valid:
        return subscription.effective_benefits
    return DEFAULT_SEEKER_FREE


def _platform_admin_company_benefits():
    from django.conf import settings

    from .plan_limits import get_company_plan_benefits

    return get_company_plan_benefits(settings.COMPANY_ENTERPRISE_PLAN_SLUG)


def _company_owned_by_platform_admin(company):
    owner = getattr(company, 'owner', None)
    return bool(owner and owner.is_platform_admin)


def get_company_benefits(company, user=None):
    if not company:
        return DEFAULT_COMPANY_NO_SUB

    if user and user.is_platform_admin:
        return _platform_admin_company_benefits()
    if _company_owned_by_platform_admin(company):
        return _platform_admin_company_benefits()

    subscription = getattr(company, 'subscription', None)
    if subscription and subscription.is_valid:
        return subscription.effective_benefits
    return DEFAULT_COMPANY_NO_SUB


def company_jobs_posted_this_month(company):
    if not company or not company.owner_id:
        return 0
    return Job.objects.filter(
        posted_by_id=company.owner_id,
        created_at__gte=month_start(),
    ).count()


def company_usage_count(company, event_type, since=None):
    since = since or month_start()
    return SubscriptionUsageEvent.objects.filter(
        company=company,
        event_type=event_type,
        created_at__gte=since,
    ).count()


def company_profile_views_this_month(company):
    return company_usage_count(company, SubscriptionUsageEvent.EventType.CV_PROFILE_VIEW)


def company_cv_downloads_this_month(company):
    return company_usage_count(company, SubscriptionUsageEvent.EventType.CV_DOWNLOAD)


def can_company_post_job(company, user=None):
    if user and user.is_platform_admin:
        return True, ''

    benefits = get_company_benefits(company)
    if benefits.job_posts_per_month == 0:
        return False, 'Your company needs an active recruitment subscription to post jobs.'

    if benefits.job_posts_per_month is None:
        return True, ''

    used = company_jobs_posted_this_month(company)
    if used >= benefits.job_posts_per_month:
        return False, (
            f'Monthly job limit reached ({benefits.job_posts_per_month}). '
            'Upgrade your plan to post more jobs.'
        )
    return True, ''


def can_company_view_profile(company, user=None):
    if user and user.is_platform_admin:
        return True, ''

    benefits = get_company_benefits(company)
    if benefits.cv_profile_views_per_month == 0:
        return False, 'Your company needs an active subscription to search the talent database.'

    if benefits.cv_profile_views_per_month is None:
        return True, ''

    used = company_profile_views_this_month(company)
    if used >= benefits.cv_profile_views_per_month:
        return False, (
            f'Monthly candidate profile limit reached ({benefits.cv_profile_views_per_month}). '
            'Upgrade your plan for more searches.'
        )
    return True, ''


def can_company_download_cv(company, user=None):
    if user and user.is_platform_admin:
        return True, ''

    benefits = get_company_benefits(company)
    if not benefits.can_download_cv:
        return False, 'CV downloads require a Professional plan or higher.'

    if benefits.cv_downloads_per_month is None:
        return True, ''

    used = company_cv_downloads_this_month(company)
    if used >= benefits.cv_downloads_per_month:
        return False, (
            f'Monthly CV download limit reached ({benefits.cv_downloads_per_month}). '
            'Upgrade your plan for more downloads.'
        )
    return True, ''


def can_company_message(company, user=None):
    if user and user.is_platform_admin:
        return True, ''

    benefits = get_company_benefits(company)
    if benefits.can_message:
        return True, ''
    return False, 'Messaging candidates requires a Professional plan or higher.'


def can_seeker_save_job(user):
    benefits = get_seeker_benefits(user)
    if benefits.saved_jobs_limit is None:
        return True, ''

    from jobs.models import SavedJob
    count = SavedJob.objects.filter(user=user).count()
    if count >= benefits.saved_jobs_limit:
        return False, (
            f'Saved job limit reached ({benefits.saved_jobs_limit}). '
            'Upgrade to Professional Plus for unlimited saved jobs.'
        )
    return True, ''


def record_profile_view(company, profile, actor):
    if SubscriptionUsageEvent.objects.filter(
        company=company,
        event_type=SubscriptionUsageEvent.EventType.CV_PROFILE_VIEW,
        seeker_profile=profile,
        created_at__gte=month_start(),
    ).exists():
        return False

    SubscriptionUsageEvent.objects.create(
        company=company,
        actor=actor,
        event_type=SubscriptionUsageEvent.EventType.CV_PROFILE_VIEW,
        seeker_profile=profile,
    )
    return True


def profile_viewed_this_month(company, profile):
    return SubscriptionUsageEvent.objects.filter(
        company=company,
        event_type=SubscriptionUsageEvent.EventType.CV_PROFILE_VIEW,
        seeker_profile=profile,
        created_at__gte=month_start(),
    ).exists()


def record_cv_download(company, profile, actor):
    SubscriptionUsageEvent.objects.create(
        company=company,
        actor=actor,
        event_type=SubscriptionUsageEvent.EventType.CV_DOWNLOAD,
        seeker_profile=profile,
    )


def _company_cv_library_subscription(company):
    if not company:
        return None
    subscription = getattr(company, 'subscription', None)
    if not subscription or not subscription.is_valid:
        return None
    return subscription


def company_has_cv_library_subscription(company):
    """True when the company has an active CV Search (Talent Database) subscription."""
    subscription = _company_cv_library_subscription(company)
    if not subscription:
        return False
    from subscriptions.models import SubscriptionPlan

    if subscription.plan.category != SubscriptionPlan.Category.TALENT_DATABASE:
        return False
    return subscription.effective_benefits.can_access_cv_library


def can_company_access_cv_library(company, user=None):
    if user and user.is_platform_admin:
        return True, ''

    if not company:
        return False, 'Set up your company profile before accessing the CV library.'

    subscription = _company_cv_library_subscription(company)
    if not subscription:
        return False, (
            'CV library access requires an active CV Search subscription '
            '(Talent Database - Basic, Plus, or Unlimited).'
        )

    from subscriptions.models import SubscriptionPlan

    if subscription.plan.category != SubscriptionPlan.Category.TALENT_DATABASE:
        return False, (
            'CV library search and bulk download is only available on CV Search subscriptions. '
            'Recruitment plans can download individual CVs from candidate profiles, but not the full library.'
        )

    benefits = subscription.effective_benefits
    if not benefits.can_access_cv_library:
        return False, (
            'Your current plan does not include CV library access. '
            'Subscribe to CV Search Basic, Plus, or Unlimited.'
        )
    return True, ''


def company_has_ats_subscription(company, user=None):
    """True when the company has an active recruitment plan that includes ATS access."""
    if user and user.is_platform_admin:
        return True
    if company and _company_owned_by_platform_admin(company):
        return True
    if not company:
        return False
    subscription = getattr(company, 'subscription', None)
    if not subscription or not subscription.is_valid:
        return False
    return subscription.effective_benefits.can_access_ats


def company_application_delivery_method(company):
    """Effective channel for new applications: 'ats' only when the company both
    subscribes to a plan with ATS access and has chosen to receive applications
    that way; otherwise applications go to the company's own email."""
    from companies.models import Company

    if company and _company_owned_by_platform_admin(company):
        return Company.ApplicationDelivery.ATS
    if company and company_has_ats_subscription(company) and (
        company.application_delivery_method == Company.ApplicationDelivery.ATS
    ):
        return Company.ApplicationDelivery.ATS
    return Company.ApplicationDelivery.EMAIL


def job_accepts_pezajob_applications(job, company=None):
    from companies.models import Company
    from jobs.models import Job

    if Job.ApplicationMethod.PEZAJOB not in job.get_application_methods():
        return False
    if job.posted_by and job.posted_by.is_platform_admin:
        return True
    return company_application_delivery_method(company) == Company.ApplicationDelivery.ATS


def job_accepts_external_applications(job):
    from jobs.models import Job

    return Job.ApplicationMethod.EXTERNAL in job.get_application_methods()


def job_application_delivery_method(job, company=None):
    """Effective application channel for the in-platform apply button."""
    from companies.models import Company

    if job_accepts_pezajob_applications(job, company):
        return Company.ApplicationDelivery.ATS
    return Company.ApplicationDelivery.EMAIL


def can_company_use_ats(company, user=None):
    if user and user.is_platform_admin:
        return True, ''

    if not company:
        return False, 'Set up your company profile before using the applicant tracking system.'

    subscription = getattr(company, 'subscription', None)
    if not subscription or not subscription.is_valid:
        return False, (
            'Accepting applications through PEZAJOB requires an active recruitment '
            'subscription (Professional, Recruiter Pro, or Enterprise).'
        )

    if not subscription.effective_benefits.can_access_ats:
        return False, (
            'Your current plan does not include applicant tracking. '
            'Upgrade to Professional or higher to accept applications through PEZAJOB.'
        )
    return True, ''


def can_company_bulk_download_cvs(company, user, count):
    if user and user.is_platform_admin:
        return True, ''

    allowed, message = can_company_access_cv_library(company, user)
    if not allowed:
        return False, message

    if count <= 0:
        return False, 'Select at least one CV to download.'

    benefits = get_company_benefits(company)
    if benefits.cv_downloads_per_month is None:
        return True, ''

    used = company_cv_downloads_this_month(company)
    remaining = benefits.cv_downloads_per_month - used
    if count > remaining:
        return False, (
            f'You can download {max(remaining, 0)} more CV(s) this month '
            f'(requested {count}). Upgrade for a higher limit.'
        )
    return True, ''


def record_bulk_cv_downloads(company, profiles, actor):
    for profile in profiles:
        record_cv_download(company, profile, actor)


def company_usage_summary(company):
    benefits = get_company_benefits(company)
    return {
        'benefits': benefits,
        'jobs_posted': company_jobs_posted_this_month(company),
        'profile_views': company_profile_views_this_month(company),
        'cv_downloads': company_cv_downloads_this_month(company),
    }
