import datetime

from django.contrib.auth.models import Group, User
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext as _
from django.utils.html import format_html


class Vendor(models.Model):
    nomerazaosocial_text = models.CharField(max_length=255, blank=True, null=True)
    nomefantasia_text = models.CharField(max_length=255, blank=True, null=True)
    cpfcnpj_text = models.CharField(max_length=18, unique=True)
    endereco_text = models.CharField(max_length=255, blank=True, null=True)
    bairro_text = models.CharField(max_length=100, blank=True, null=True)
    cep_text = models.CharField(max_length=10, blank=True, null=True)
    municipio_text = models.CharField(max_length=255, blank=True, null=True)
    uf_text = models.CharField(max_length=100, blank=True, null=True)
    telefone_text = models.CharField(max_length=20, blank=True, null=True)
    inscricaoestadual_text = models.CharField(max_length=20, blank=True, null=True)
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)
    
    class Meta:
        verbose_name = _('Loja')
    
    def __str__(self):
        return self.cpfcnpj_text + ' - ' + self.nomefantasia_text



class Product(models.Model):
    description_text = models.CharField(max_length=255, help_text=_('A Brief Description'))
    ncm = models.IntegerField(default=0)
    ean = models.CharField(max_length=13, blank=True, null=True)
    cfop = models.IntegerField(default=0)
    unidademedida = models.CharField(max_length=10, blank=True, null=True)
    
    class Meta:
        verbose_name = _('Produto')
    
    def __str__(self):
        return self.description_text



class Order(models.Model):
    key_sefaz = models.CharField(max_length=44, unique=True, verbose_name="Chave de acesso")
    
    #def btn_start_camera(self): 
    #    return format_html(u'<a href="#" class="button" ' u'id="btn_start_camera">Start Camera</a>')
    
    #btn_start_camera.allow_tags = True
    #btn_start_camera.short_description = 'Camera'
    
    #def btn_send_key(self): 
    #    return format_html(u'<a href="#" class="button" ' u'id="btn_send_key">Importar</a>')
    
    #btn_send_key.allow_tags = True
    #btn_start_camera.short_description = 'Importar'
    
    products = models.ManyToManyField(Product, through="OrderProduct")
    vendor = models.ForeignKey(Vendor, on_delete=models.DO_NOTHING, verbose_name="Estabelecimento", related_name='lojas')
    sale_date = models.DateTimeField("Data da Compra")
    total_discount = models.FloatField(default=0, verbose_name="Desconto (R$)")
    total_price = models.FloatField(default=0, verbose_name="Valor Total (R$)")
    total_paid = models.FloatField(default=0, verbose_name="Total Pago (R$)")
    total_taxes = models.FloatField(default=0, verbose_name="Total Impostos (R$)")
    
    PAYMENT_FORM = [
        ("MN", "1 - Dinheiro"),
        ("CC", "3 - Cartão de Crédito"),
        ("DC", "4 - Cartão de Débito"),
        ("PX", "17 - PIX"),
        ("OT", "99 - Outros"),
        ("ET", "Ethereum"),
        ("BC", "Bitcoin"),
    ]
    
    payment_form = models.CharField(max_length=255, verbose_name="Forma(s) Pagamento(s)")
    contem_parcelamento = models.BooleanField(default=False)
    numero_parcelas = models.IntegerField(default=1)
    total_quantity = models.IntegerField(default=1, verbose_name="Qtde. Itens")
    
    def __str__(self):
        #return self.key_sefaz
        return str(self.id) + ' - ' + str(self.vendor.nomefantasia_text) + ' - (R$ ' + str(self.total_paid) + ')'
    
    def was_sold_recently(self):
        return self.sale_date >= timezone.now() - datetime.timedelta(days=1)
    
    class Meta:
        verbose_name = "Compra"
        verbose_name_plural = "Compras"
        ordering = ["-sale_date"]


class OrderProduct(models.Model):
    order = models.ForeignKey(Order, on_delete=models.DO_NOTHING)
    product = models.ForeignKey(Product, on_delete=models.DO_NOTHING, verbose_name="Produto")
    product_un_price = models.FloatField(default=0.00, verbose_name="Valor Unitário")
    product_quantity = models.FloatField(default=0.00, verbose_name="Qtde.")
    product_total_price = models.FloatField(default=0.00, verbose_name="Preço")
    product_total_taxes = models.FloatField(default=0.00, verbose_name="Imposto")
    
    def __str__(self):
        return ''
    
    class Meta:
        verbose_name = "Item da Compra"
        verbose_name_plural = "Itens da Compra"
        db_table = 'notas_orderproduct'


class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)
    radius_km = models.IntegerField(default=10)
    notifications_enabled = models.BooleanField(default=True)
    expo_push_token = models.CharField(max_length=255, blank=True, default='')
    monthly_income = models.FloatField('Receita Mensal (R$)', null=True, blank=True)
    monthly_goal = models.FloatField('Meta de Gastos (R$)', null=True, blank=True)
    vendors_goal = models.TextField(default='[]', blank=True)
    products_goal = models.TextField(default='[]', blank=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Perfil do Usuário"
        verbose_name_plural = "Perfis dos Usuários"

    def __str__(self):
        return f"Perfil de {self.user.get_full_name() or self.user.username}"


class Notification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='notifications')
    title = models.CharField(max_length=255)
    body = models.TextField()
    product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True, blank=True)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, null=True, blank=True)
    price = models.FloatField(default=0)
    is_read = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = "Notificação"
        verbose_name_plural = "Notificações"
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.title} — {self.user.username}"


class ContaBasica(models.Model):
    TIPO_CHOICES = [
        ('agua', 'Água'),
        ('luz', 'Luz'),
        ('iptu', 'IPTU'),
        ('claro', 'Claro'),
        ('gas', 'Gás'),
    ]
    tipo = models.CharField(max_length=10, choices=TIPO_CHOICES)
    codigo_barras = models.CharField('Código de Barras', max_length=60, blank=True, default='')
    data_vencimento = models.DateField('Data de Vencimento', null=True, blank=True)
    valor_devido = models.FloatField('Valor Devido (R$)', null=True, blank=True)
    valor_pago = models.FloatField('Valor Pago (R$)', null=True, blank=True)
    data_pagamento = models.DateField('Data de Pagamento', null=True, blank=True)

    class Meta:
        verbose_name = 'Conta Básica'
        verbose_name_plural = 'Contas Básicas'
        ordering = ['-data_vencimento']

    def __str__(self):
        return f"{self.get_tipo_display()} — R$ {self.valor_devido:.2f}"


class ImportJob(models.Model):
    STATUS_CHOICES = [
        ('pending', 'Pendente'),
        ('processing', 'Processando'),
        ('completed', 'Concluída'),
        ('failed', 'Falhou'),
    ]
    key_sefaz = models.CharField(max_length=44)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='import_jobs')
    status = models.CharField(max_length=12, default='pending', choices=STATUS_CHOICES, db_index=True)
    result = models.JSONField(null=True, blank=True)
    error_message = models.TextField(blank=True, default='')
    retry_count = models.IntegerField(default=0)
    max_retries = models.IntegerField(default=3)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = 'Importação'
        verbose_name_plural = 'Importações'
        ordering = ['created_at']

    def __str__(self):
        return f"{self.key_sefaz} — {self.get_status_display()}"


class SefazCaptchaSample(models.Model):
    """Captcha SEFIN-RO que abriu a nota — só sucessos, para o OCR aprender."""

    texto = models.CharField(max_length=8)
    tamanho = models.PositiveSmallIntegerField()
    tentativa = models.PositiveSmallIntegerField(default=1)
    png = models.BinaryField(null=True, blank=True)
    chave_sefaz = models.CharField(max_length=44, blank=True, default='')
    import_job = models.ForeignKey(
        ImportJob,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='captcha_samples',
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = 'Amostra de captcha SEFAZ'
        verbose_name_plural = 'Amostras de captcha SEFAZ'
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.texto} ({self.tamanho} chars, try {self.tentativa})"


class FamilyGroup(models.Model):
    group = models.OneToOneField(
        Group, on_delete=models.CASCADE, related_name='family',
    )
    created_by = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='created_family',
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = 'Grupo Familiar'
        verbose_name_plural = 'Grupos Familiares'

    def __str__(self):
        return f"Família de {self.created_by.get_full_name() or self.created_by.username}"


class FamilyInvite(models.Model):
    STATUS_CHOICES = [
        ('pending', 'Pendente'),
        ('accepted', 'Aceito'),
        ('rejected', 'Rejeitado'),
    ]
    family = models.ForeignKey(
        FamilyGroup, on_delete=models.CASCADE, related_name='invites',
    )
    invited_email = models.EmailField()
    invited_by = models.ForeignKey(User, on_delete=models.CASCADE)
    status = models.CharField(max_length=10, default='pending', choices=STATUS_CHOICES)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = 'Convite Familiar'
        verbose_name_plural = 'Convites Familiares'

    def __str__(self):
        return f"Convite para {self.invited_email} ({self.get_status_display()})"


class MegaSenaJob(models.Model):
    """
    Scrape queue for Mega-Sena. The HTTP endpoint at
    /api/internal/loterias/megasena/ creates a `pending` row and
    long-polls until the systemd worker (the same one that powers
    SEFAZ) consumes it on its next tick (≤ 60 s).

    There is no user FK: Mega-Sena is a global resource.

    The canonical result store lives on the Drupal side
    (mega_sena_draw table); this model only carries the in-flight
    state plus the latest scraped payload in `result` as a transient
    cache used by the API to respond synchronously.
    """
    STATUS_CHOICES = [
        ('pending', 'Pendente'),
        ('processing', 'Processando'),
        ('completed', 'Concluído'),
        ('failed', 'Falhou'),
    ]
    status = models.CharField(
        max_length=12, default='pending', choices=STATUS_CHOICES, db_index=True,
    )
    result = models.JSONField(null=True, blank=True)
    error_message = models.TextField(blank=True, default='')
    retry_count = models.IntegerField(default=0)
    max_retries = models.IntegerField(default=3)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = 'Job Mega-Sena'
        verbose_name_plural = 'Jobs Mega-Sena'
        ordering = ['created_at']

    def __str__(self):
        return f"MegaSenaJob #{self.pk} — {self.get_status_display()}"


class MegaSenaBetJob(models.Model):
    """
    Bet queue for Mega-Sena: the Drupal-cron scheduler POSTs a row,
    the systemd worker consumes it and drives the Caixa Internet
    Banking automation in `notas.caixa_banking`.

    The canonical record of the bet placement (with receipt) lives
    in Drupal's `mega_sena_bet` table; this model is the transient
    queue + cache for the synchronous HTTP endpoint, identical in
    shape to `MegaSenaJob`.

    `dry_run=True` instructs the worker to walk the full UI flow up
    to (but not including) the irreversible signature submit. Used
    for selector-verification before a real bet is placed.
    """
    STATUS_CHOICES = [
        ('pending', 'Pendente'),
        ('processing', 'Processando'),
        ('completed', 'Concluído'),
        ('failed', 'Falhou'),
    ]
    dezenas = models.JSONField(
        help_text='Lista de 6 dezenas que serão apostadas (int 1..60).',
    )
    dry_run = models.BooleanField(
        default=False,
        help_text='Se TRUE, percorre o flow mas não submete a assinatura.',
    )
    status = models.CharField(
        max_length=12, default='pending', choices=STATUS_CHOICES, db_index=True,
    )
    result = models.JSONField(null=True, blank=True)
    error_message = models.TextField(blank=True, default='')
    retry_count = models.IntegerField(default=0)
    max_retries = models.IntegerField(default=2)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = 'Aposta Mega-Sena (job)'
        verbose_name_plural = 'Apostas Mega-Sena (jobs)'
        ordering = ['created_at']

    def __str__(self):
        flag = ' [DRY-RUN]' if self.dry_run else ''
        return (
            f"MegaSenaBetJob #{self.pk} — {self.get_status_display()}{flag}"
        )
