import os
import uuid

from django.contrib.auth.models import User
from django.core.validators import FileExtensionValidator
from django.db import models
from django.urls import reverse
from django.utils.text import slugify

EVIDENCE_FILE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'pdf']
IMAGE_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'}
DRAFT_UPLOAD_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'pdf']


class Tag(models.Model):
    name = models.CharField('Name', max_length=100, unique=True)
    slug = models.SlugField('Slug', max_length=120, unique=True, blank=True)

    class Meta:
        verbose_name = 'Schlagwort'
        verbose_name_plural = 'Schlagwörter'
        ordering = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)


class Category(models.Model):
    name = models.CharField('Name', max_length=200)
    slug = models.SlugField('Slug', max_length=220, unique=True, blank=True)
    description = models.TextField('Beschreibung')
    icon = models.CharField(
        'Icon (Bootstrap Icons Klasse)',
        max_length=50,
        blank=True,
        help_text='z. B. bi-thermometer-half',
    )
    created_at = models.DateTimeField('Erstellt am', auto_now_add=True)

    class Meta:
        verbose_name = 'Kategorie'
        verbose_name_plural = 'Kategorien'
        ordering = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('claims:category_detail', kwargs={'slug': self.slug})

    @property
    def claim_count(self):
        return self.claims.count()


class Claim(models.Model):
    class Status(models.TextChoices):
        FALSCH = 'falsch', 'Falsch'
        IRREFUEHREND = 'irrefuehrend', 'Irreführend'
        TEILWEISE_RICHTIG = 'teilweise_richtig', 'Teilweise richtig'
        UNBELEGT = 'unbelegt', 'Unbelegt'
        WISSENSCHAFTLICHER_KONSENS = 'wissenschaftlicher_konsens', 'Wissenschaftlicher Konsens'
        OFFENE_FRAGE = 'offene_frage', 'Offene Frage'

    class EvidenceLevel(models.TextChoices):
        SEHR_STARK = 'sehr_stark', 'Sehr stark'
        STARK = 'stark', 'Stark'
        MITTEL = 'mittel', 'Mittel'
        SCHWACH = 'schwach', 'Schwach'

    category = models.ForeignKey(
        Category,
        on_delete=models.CASCADE,
        related_name='claims',
        verbose_name='Kategorie',
    )
    title = models.CharField('Titel (Behauptung)', max_length=300)
    slug = models.SlugField('Slug', max_length=320, unique=True, blank=True)
    status = models.CharField(
        'Status',
        max_length=40,
        choices=Status.choices,
        default=Status.UNBELEGT,
    )
    short_answer = models.TextField('Kurzantwort')
    detailed_explanation = models.TextField('Ausführliche Erklärung', blank=True)
    evidence_level = models.CharField(
        'Evidenzlevel',
        max_length=20,
        choices=EvidenceLevel.choices,
        default=EvidenceLevel.MITTEL,
    )
    tags = models.ManyToManyField(Tag, blank=True, verbose_name='Schlagwörter')
    created_at = models.DateTimeField('Erstellt am', auto_now_add=True)
    updated_at = models.DateTimeField('Aktualisiert am', auto_now=True)

    class Meta:
        verbose_name = 'Behauptung'
        verbose_name_plural = 'Behauptungen'
        ordering = ['-updated_at']

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            base_slug = slugify(self.title)
            slug = base_slug
            counter = 1
            while Claim.objects.filter(slug=slug).exclude(pk=self.pk).exists():
                slug = f'{base_slug}-{counter}'
                counter += 1
            self.slug = slug
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('claims:claim_detail', kwargs={'slug': self.slug})

    def get_status_badge_class(self):
        mapping = {
            self.Status.FALSCH: 'danger',
            self.Status.IRREFUEHREND: 'warning',
            self.Status.TEILWEISE_RICHTIG: 'info',
            self.Status.UNBELEGT: 'secondary',
            self.Status.WISSENSCHAFTLICHER_KONSENS: 'success',
            self.Status.OFFENE_FRAGE: 'primary',
        }
        return mapping.get(self.status, 'secondary')

    def get_evidence_badge_class(self):
        mapping = {
            self.EvidenceLevel.SEHR_STARK: 'success',
            self.EvidenceLevel.STARK: 'primary',
            self.EvidenceLevel.MITTEL: 'info',
            self.EvidenceLevel.SCHWACH: 'warning',
        }
        return mapping.get(self.evidence_level, 'secondary')


def evidence_upload_path(instance, filename):
    ext = os.path.splitext(filename)[1].lower().lstrip('.') or 'bin'
    if ext not in EVIDENCE_FILE_EXTENSIONS:
        ext = 'bin'
    claim_id = instance.claim_id or 'new'
    return f'evidence/{claim_id}/{uuid.uuid4().hex[:12]}.{ext}'


class EvidenceFile(models.Model):
    claim = models.ForeignKey(
        Claim,
        on_delete=models.CASCADE,
        related_name='evidence_files',
        verbose_name='Behauptung',
    )
    title = models.CharField('Titel', max_length=200, blank=True)
    file = models.FileField(
        'Datei',
        upload_to=evidence_upload_path,
        max_length=500,
        validators=[FileExtensionValidator(allowed_extensions=EVIDENCE_FILE_EXTENSIONS)],
        help_text='Bilder (JPG, PNG, GIF, WebP, SVG) oder PDF',
    )
    caption = models.CharField('Bildunterschrift', max_length=500, blank=True)
    order = models.PositiveSmallIntegerField('Reihenfolge', default=0)
    created_at = models.DateTimeField('Hochgeladen am', auto_now_add=True)

    class Meta:
        verbose_name = 'Nachweis'
        verbose_name_plural = 'Nachweise'
        ordering = ['order', 'id']

    def __str__(self):
        return self.display_title

    @property
    def display_title(self):
        if self.title:
            return self.title
        return self.file.name.rsplit('/', 1)[-1]

    @property
    def file_extension(self):
        return self.file.name.rsplit('.', 1)[-1].lower()

    @property
    def is_image(self):
        return self.file_extension in IMAGE_EXTENSIONS

    @property
    def is_pdf(self):
        return self.file_extension == 'pdf'

    @property
    def image_alt(self):
        return self.caption or 'Nachweis-Grafik'


class Source(models.Model):
    claim = models.ForeignKey(
        Claim,
        on_delete=models.CASCADE,
        related_name='sources',
        verbose_name='Behauptung',
    )
    title = models.CharField('Titel', max_length=300)
    organization = models.CharField('Autor/Organisation', max_length=200)
    url = models.URLField('Link', max_length=500)
    description = models.TextField('Beschreibung', blank=True)

    class Meta:
        verbose_name = 'Quelle'
        verbose_name_plural = 'Quellen'
        ordering = ['id']

    def __str__(self):
        return self.title


class CounterArgument(models.Model):
    claim = models.ForeignKey(
        Claim,
        on_delete=models.CASCADE,
        related_name='counter_arguments',
        verbose_name='Behauptung',
    )
    argument = models.TextField('Gegenargument')
    response = models.TextField('Antwort')

    class Meta:
        verbose_name = 'Gegenargument'
        verbose_name_plural = 'Gegenargumente'
        ordering = ['id']

    def __str__(self):
        return self.argument[:80]


def draft_upload_path(instance, filename):
    return f'drafts/{instance.pk or "new"}/{filename}'


class ClaimDraft(models.Model):
    class DraftStatus(models.TextChoices):
        PROCESSING = 'processing', 'Wird verarbeitet'
        REVIEW = 'review', 'Zur Prüfung'
        PUBLISHED = 'published', 'Veröffentlicht'
        FAILED = 'failed', 'Fehlgeschlagen'
        REJECTED = 'rejected', 'Abgelehnt'

    created_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='claim_drafts',
        verbose_name='Erstellt von',
    )
    status = models.CharField(
        'Status',
        max_length=20,
        choices=DraftStatus.choices,
        default=DraftStatus.PROCESSING,
    )
    article_url = models.URLField('Artikel-URL', max_length=500, blank=True)
    user_notes = models.TextField('Eingabe / Beschreibung', blank=True)
    uploaded_file = models.FileField(
        'Hochgeladene Datei',
        upload_to='drafts/uploads/%Y/%m/',
        max_length=500,
        blank=True,
        validators=[FileExtensionValidator(allowed_extensions=DRAFT_UPLOAD_EXTENSIONS)],
        help_text='Optional: Bild oder PDF als Kontext',
    )
    article_text = models.TextField('Extrahierter Artikeltext', blank=True)

    category_slug = models.SlugField(
        'Bestehende Kategorie (Slug)',
        max_length=220,
        blank=True,
        help_text='Slug einer vorhandenen Kategorie, falls passend',
    )
    new_category_name = models.CharField('Neue Kategorie', max_length=200, blank=True)
    new_category_description = models.TextField('Beschreibung neue Kategorie', blank=True)
    new_category_icon = models.CharField(
        'Icon neue Kategorie',
        max_length=50,
        blank=True,
        help_text='Bootstrap-Icon-Klasse, z. B. bi-thermometer-half',
    )

    title = models.CharField('Behauptung', max_length=300, blank=True)
    claim_status = models.CharField(
        'Einordnung',
        max_length=40,
        choices=Claim.Status.choices,
        blank=True,
    )
    short_answer = models.TextField('Kurzantwort', blank=True)
    detailed_explanation = models.TextField('Ausführliche Erklärung', blank=True)
    evidence_level = models.CharField(
        'Evidenzlevel',
        max_length=20,
        choices=Claim.EvidenceLevel.choices,
        blank=True,
    )
    tags = models.JSONField('Schlagwörter', default=list, blank=True)
    sources = models.JSONField('Quellen', default=list, blank=True)
    counter_arguments = models.JSONField('Gegenargumente', default=list, blank=True)
    conversation = models.JSONField('Konversation', default=list, blank=True)
    ai_raw_response = models.JSONField('KI-Rohantwort', blank=True, null=True)
    error_message = models.TextField('Fehlermeldung', blank=True)
    published_claim = models.ForeignKey(
        Claim,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='origin_drafts',
        verbose_name='Veröffentlichte Behauptung',
    )
    created_at = models.DateTimeField('Erstellt am', auto_now_add=True)
    updated_at = models.DateTimeField('Aktualisiert am', auto_now=True)

    class Meta:
        verbose_name = 'Fakten-Entwurf'
        verbose_name_plural = 'Fakten-Entwürfe'
        ordering = ['-created_at']

    def __str__(self):
        return self.title or f'Entwurf #{self.pk}'

    def get_admin_review_url(self):
        return reverse('admin:claims_claimdraft_review', args=[self.pk])

    def get_admin_assistant_url(self):
        return reverse('admin:claims_claimdraft_assistant')

    def add_message(self, role, content):
        from django.utils import timezone

        messages = list(self.conversation or [])
        messages.append({
            'role': role,
            'content': content,
            'at': timezone.now().isoformat(),
        })
        self.conversation = messages
