import pytz
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from django_cryptography.fields import encrypt

from api.date_time_extractor import DEFAULT_RULES_JSON
from api.burst_detection_rules import get_default_burst_detection_rules


def get_default_config_datetime_rules():  # This is a callable
    return DEFAULT_RULES_JSON


def get_default_config_burst_detection_rules():  # This is a callable
    return get_default_burst_detection_rules()


def get_default_llm_settings():
    return {
        "enabled": False,
        "add_person": False,
        "add_location": False,
        "add_keywords": False,
        "add_camera": False,
        "add_lens": False,
        "add_album": False,
        "sentiment": 0,
        "custom_prompt": "",
        "custom_prompt_enabled": False,
    }


def get_default_public_sharing_settings():
    """Default settings for what metadata to share in public albums.

    All options default to False (opt-in) for privacy-first approach.
    Users can change their defaults, and per-album overrides take precedence.
    """
    return {
        "share_location": False,  # GPS coordinates and location names
        "share_camera_info": False,  # Camera make/model, lens, settings
        "share_timestamps": False,  # Date/time when photo was taken
        "share_captions": False,  # AI-generated or user captions
        "share_faces": False,  # Detected faces (always recommend False)
    }


class User(AbstractUser):
    scan_directory = models.CharField(
        max_length=512, db_index=True, blank=True, default=""
    )
    confidence = models.FloatField(default=0.1, db_index=True)
    confidence_person = models.FloatField(default=0.9)
    image_scale = models.FloatField(default=1)
    semantic_search_topk = models.IntegerField(default=0)
    avatar = models.ImageField(upload_to="avatars", null=True, blank=True)
    transcode_videos = models.BooleanField(default=False)
    nextcloud_server_address = models.CharField(max_length=200, default="", blank=True)
    nextcloud_username = models.CharField(max_length=64, default="", blank=True)
    nextcloud_app_password = encrypt(
        models.CharField(max_length=64, default="", blank=True)
    )
    nextcloud_scan_directory = models.CharField(
        max_length=512, db_index=True, default="", blank=True
    )

    favorite_min_rating = models.IntegerField(
        default=settings.DEFAULT_FAVORITE_MIN_RATING, db_index=True
    )

    class SaveMetadata(models.TextChoices):
        OFF = "OFF"
        MEDIA_FILE = "MEDIA_FILE"
        SIDECAR_FILE = "SIDECAR_FILE"

    save_metadata_to_disk = models.TextField(
        choices=SaveMetadata.choices, default=SaveMetadata.OFF
    )
    save_face_tags_to_disk = models.BooleanField(default=False)
    llm_settings = models.JSONField(default=get_default_llm_settings)
    datetime_rules = models.JSONField(default=get_default_config_datetime_rules)
    burst_detection_rules = models.JSONField(
        default=get_default_config_burst_detection_rules
    )
    default_timezone = models.TextField(
        choices=[(x, x) for x in pytz.all_timezones],
        default="UTC",
    )
    public_sharing = models.BooleanField(default=False)
    public_sharing_defaults = models.JSONField(
        default=get_default_public_sharing_settings
    )

    # Deprecated legacy user-level setting kept only for migration compatibility.
    # Runtime face model selection is now site-wide via Constance
    # FACE_RECOGNITION_MODEL.
    class FaceRecogniton(models.TextChoices):
        HOG = "HOG"
        CNN = "CNN"

    face_recognition_model = models.TextField(
        choices=FaceRecogniton.choices, default=FaceRecogniton.HOG
    )
    min_cluster_size = models.IntegerField(default=0)
    confidence_unknown_face = models.FloatField(default=0.5)
    min_samples = models.IntegerField(default=1)
    cluster_selection_epsilon = models.FloatField(default=0.05)

    class TextAlignment(models.TextChoices):
        LEFT = "left"
        RIGHT = "right"

    text_alignment = models.TextField(
        choices=TextAlignment.choices, default=TextAlignment.RIGHT
    )

    class HeaderSize(models.TextChoices):
        LARGE = "large"
        NORMAL = "normal"
        SMALL = "small"

    header_size = models.TextField(choices=HeaderSize.choices, default=HeaderSize.LARGE)
    skip_raw_files = models.BooleanField(
        default=False
    )  # Deprecated: kept for migration compatibility
    stack_raw_jpeg = models.BooleanField(default=True)
    slideshow_interval = models.IntegerField(default=5)

    # Duplicate detection settings
    class DuplicateSensitivity(models.TextChoices):
        STRICT = "strict"
        NORMAL = "normal"
        LOOSE = "loose"

    duplicate_sensitivity = models.TextField(
        choices=DuplicateSensitivity.choices, default=DuplicateSensitivity.NORMAL
    )
    duplicate_clear_existing = models.BooleanField(default=False)


def get_admin_user():
    return User.objects.get(is_superuser=True)


def get_deleted_user():
    deleted_user: User = User.objects.get_or_create(username="deleted")[0]
    if deleted_user.is_active is not False:
        deleted_user.is_active = False
        deleted_user.save()
    return deleted_user
