import json
import logging
import requests
from django.shortcuts import render, redirect
from django.conf import settings
from django.http import JsonResponse
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from .models import ContactEnquiry
from apps.tickets.models import Ticket
from apps.pages.models import SiteSettings
from apps.sales.models import ProjectAssessment

log = logging.getLogger(__name__)


def _rc_site_key():
    """The public reCAPTCHA key, from Settings. Never from .env."""
    from apps.pages.api_keys import get_recaptcha_site_key
    return get_recaptcha_site_key()


def _send_assessment_emails(assessment, ticket):
    """Send confirmation to client and notification to support@finaltarget.com."""
    try:
        from django.core.mail import send_mail

        # Reference follows the house formula, FT + yy + mm + sequence, the same
        # shape as order numbers. A bare primary key told the client their brief
        # was number 9.
        ref = getattr(ticket, 'ticket_number', '') if ticket else ''
        if not ref:
            created = getattr(assessment, 'created_at', None) or timezone.now()
            from apps.tenants.refs import stem, BRIEF
            ref = f'{stem(BRIEF, getattr(assessment, "tenant", None), created)}{assessment.pk:04d}'

        # Domains come from settings rather than being hard coded. These read
        # finaltarget.co.uk while the business runs on finaltarget.com.
        site_url = (getattr(settings, 'SITE_URL', '') or 'https://finaltarget.com').rstrip('/')
        site_domain = site_url.split('//')[-1]
        support_email = _outgoing() or f'support@{site_domain}'
        panel_url = f'https://panel.{site_domain}'

        # 1 — Client confirmation
        from apps.pages.branding import company_name
        _co = company_name(getattr(assessment, 'tenant', None))
        client_subject = f'We received your project brief, {_co} (Ref: {ref})'
        try:
            from apps.ecommerce.email_utils import _send
            _send(
                subject=client_subject,
                to=assessment.email,
                template='public/emails/assessment_received.html',
                email_type='assessment',
                context={
                    'client_name':   assessment.name,
                    'reference':     ref,
                    'service':       assessment.service_types_display,
                    'budget':        assessment.get_budget_display(),
                    'timeline':      assessment.get_timeline_display(),
                    'portfolio_url': f'{site_url}/portfolio',
                    'site_url':      site_url,
                    'site_domain':   site_domain,
                },
            )
        except Exception:
            send_mail(
                subject=client_subject,
                message=(
                    f'Hi {assessment.name},\n\n'
                    f'Thank you for reaching out to {_co}. We have received your '
                    f'project brief and one of our team will be in touch within 5 business days.\n\n'
                    f'Your reference number is: {ref}\n\n'
                    f'Best regards,\nThe {_co} Team\n{site_url}\n'
                ),
                from_email=support_email,
                recipient_list=[assessment.email],
                fail_silently=True,
            )

        # 2 — Internal notification to support
        features = ', '.join(assessment.features_list) if assessment.features_list else 'None specified'
        internal_subject = f'New Project Assessment — {assessment.name} ({assessment.service_types_display}) [Ref: {ref}]'
        internal_body = (
            f'A new project assessment has been submitted.\n\n'
            f'Client: {assessment.name}\n'
            f'Email: {assessment.email}\n'
            f'Phone: {assessment.phone or "Not provided"}\n'
            f'Company: {assessment.company or "Not provided"}\n\n'
            f'Service: {assessment.service_types_display}\n'
            f'Budget: {assessment.get_budget_display()}\n'
            f'Timeline: {assessment.get_timeline_display()}\n'
            f'Features: {features}\n\n'
            f'Description:\n{assessment.project_description or "Not provided"}\n\n'
            f'Reference sites: {assessment.reference_sites or "None"}\n\n'
            f'View in the panel: {panel_url}/assessments/{assessment.pk}/\n'
        )
        send_mail(
            subject=internal_subject,
            message=internal_body,
            from_email=support_email,
            recipient_list=[support_email],
            fail_silently=True,
        )
    except Exception:
        pass  # Never block submission if email fails


def _ai_analyse_assessment(assessment):
    """Call OpenAI to generate a project label + feasibility score. Non-blocking."""
    try:
        from openai import OpenAI
        from apps.pages.api_keys import get_openai_api_key
        api_key = get_openai_api_key()
        if not api_key:
            return

        features = ', '.join(assessment.features_list) if assessment.features_list else 'None specified'

        prompt = f"""You are a UK digital agency quoting expert. Analyse this project brief and respond ONLY with valid JSON.

Project brief:
- Service: {assessment.service_types_display}
- Budget: {assessment.get_budget_display()}
- Timeline: {assessment.get_timeline_display()}
- Features requested: {features}
- Description: {assessment.project_description or 'Not provided'}

Return JSON with exactly these keys:
{{
  "label": "A concise 5-10 word label describing the project (e.g. 'E-commerce Store with Login & Payments')",
  "feasibility_score": <integer 0-100 — how achievable is this given budget AND timeline vs UK market rates>,
  "market_note": "2-3 sentences: typical UK market cost for this type of project, whether the budget/timeline is realistic, and what scope might need adjusting if not.",
  "verdict": "<one of: feasible | possible_reduced_scope | challenging | unrealistic>"
}}

Scoring guide:
- 80-100: budget and timeline both match UK market for stated scope
- 50-79: achievable but scope will need to be reduced or timeline extended
- 20-49: budget or timeline is significantly below market — major scope reduction needed
- 0-19: budget/timeline are far below what this type of project costs in the UK market"""

        client = OpenAI(api_key=api_key)
        resp = client.chat.completions.create(
            model='gpt-4o-mini',
            messages=[{'role': 'user', 'content': prompt}],
            max_tokens=400,
            temperature=0.3,
            response_format={'type': 'json_object'},
        )
        data = json.loads(resp.choices[0].message.content)

        assessment.ai_label            = str(data.get('label', ''))[:200]
        assessment.ai_feasibility_score = max(0, min(100, int(data.get('feasibility_score', 0))))
        assessment.ai_market_note       = str(data.get('market_note', ''))
        assessment.ai_verdict           = str(data.get('verdict', ''))[:30]
        assessment.ai_analysed_at       = timezone.now()
        assessment.save(update_fields=[
            'ai_label', 'ai_feasibility_score', 'ai_market_note',
            'ai_verdict', 'ai_analysed_at',
        ])
    except Exception:
        pass  # Never block the submission if AI fails


def _get_tenant(request):
    tenant = getattr(request, 'tenant', None)
    if tenant is None or getattr(tenant, 'pk', 0) == 0:
        try:
            from apps.tenants.models import Tenant
            return Tenant.objects.get(is_master=True)
        except Exception:
            return None
    return tenant


def contact(request):
    tenant = _get_tenant(request)
    site = SiteSettings.load(tenant)

    if request.method == 'POST':
        from apps.contact import antispam

        def _quiet_success():
            """Show the spammer the success page without saving anything.

            Silence is deliberate. An error tells a bot to adjust and retry,
            a success tells it the address is done and it moves on.
            """
            return render(request, 'public/contact.html', {
                'site': site,
                'recaptcha_site_key': _rc_site_key(),
                'form_ts': antispam.form_stamp(),
                'category_choices': ContactEnquiry.CATEGORY_CHOICES,
                'form_submitted': True,
            })

        automated, why = antispam.looks_automated(request.POST)
        if automated:
            log.info('Contact form rejected, %s, ip %s', why, antispam.client_ip(request))
            return _quiet_success()

        if antispam.rate_limited(request, 'contact', limit=5, window=3600):
            log.warning('Contact form rate limited for ip %s', antispam.client_ip(request))
            return _quiet_success()

        passed, score = antispam.verify_recaptcha(
            request.POST.get('g-recaptcha-response', ''), action='contact'
        )

        name = request.POST.get('name', '').strip()
        email = request.POST.get('email', '').strip()
        phone_code   = request.POST.get('phone_code', '').strip()
        phone_number = request.POST.get('phone_number', request.POST.get('phone', '')).strip()
        phone = f"{phone_code} {phone_number}".strip() if phone_number else ''
        company = request.POST.get('company', '').strip()
        category = request.POST.get('category', 'general')
        subject = request.POST.get('subject', '').strip()
        message = request.POST.get('message', '').strip()

        from apps.tickets.models import BlockedEmail
        if BlockedEmail.is_blocked(email):
            return _quiet_success()

        if not all([name, email, message]):
            return render(request, 'public/contact.html', {
                'site': site,
                'recaptcha_site_key': _rc_site_key(),
                'form_ts': antispam.form_stamp(),
                'category_choices': ContactEnquiry.CATEGORY_CHOICES,
                'error_message': 'Please fill in all required fields.',
                'form_data': request.POST,
            })

        # A low score can happen to a real person on a shared network, so this
        # one is visible and retryable rather than a silent success.
        if not passed:
            log.warning('Contact form failed reCAPTCHA, score %s, ip %s',
                        score, antispam.client_ip(request))
            return render(request, 'public/contact.html', {
                'site': site,
                'recaptcha_site_key': _rc_site_key(),
                'form_ts': antispam.form_stamp(),
                'category_choices': ContactEnquiry.CATEGORY_CHOICES,
                'error_message': 'We could not verify that you are human. '
                                 'Please try sending it again.',
                'form_data': request.POST,
            })

        if not subject:
            subject = 'Website Enquiry'

        try:
            # Create ticket
            ticket = Ticket.objects.create(
                source=Ticket.SOURCE_CONTACT,
                sender_name=name,
                sender_email=email,
                sender_phone=phone,
                sender_company=company,
                subject=subject,
                message=message,
                category=category,
            )
            # Store enquiry
            ContactEnquiry.objects.create(
                name=name, email=email, phone=phone, company=company,
                category=category, subject=subject, message=message,
                recaptcha_score=score,
                ip_address=antispam.client_ip(request),
                ticket=ticket,
            )
            return redirect(f"/contact/?sent=1&ref={ticket.ticket_number}")

        except Exception as exc:
            log.exception('Contact form save failed')
            return render(request, 'public/contact.html', {
                'site': site,
                'recaptcha_site_key': _rc_site_key(),
                'form_ts': antispam.form_stamp(),
                'category_choices': ContactEnquiry.CATEGORY_CHOICES,
                'error_message': f'Something went wrong: {exc}',
                'form_data': request.POST,
            })

    from apps.contact import antispam as _antispam
    sent = request.GET.get('sent') == '1'
    ref  = request.GET.get('ref', '')
    return render(request, 'public/contact.html', {
        'site': site,
        'recaptcha_site_key': _rc_site_key(),
        'form_ts': _antispam.form_stamp(),
        'category_choices': ContactEnquiry.CATEGORY_CHOICES,
        'success_message': ref if sent else '',
    })


@csrf_exempt
def assessment_submit(request):
    """Receive project assessment form submission from assessment.html."""
    if request.method != 'POST':
        return JsonResponse({'error': 'Method not allowed'}, status=405)

    try:
        body = json.loads(request.body)
    except (json.JSONDecodeError, ValueError):
        body = request.POST.dict()

    # This endpoint is csrf_exempt because the brief is posted as JSON, which
    # means the only thing standing between a script and the assessments table
    # is what follows. It answers 200 to a rejected brief on purpose, so a bot
    # cannot tell a saved one from a dropped one.
    from apps.contact import antispam

    _accepted = JsonResponse({'success': True})

    automated, why = antispam.looks_automated(body)
    if automated:
        log.info('Assessment rejected, %s, ip %s', why, antispam.client_ip(request))
        return _accepted

    if antispam.rate_limited(request, 'assessment', limit=3, window=3600):
        log.warning('Assessment rate limited for ip %s', antispam.client_ip(request))
        return _accepted

    _passed, _score = antispam.verify_recaptcha(
        str(body.get('g-recaptcha-response', '') or body.get('recaptcha_token', '')),
        action='assessment',
    )
    if not _passed:
        log.warning('Assessment failed reCAPTCHA, score %s, ip %s',
                    _score, antispam.client_ip(request))
        return JsonResponse(
            {'error': 'We could not verify that you are human. Please try again.'},
            status=400,
        )

    title      = str(body.get('title', '')).strip()
    first_name = str(body.get('first_name', '')).strip()
    last_name  = str(body.get('last_name', '')).strip()
    name       = f'{first_name} {last_name}'.strip() or str(body.get('name', '')).strip()
    email      = str(body.get('email', '')).strip()
    phone      = str(body.get('phone', '')).strip()
    company    = str(body.get('company', '')).strip()
    position   = str(body.get('position', '')).strip()
    heard_from = str(body.get('heard_from', '')).strip()

    if not name or not email or '@' not in email:
        return JsonResponse({'error': 'Name and a valid email are required.'}, status=400)

    tenant = getattr(request, 'tenant', None)
    if tenant and getattr(tenant, 'pk', 0) == 0:
        tenant = None

    # Support multi-select service types (new) or single string (legacy)
    service_types = body.get('service_types', [])
    if isinstance(service_types, list) and service_types:
        service_type = ','.join(service_types)
    else:
        service_type = str(body.get('service_type', 'web')).strip() or 'web'

    features = body.get('features', [])
    if isinstance(features, list):
        features_json = json.dumps(features)
    else:
        features_json = str(features)

    assessment = ProjectAssessment.objects.create(
        tenant=tenant,
        title=title,
        first_name=first_name,
        last_name=last_name,
        name=name,
        email=email,
        phone=phone,
        company=company,
        position=position,
        heard_from=heard_from,
        service_type=service_type,
        project_description=str(body.get('project_description', '')).strip(),
        features_requested=features_json,
        budget=body.get('budget', 'discuss'),
        timeline=body.get('timeline', 'flexible'),
        reference_sites=str(body.get('reference_sites', '')).strip(),
        brand_name=str(body.get('brand_name','') or '').strip()[:150],
        country=str(body.get('country','') or '').strip()[:80],
        existing_site=str(body.get('existing_site','') or '').strip()[:200],
        sector=str(body.get('sector','') or '').strip()[:100],
        project_type=str(body.get('project_type','') or '').strip()[:30],
        page_count=str(body.get('page_count','') or '').strip()[:20],
        design_level=str(body.get('design_level','') or '').strip()[:30],
        has_brand_assets=str(body.get('has_brand_assets','') or '').strip()[:10],
        integrations=str(body.get('integrations','') or '').strip()[:2000],
        product_count=str(body.get('product_count','') or '').strip()[:20],
        currency=str(body.get('currency','') or '').strip()[:20],
        payment_gateway=str(body.get('payment_gateway','') or '').strip()[:60],
        content_author=str(body.get('content_author','') or '').strip()[:30],
        seo_wanted=str(body.get('seo_wanted','') or '').strip()[:10],
        payment_model=str(body.get('payment_model','') or '').strip()[:30],
        is_urgent=bool(body.get('is_urgent')),
        nda_required=bool(body.get('nda_required')),
        ip_address=request.META.get('REMOTE_ADDR'),
    )

    # Send confirmation email to client + notification to support
    _send_assessment_emails(assessment, None)

    # Run AI analysis (non-blocking — failure is silent)
    _ai_analyse_assessment(assessment)

    return JsonResponse({
        'status': 'ok',
        'message': "Thank you! We'll be in touch within 5 business days.",
    })


def _outgoing():
    """The sending address, from Settings. Never .env."""
    from apps.pages.email_backend import outgoing_address
    return outgoing_address()
