#models.py
import os
import time
import stripe
import uuid
import shutil
from django.utils import timezone
from datetime import timedelta
from django.db import models, transaction
from django.utils.text import slugify
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django.contrib.auth.models import AbstractUser
from django.conf import settings
from PIL import Image
from decimal import Decimal
from django.template.loader import render_to_string
from django.core.files import File
from django.core.validators import MinValueValidator, MaxValueValidator
from django.urls import reverse
from weasyprint import HTML
import weasyprint

stripe.api_key = settings.STRIPE_SECRET_KEY

# model utilizator simplificat
class User(AbstractUser):
    ROLE_CHOICES = [
        ('organizator', 'Organizator'),
        ('participant', 'Participant'),
    ]
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='participant')
    stripe_account_id = models.CharField(max_length=255, blank=True, null=True)  # 🆕 ID-ul contului Stripe

    # Date facturare
    companie_nume = models.CharField(max_length=255, blank=True, null=True)
    companie_adresa = models.CharField(max_length=255, blank=True, null=True)
    companie_cod_fiscal = models.CharField(max_length=50, blank=True, null=True)
    companie_cont_bancar = models.CharField(max_length=50, blank=True, null=True)
    companie_email = models.EmailField(blank=True, null=True)
    companie_telefon = models.CharField(max_length=20, blank=True, null=True)
    
    serie_facturi = models.CharField(max_length=10, default='BIL')
    numar_curent_factura = models.BigIntegerField(default=1)  # pentru incrementare

    #taxa
    taxa_organizator = models.BooleanField(
        default=True,
        help_text="Dacă este activat, taxele sunt adăugate peste prețul biletelor."
    )

    procent_taxa = models.PositiveIntegerField(
        default=2,
        validators=[MinValueValidator(0), MaxValueValidator(50)],
        help_text="Procentul perceput de platformă din total."
    )
    
    platitor_tva = models.BooleanField(default=False)
    cota_tva = models.BigIntegerField(default=0)

    def __str__(self):
        return self.username


def path_imagine_event(instance, filename):
    ext = filename.split('.')[-1]
    filename = f"imagine_{int(time.time())}.{ext}"  # ex: imagine_1720000000.png
    return os.path.join(slugify(instance.slug or instance.nume), filename)


def generate_unique_slug(instance, field_value, slug_field_name='slug'):
    slug = slugify(field_value)
    ModelClass = instance.__class__
    unique_slug = slug
    num = 1
    while ModelClass.objects.filter(**{slug_field_name: unique_slug}).exists():
        unique_slug = f"{slug}-{num}"
        num += 1
    return unique_slug


class Event(models.Model):
    nume = models.CharField(max_length=255)
    descriere = models.TextField()
    locatie = models.CharField(max_length=255, default="")
    imagine = models.ImageField(upload_to=path_imagine_event)
    data = models.DateTimeField()
    public = models.BooleanField(default=True)
    finalizat = models.BooleanField(default=False)
    organizator = models.ForeignKey(User, on_delete=models.CASCADE, related_name='evenimente')
    slug = models.SlugField(unique=True, blank=True)

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = generate_unique_slug(self, self.nume)

        try:
            # Dacă eventul există deja în DB
            this = Event.objects.get(id=self.id)
            if this.imagine and this.imagine != self.imagine:
                # Șterge imaginea veche
                if this.imagine.storage.exists(this.imagine.name):
                    this.imagine.storage.delete(this.imagine.name)
        except Event.DoesNotExist:
            pass

        super().save(*args, **kwargs)

        if self.imagine:
            img = Image.open(self.imagine.path)

            # conversie în RGB (ca să eviți erori cu PNG/transparență)
            if img.mode in ("RGBA", "P"):
                img = img.convert("RGB")

            # dimensiune maximă (ex. 1280px lățime)
            MAX_WIDTH = 1080
            MAX_HEIGHT = 1080

            if img.width > MAX_WIDTH or img.height > MAX_HEIGHT:
                img.thumbnail((MAX_WIDTH, MAX_HEIGHT), Image.Resampling.LANCZOS)

            # rescrie fișierul cu compresie
            img.save(self.imagine.path, optimize=True, quality=70)



    def __str__(self):
        return self.nume


@receiver(post_delete, sender=Event)
def delete_event_folder(sender, instance, **kwargs):
    if instance.slug:
        folder_path = os.path.join(settings.MEDIA_ROOT, instance.slug)
        if os.path.exists(folder_path):
            shutil.rmtree(folder_path)

# model pentru tipurile de bilete din eveniment
class TipBilet(models.Model):
    event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='tipuri_bilete')
    nume = models.CharField(max_length=100)
    pret = models.DecimalField(max_digits=8, decimal_places=2)
    nr_maxim = models.PositiveIntegerField()
    nr_vandute = models.PositiveIntegerField(default=0)
    de_vanzare = models.BooleanField(default=True)
    serie = models.CharField(max_length=20, default="BLT")

    # 🆕 intervale pentru numerotare
    interval_start = models.PositiveIntegerField(null=True, blank=True)
    interval_end = models.PositiveIntegerField(null=True, blank=True)
    ultimul_nr_alocat = models.PositiveIntegerField(default=0)

    def __str__(self):
        return f"{self.nume}"

def upload_bilet_pdf(instance, filename):
    return f"bilete/{instance.tip_bilet.event.id}/bilet_{instance.nr_serie}.pdf"

# model pentru biletele efective
class Bilet(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    tip_bilet = models.ForeignKey(TipBilet, on_delete=models.CASCADE, related_name='bilete')
    nume_participant = models.CharField(max_length=150)
    email_participant = models.EmailField()
    folosit = models.BooleanField(default=False)
    nr_serie = models.PositiveIntegerField(null=True, blank=True)

    # PDF field pentru bilet
    pdf = models.FileField(upload_to=upload_bilet_pdf, null=True, blank=True)

    def __str__(self):
        return f"{self.id} - {self.nume_participant}"

    def get_qr_data(self):
        return f"TICKNEX-BILET-{self.id}"

        


#comanda
class ContorComenzi(models.Model):
    ultimul_nr = models.PositiveIntegerField(default=0)

    @classmethod
    def get_next_nr(cls):
        with transaction.atomic():
            contor, created = cls.objects.select_for_update().get_or_create(pk=1)
            contor.ultimul_nr += 1
            contor.save()
            return contor.ultimul_nr
        
class Comanda(models.Model):
    # ForeignKey spre Eveniment
    eveniment = models.ForeignKey('Event', default="", on_delete=models.CASCADE, related_name='comenzi')
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    nr_serie = models.CharField(max_length=20, unique=True)
    nume = models.CharField(max_length=100)
    email = models.EmailField()
    telefon = models.CharField(max_length=20)
    adresa = models.TextField()
    achitata = models.BooleanField(default=False)
    bilete = models.JSONField(default=list, blank=True)  # lista de bilete ca dicturi: [{ "tip_id": 1, "nume": "Ion Popescu", "email": "ion@example.com" }, ...]
    created_at = models.DateTimeField(auto_now_add=True)
    total = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)  # 🆕 Câmp pentru total

    #fiscalitate
    fee_biletis = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    fee_stripe = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    fee_total = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
    plata_neta = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)


    #Checkout ID
    checkout_session_id = models.CharField(max_length=255, blank=True, null=True)
    charge_id = models.CharField(max_length=255, blank=True, null=True)

    # timpul până la care comanda este rezervată
    rezervata_pana = models.DateTimeField(blank=True, null=True)

    STATUS_CHOICES = [
    ('rezervata', 'Rezervată'),
    ('achitata', 'Achitată'),
    ('anulata', 'Anulată'),
    ]
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='rezervata')

    def __str__(self):
        return f"Comanda {self.nr_serie} - {self.nume}"
    
    def verifica_expirare(self):
        from .models import TipBilet
        if self.status == 'rezervata' and self.rezervata_pana < timezone.now():
            # scadem nr_vandute pentru fiecare tip
            for b in self.bilete:
                tip = TipBilet.objects.get(id=b['tip_id'])
                tip.nr_vandute -= 1
                tip.save()
            self.status = 'anulata'
            self.save()

    
    def save(self, *args, **kwargs):
        if not self.nr_serie:
            nr = ContorComenzi.get_next_nr()
            self.nr_serie = f"{nr:06d}"
        if not self.rezervata_pana:
            self.rezervata_pana = timezone.now() + timedelta(minutes=15)
        if not self.status:
            self.status = 'rezervata'

        super().save(*args, **kwargs)


#Chitante

class ContorChitante(models.Model):
    serie = models.CharField(max_length=10, default="CHT")
    numar_curent = models.PositiveIntegerField(default=1)

    def __str__(self):
        return f"{self.serie} - {self.numar_curent:06d}"
    
    def reset(self, start=1):
        self.numar_curent = start
        self.save()


class UserFile(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='files')
    file = models.FileField(upload_to='user_files/%Y/%m/%d/')
    folder = models.CharField(max_length=100, default='General')
    uploaded_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.file.name} ({self.user})"

"""
class Chitanta(models.Model):
    comanda = models.ForeignKey(Comanda, on_delete=models.CASCADE, related_name="chitante")

    serie = models.CharField(max_length=10, default="BLTS")
    numar = models.PositiveIntegerField(blank=True, null=True)

    # Date firmă emitent (se iau din superuser)
    firma = models.CharField(max_length=255, blank=True)
    cui = models.CharField(max_length=50, blank=True)
    adresa = models.CharField(max_length=255, blank=True)
    cont_bancar = models.CharField(max_length=50, blank=True)

    emis_la = models.DateTimeField(auto_now_add=True)

    def save(self, *args, **kwargs):
        # Setare număr din contor (dacă nu există deja)
        if not self.numar:
            contor, _ = ContorChitante.objects.get_or_create(serie=self.serie)
            self.numar = contor.numar_curent
            contor.numar_curent += 1
            contor.save()

        # Preluare date firmă din superuser (doar prima dată)
        if not self.firma:
            superuser = User.objects.filter(is_superuser=True).first()
            if superuser:
                self.firma = superuser.companie_nume or ""
                self.cui = superuser.companie_cod_fiscal or ""
                self.adresa = superuser.companie_adresa or ""
                self.cont_bancar = superuser.companie_cont_bancar or ""

        super().save(*args, **kwargs)

    def __str__(self):
        return f"Chitanța {self.serie}-{self.numar:06d} pentru {self.comanda.nume}"
"""