import uuid

from django.db import models
from django.utils import timezone
import json


class ProjectAssessment(models.Model):
    """Submitted via the public assessment wizard on the website."""

    SERVICE_WEB         = 'web'
    SERVICE_ECOMMERCE   = 'ecommerce'
    SERVICE_APP         = 'app'
    SERVICE_MARKETING   = 'marketing'
    SERVICE_PORTAL      = 'portal'
    SERVICE_SAAS        = 'saas'
    SERVICE_OTHER       = 'other'

    SERVICE_CHOICES = [
        (SERVICE_WEB,       'Website / Web Portal'),
        (SERVICE_ECOMMERCE, 'E-commerce Store'),
        (SERVICE_APP,       'Mobile App (iOS / Android)'),
        (SERVICE_MARKETING, 'Digital Marketing (SEO / SEM)'),
        (SERVICE_PORTAL,    'Client Portal / Dashboard'),
        (SERVICE_SAAS,      'SaaS Platform'),
        (SERVICE_OTHER,     'Other / Not Sure'),
    ]

    BUDGET_UNDER_2K   = 'under_2k'
    BUDGET_2K_5K      = '2k_5k'
    BUDGET_5K_15K     = '5k_15k'
    BUDGET_15K_50K    = '15k_50k'
    BUDGET_OVER_50K   = 'over_50k'
    BUDGET_DISCUSS    = 'discuss'

    BUDGET_CHOICES = [
        # Values sent by the assessment form
        ('under5k',    'Under £5k'),
        ('5k-15k',     '£5-15k'),
        ('15k-40k',    '£15-40k'),
        ('40k-100k',   '£40-100k'),
        ('100k+',      '£100k+'),
        (BUDGET_DISCUSS,   "Let's discuss"),
        # Legacy values (backwards-compatibility)
        (BUDGET_UNDER_2K,  'Under £2k'),
        (BUDGET_2K_5K,     '£2-5k'),
        (BUDGET_5K_15K,    '£5-15k'),
        (BUDGET_15K_50K,   '£15-50k'),
        (BUDGET_OVER_50K,  'Over £50k'),
    ]

    TIMELINE_ASAP     = 'asap'
    TIMELINE_1M       = '1_month'
    TIMELINE_3M       = '3_months'
    TIMELINE_6M       = '6_months'
    TIMELINE_FLEXIBLE = 'flexible'

    TIMELINE_CHOICES = [
        (TIMELINE_ASAP,     'As soon as possible'),
        (TIMELINE_1M,       'Within 1 month'),
        (TIMELINE_3M,       '1-3 months'),
        (TIMELINE_6M,       '3-6 months'),
        (TIMELINE_FLEXIBLE, 'Flexible / Not urgent'),
    ]

    STATUS_NEW      = 'new'
    STATUS_REVIEWED = 'reviewed'
    STATUS_QUOTED   = 'quoted'
    STATUS_WON      = 'won'
    STATUS_LOST     = 'lost'

    STATUS_CHOICES = [
        (STATUS_NEW,      'New'),
        (STATUS_REVIEWED, 'Reviewed'),
        (STATUS_QUOTED,   'Quoted'),
        (STATUS_WON,      'Won'),
        (STATUS_LOST,     'Lost'),
    ]

    tenant       = models.ForeignKey(
        'tenants.Tenant', on_delete=models.CASCADE,
        null=True, blank=True, related_name='project_assessments'
    )

    TITLE_CHOICES = [('mr','Mr'), ('mrs','Mrs'), ('ms','Ms'), ('miss','Miss'), ('dr','Dr'), ('prof','Prof')]

    HEARD_FROM_CHOICES = [
        ('google',      'Google Search'),
        ('social',      'Social Media'),
        ('referral',    'Referral / Word of Mouth'),
        ('linkedin',    'LinkedIn'),
        ('instagram',   'Instagram'),
        ('facebook',    'Facebook'),
        ('youtube',     'YouTube'),
        ('event',       'Event / Conference'),
        ('press',       'Press / Article'),
        ('returning',   'Returning Client'),
        ('other',       'Other'),
    ]

    # Client info
    title        = models.CharField(max_length=10, blank=True, choices=[('mr','Mr'), ('mrs','Mrs'), ('ms','Ms'), ('miss','Miss'), ('dr','Dr'), ('prof','Prof')])
    first_name   = models.CharField(max_length=75, blank=True)
    last_name    = models.CharField(max_length=75, blank=True)
    name         = models.CharField(max_length=150)  # kept for display / legacy
    email        = models.EmailField()
    phone        = models.CharField(max_length=30, blank=True)
    company      = models.CharField(max_length=150, blank=True)
    position     = models.CharField(max_length=100, blank=True, help_text='Job title / position')
    heard_from   = models.CharField(max_length=20, blank=True, choices=[
        ('google','Google Search'), ('social','Social Media'),
        ('referral','Referral / Word of Mouth'), ('linkedin','LinkedIn'),
        ('instagram','Instagram'), ('facebook','Facebook'),
        ('youtube','YouTube'), ('event','Event / Conference'),
        ('press','Press / Article'), ('returning','Returning Client'), ('other','Other'),
    ])

    # Project details
    service_type = models.CharField(max_length=100, default=SERVICE_WEB)  # comma-joined for multi-select
    project_description = models.TextField(blank=True, help_text='What the client described')
    features_requested  = models.TextField(blank=True, help_text='JSON list of selected features')
    budget       = models.CharField(max_length=20, choices=BUDGET_CHOICES, default=BUDGET_DISCUSS)
    timeline     = models.CharField(max_length=20, choices=TIMELINE_CHOICES, default=TIMELINE_FLEXIBLE)
    reference_sites = models.TextField(blank=True, help_text='Websites the client likes / wants as reference')

    brand_name        = models.CharField(max_length=150, blank=True)
    country           = models.CharField(max_length=80,  blank=True)
    existing_site     = models.CharField(max_length=200, blank=True)
    sector            = models.CharField(max_length=100, blank=True)
    project_type      = models.CharField(max_length=30,  blank=True)
    page_count        = models.CharField(max_length=20,  blank=True)
    languages         = models.CharField(max_length=100, blank=True)
    design_level      = models.CharField(max_length=30,  blank=True)
    has_brand_assets  = models.CharField(max_length=10,  blank=True)
    modules           = models.TextField(blank=True)
    integrations      = models.TextField(blank=True)
    product_count     = models.CharField(max_length=20,  blank=True)
    currency          = models.CharField(max_length=20,  blank=True)
    payment_gateway   = models.CharField(max_length=60,  blank=True)
    content_author    = models.CharField(max_length=30,  blank=True)
    seo_wanted        = models.CharField(max_length=10,  blank=True)
    launch_date       = models.DateField(null=True, blank=True)
    is_urgent         = models.BooleanField(default=False)
    payment_model     = models.CharField(max_length=30,  blank=True)
    nda_required      = models.BooleanField(default=False)
    brief_score       = models.PositiveSmallIntegerField(default=0)

    # Admin-only estimate fields (never sent to client)
    est_weeks_min = models.PositiveSmallIntegerField(null=True, blank=True, help_text='Estimated delivery min weeks')
    est_weeks_max = models.PositiveSmallIntegerField(null=True, blank=True, help_text='Estimated delivery max weeks')
    est_cost_min  = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, help_text='Estimated cost min (GBP)')
    est_cost_max  = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, help_text='Estimated cost max (GBP)')
    internal_notes = models.TextField(blank=True, help_text='Internal notes — not visible to client')

    # Pipeline
    status       = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_NEW)
    ip_address   = models.GenericIPAddressField(null=True, blank=True)
    is_archived  = models.BooleanField(
        default=False,
        help_text='Client went quiet or cancelled. Hidden from the main list, nothing deleted.'
    )
    archived_at  = models.DateTimeField(null=True, blank=True)

    created_at   = models.DateTimeField(auto_now_add=True)
    updated_at   = models.DateTimeField(auto_now=True)

    # Quotation
    quote_weeks   = models.PositiveSmallIntegerField(null=True, blank=True, help_text='Quoted delivery period in weeks')
    quote_amount  = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, help_text='Quoted price (GBP)')
    quote_notes   = models.TextField(blank=True, help_text='Message to client included in the quote email')
    quote_sent_at = models.DateTimeField(null=True, blank=True, help_text='When the quote was emailed to the client')
    quote_sent_by = models.ForeignKey(
        'accounts.User', on_delete=models.SET_NULL,
        null=True, blank=True, related_name='sent_quotes',
        help_text='CMS user who sent the quote'
    )

    # AI analysis (generated automatically on submission)
    ai_label            = models.CharField(max_length=200, blank=True, help_text='AI-generated short project label')
    ai_feasibility_score = models.SmallIntegerField(null=True, blank=True, help_text='0–100 feasibility % vs market')
    ai_market_note      = models.TextField(blank=True, help_text='AI market comparison note')
    ai_verdict          = models.CharField(max_length=30, blank=True, help_text='feasible / possible_reduced_scope / challenging / unrealistic')
    ai_analysed_at      = models.DateTimeField(null=True, blank=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Project Assessment'
        verbose_name_plural = 'Project Assessments'

    def __str__(self):
        return f'{self.name} — {self.get_service_type_display()} ({self.created_at.strftime("%d %b %Y")})'

    @property
    def service_types_list(self):
        """Return list of service type values (handles both single and comma-joined)."""
        return [s.strip() for s in self.service_type.split(',') if s.strip()]

    @property
    def service_types_display(self):
        """Human-readable comma-joined service types."""
        labels = dict(self.SERVICE_CHOICES)
        return ', '.join(labels.get(s, s) for s in self.service_types_list)

    @property
    def features_list(self):
        try:
            return json.loads(self.features_requested)
        except Exception:
            return []

    @property
    def estimate_display(self):
        parts = []
        if self.est_weeks_min and self.est_weeks_max:
            parts.append(f'{self.est_weeks_min}–{self.est_weeks_max} weeks')
        if self.est_cost_min and self.est_cost_max:
            parts.append(f'£{self.est_cost_min:,.0f} – £{self.est_cost_max:,.0f}')
        return ' / '.join(parts) if parts else 'Not estimated yet'


class AssessmentExpenseItem(models.Model):
    """
    A catalog item (Product / Service / Subscription) linked to a project assessment
    as a cost estimate line. Admin-only — never shown to the client.
    Can be pushed to the Expenses ledger once the project is approved.
    """
    TYPE_PRODUCT      = 'product'
    TYPE_SERVICE      = 'service'
    TYPE_SUBSCRIPTION = 'subscription'
    TYPE_CUSTOM       = 'custom'

    TYPE_CHOICES = [
        (TYPE_PRODUCT,      'Product'),
        (TYPE_SERVICE,      'Service'),
        (TYPE_SUBSCRIPTION, 'Subscription'),
        (TYPE_CUSTOM,       'Custom'),
    ]

    BILLING_ONCE    = 'once'
    BILLING_HOURLY  = 'hourly'
    BILLING_MONTHLY = 'monthly'
    BILLING_ANNUAL  = 'annual'

    BILLING_CHOICES = [
        (BILLING_ONCE,    'One-off'),
        (BILLING_HOURLY,  'Hourly'),
        (BILLING_MONTHLY, 'Monthly'),
        (BILLING_ANNUAL,  'Annual'),
    ]

    assessment     = models.ForeignKey(
        ProjectAssessment, on_delete=models.CASCADE, related_name='expense_items'
    )
    item_type      = models.CharField(max_length=15, choices=TYPE_CHOICES, default=TYPE_PRODUCT)
    product        = models.ForeignKey(
        'ecommerce.Product', on_delete=models.SET_NULL,
        null=True, blank=True, related_name='assessment_items'
    )
    service        = models.ForeignKey(
        'pages.Service', on_delete=models.SET_NULL,
        null=True, blank=True, related_name='assessment_items'
    )
    label          = models.CharField(max_length=200, help_text='Item name (auto-filled, editable)')
    billing_period = models.CharField(max_length=10, choices=BILLING_CHOICES, default=BILLING_ONCE)
    amount         = models.DecimalField(max_digits=10, decimal_places=2)
    quantity       = models.PositiveSmallIntegerField(default=1)
    notes          = models.CharField(max_length=300, blank=True)
    pushed_to_expenses = models.BooleanField(default=False, help_text='Has this item been pushed to the Expenses ledger?')
    created_at     = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['created_at']
        verbose_name = 'Assessment Expense Item'
        verbose_name_plural = 'Assessment Expense Items'

    def __str__(self):
        return f'{self.label} — £{self.amount} ({self.assessment})'

    @property
    def line_total(self):
        return self.amount * self.quantity


class AssessmentQuote(models.Model):
    """Immutable record of each quote version sent to a client."""

    assessment  = models.ForeignKey(
        ProjectAssessment, on_delete=models.CASCADE, related_name='quote_versions'
    )
    version     = models.PositiveSmallIntegerField(help_text='Quote number within this assessment (1, 2, 3…)')
    quote_weeks = models.PositiveSmallIntegerField(null=True, blank=True)
    quote_amount = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    quote_notes  = models.TextField(blank=True)
    sent_at     = models.DateTimeField(auto_now_add=True)
    sent_by     = models.ForeignKey(
        'accounts.User', on_delete=models.SET_NULL,
        null=True, blank=True, related_name='sent_assessment_quotes'
    )

    # ── Client response ──────────────────────────────────────────────────
    OUTCOME_PENDING  = 'pending'
    OUTCOME_ADVISOR  = 'advisor'
    OUTCOME_ACCEPTED = 'accepted'

    OUTCOME_CHOICES = [
        (OUTCOME_PENDING,  'Awaiting response'),
        (OUTCOME_ADVISOR,  'Advisor requested'),
        (OUTCOME_ACCEPTED, 'Accepted'),
    ]

    accept_token = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
    expires_at   = models.DateTimeField(null=True, blank=True, help_text='Ten working days from sending')
    outcome      = models.CharField(max_length=20, choices=OUTCOME_CHOICES, default=OUTCOME_PENDING)
    responded_at = models.DateTimeField(null=True, blank=True)
    responded_ip = models.GenericIPAddressField(null=True, blank=True)
    agreement    = models.ForeignKey(
        'ecommerce.DealAgreement', on_delete=models.SET_NULL,
        null=True, blank=True, related_name='assessment_quotes',
        help_text='Created when the client accepts',
    )

    @staticmethod
    def working_days_from(start, days=10):
        """Add working days, skipping weekends. Bank holidays are not excluded."""
        from datetime import timedelta
        d = start
        added = 0
        while added < days:
            d += timedelta(days=1)
            if d.weekday() < 5:
                added += 1
        return d

    @property
    def is_expired(self):
        from django.utils import timezone as _tz
        return bool(self.expires_at and _tz.now() > self.expires_at)

    class Meta:
        ordering = ['-version']
        verbose_name = 'Assessment Quote'
        verbose_name_plural = 'Assessment Quotes'

    def __str__(self):
        return f'Quote #{self.version} for {self.assessment}'


class SalesLead(models.Model):
    # Service types
    SERVICE_DOMAIN       = 'domain'
    SERVICE_WEB          = 'web'
    SERVICE_APP          = 'app'
    SERVICE_MARKETING    = 'marketing'
    SERVICE_SERVER       = 'server'
    SERVICE_CONSULTATION = 'consultation'
    SERVICE_ECOMMERCE    = 'ecommerce'
    SERVICE_OTHER        = 'other'

    SERVICE_CHOICES = [
        (SERVICE_DOMAIN,       'Domain Registration / Premium Domain'),
        (SERVICE_WEB,          'Website / Web Portal'),
        (SERVICE_APP,          'iOS / Android App'),
        (SERVICE_MARKETING,    'Digital Marketing (SEO/SEM)'),
        (SERVICE_SERVER,       'Server / Hosting / Cloud'),
        (SERVICE_CONSULTATION, 'IT Consultation'),
        (SERVICE_ECOMMERCE,    'E-commerce'),
        (SERVICE_OTHER,        'Other'),
    ]

    # Status
    STATUS_NEW       = 'new'
    STATUS_CONTACTED = 'contacted'
    STATUS_QUOTED    = 'quoted'
    STATUS_WON       = 'won'
    STATUS_LOST      = 'lost'
    STATUS_ON_HOLD   = 'on_hold'

    STATUS_CHOICES = [
        (STATUS_NEW,       '🔵 New'),
        (STATUS_CONTACTED, '🟡 Contacted'),
        (STATUS_QUOTED,    '🟠 Quoted'),
        (STATUS_WON,       '🟢 Won'),
        (STATUS_LOST,      '🔴 Lost'),
        (STATUS_ON_HOLD,   '⚪ On Hold'),
    ]

    # Priority
    PRIORITY_LOW    = 'low'
    PRIORITY_MEDIUM = 'medium'
    PRIORITY_HIGH   = 'high'

    PRIORITY_CHOICES = [
        (PRIORITY_LOW,    'Low'),
        (PRIORITY_MEDIUM, 'Medium'),
        (PRIORITY_HIGH,   'High'),
    ]

    tenant       = models.ForeignKey(
        'tenants.Tenant', on_delete=models.CASCADE,
        null=True, blank=True, related_name='sales_leads'
    )

    # Contact info
    name         = models.CharField(max_length=150)
    email        = models.EmailField()
    phone        = models.CharField(max_length=30, blank=True)
    company      = models.CharField(max_length=150, blank=True)

    # Lead details
    service_type = models.CharField(max_length=30, choices=SERVICE_CHOICES, default=SERVICE_WEB)
    subject      = models.CharField(max_length=300)
    message      = models.TextField()
    budget       = models.CharField(max_length=100, blank=True, help_text='e.g. £500-£2000')

    # Domain specific
    domain_name  = models.CharField(max_length=255, blank=True, help_text='e.g. mybusiness.com')
    domain_tld   = models.CharField(max_length=20, blank=True, help_text='e.g. .com .co.uk .io')

    # Pipeline
    status       = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_NEW)
    priority     = models.CharField(max_length=10, choices=PRIORITY_CHOICES, default=PRIORITY_MEDIUM)
    assigned_to  = models.CharField(max_length=100, blank=True, help_text='Team member handling this lead')
    notes        = models.TextField(blank=True, help_text='Internal notes — not visible to client')
    quoted_value = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, help_text='Quote value in GBP')
    closed_at    = models.DateTimeField(null=True, blank=True)

    # Meta
    source       = models.CharField(max_length=50, default='website', help_text='website / email / referral / phone')
    ip_address   = models.GenericIPAddressField(null=True, blank=True)
    created_at   = models.DateTimeField(auto_now_add=True)
    updated_at   = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Sales Lead'
        verbose_name_plural = 'Sales Leads'

    def __str__(self):
        return f'{self.name} — {self.get_service_type_display()} ({self.get_status_display()})'

    def mark_won(self):
        self.status = self.STATUS_WON
        self.closed_at = timezone.now()
        self.save()

    def mark_lost(self):
        self.status = self.STATUS_LOST
        self.closed_at = timezone.now()
        self.save()


class DomainInquiry(models.Model):
    """Dedicated model for premium domain / domain handle inquiries."""

    TYPE_REGISTER  = 'register'
    TYPE_TRANSFER  = 'transfer'
    TYPE_PREMIUM   = 'premium'
    TYPE_HANDLE    = 'handle'

    TYPE_CHOICES = [
        (TYPE_REGISTER, 'Register New Domain'),
        (TYPE_TRANSFER, 'Transfer Existing Domain'),
        (TYPE_PREMIUM,  'Buy Premium Domain'),
        (TYPE_HANDLE,   'Domain Handle / Portfolio Management'),
    ]

    STATUS_NEW       = 'new'
    STATUS_CHECKING  = 'checking'
    STATUS_AVAILABLE = 'available'
    STATUS_TAKEN     = 'taken'
    STATUS_QUOTED    = 'quoted'
    STATUS_COMPLETE  = 'complete'

    STATUS_CHOICES = [
        (STATUS_NEW,       'New Request'),
        (STATUS_CHECKING,  'Checking Availability'),
        (STATUS_AVAILABLE, 'Available — Awaiting Order'),
        (STATUS_TAKEN,     'Taken — Alternatives Sent'),
        (STATUS_QUOTED,    'Quoted'),
        (STATUS_COMPLETE,  'Complete'),
    ]

    tenant       = models.ForeignKey(
        'tenants.Tenant', on_delete=models.CASCADE,
        null=True, blank=True, related_name='domain_inquiries'
    )
    name         = models.CharField(max_length=150)
    email        = models.EmailField()
    phone        = models.CharField(max_length=30, blank=True)
    company      = models.CharField(max_length=150, blank=True)

    inquiry_type = models.CharField(max_length=20, choices=TYPE_CHOICES, default=TYPE_REGISTER)
    domain_name  = models.CharField(max_length=255, help_text='Domain name requested e.g. mybusiness.com')
    alternatives = models.TextField(blank=True, help_text='Alternative domains the client would accept')
    message      = models.TextField(blank=True)
    budget       = models.CharField(max_length=100, blank=True)

    status       = models.CharField(max_length=20, choices=STATUS_CHOICES, default=STATUS_NEW)
    registrar    = models.CharField(max_length=100, blank=True, help_text='Registrar used e.g. OnlineNIC')
    reg_price    = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True, help_text='Registration price GBP')
    our_price    = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True, help_text='Price charged to client GBP')
    notes        = models.TextField(blank=True)

    created_at   = models.DateTimeField(auto_now_add=True)
    updated_at   = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Domain Inquiry'
        verbose_name_plural = 'Domain Inquiries'

    def __str__(self):
        return f'{self.domain_name} — {self.name} ({self.get_status_display()})'

    @property
    def margin(self):
        if self.reg_price and self.our_price:
            return self.our_price - self.reg_price
        return None
