from django.db import models

from apps.common.models import TeamOwnedModel, TimeStampedModel


class Project(TeamOwnedModel):
    class Status(models.TextChoices):
        DRAFT = "draft", "Draft"
        SCRIPTING = "scripting", "Scripting"
        ASSETING = "asseting", "Asseting"
        STORYBOARDING = "storyboarding", "Storyboarding"
        VIDEOING = "videoing", "Videoing"
        EXPORTING = "exporting", "Exporting"
        COMPLETED = "completed", "Completed"
        FAILED = "failed", "Failed"

    name = models.CharField(max_length=255)
    product = models.ForeignKey("products.Product", on_delete=models.PROTECT, related_name="projects")
    status = models.CharField(max_length=32, choices=Status.choices, default=Status.DRAFT)
    current_stage = models.CharField(max_length=32, default="script")
    budget_limit = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
    failure_reason = models.TextField(blank=True)
    metadata = models.JSONField(default=dict, blank=True)

    class Meta:
        indexes = [
            models.Index(fields=["team", "status"]),
            models.Index(fields=["team", "current_stage"]),
        ]

    def __str__(self) -> str:
        return self.name


class ProjectStage(TimeStampedModel):
    class Stage(models.TextChoices):
        SCRIPT = "script", "Script"
        BASE_ASSETS = "base_assets", "Base Assets"
        STORYBOARD = "storyboard", "Storyboard"
        VIDEO = "video", "Video"
        EXPORT = "export", "Export"

    class Status(models.TextChoices):
        NOT_STARTED = "not_started", "Not Started"
        DRAFT = "draft", "Draft"
        QUEUED = "queued", "Queued"
        RUNNING = "running", "Running"
        SUCCEEDED = "succeeded", "Succeeded"
        FAILED = "failed", "Failed"
        SKIPPED = "skipped", "Skipped"
        NEEDS_REVIEW = "needs_review", "Needs Review"

    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="stages")
    stage = models.CharField(max_length=32, choices=Stage.choices)
    status = models.CharField(max_length=32, choices=Status.choices, default=Status.NOT_STARTED)
    started_at = models.DateTimeField(null=True, blank=True)
    completed_at = models.DateTimeField(null=True, blank=True)
    error_message = models.TextField(blank=True)
    metadata = models.JSONField(default=dict, blank=True)

    class Meta:
        unique_together = [("project", "stage")]
        ordering = ["created_at"]


class ScriptVersion(TimeStampedModel):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="script_versions")
    task = models.ForeignKey("ai.AITask", on_delete=models.SET_NULL, null=True, blank=True, related_name="script_versions")
    title = models.CharField(max_length=128, blank=True)
    content = models.TextField()
    source = models.CharField(max_length=32, default="ai")
    is_adopted = models.BooleanField(default=False)
    metadata = models.JSONField(default=dict, blank=True)


class ScriptSegment(TimeStampedModel):
    script_version = models.ForeignKey(ScriptVersion, on_delete=models.CASCADE, related_name="segments")
    sort_order = models.PositiveIntegerField(default=0)
    duration_seconds = models.PositiveIntegerField(default=15)
    narration = models.TextField(blank=True)
    visual_prompt = models.TextField(blank=True)
    product_points = models.JSONField(default=list, blank=True)

    class Meta:
        ordering = ["sort_order", "created_at"]


class BaseAssetGroup(TimeStampedModel):
    class Kind(models.TextChoices):
        PRODUCT = "product", "Product"
        PERSON = "person", "Person"
        SCENE = "scene", "Scene"

    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="base_asset_groups")
    kind = models.CharField(max_length=32, choices=Kind.choices)
    task = models.ForeignKey("ai.AITask", on_delete=models.SET_NULL, null=True, blank=True, related_name="base_asset_groups")
    prompt = models.TextField(blank=True)
    adopted_asset = models.ForeignKey(
        "assets.Asset",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="adopted_base_groups",
    )
    candidate_assets = models.ManyToManyField("assets.Asset", blank=True, related_name="candidate_base_groups")
    version = models.PositiveIntegerField(default=1)
    metadata = models.JSONField(default=dict, blank=True)

    class Meta:
        indexes = [models.Index(fields=["project", "kind"])]


class StoryboardVersion(TimeStampedModel):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="storyboard_versions")
    task = models.ForeignKey(
        "ai.AITask",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="storyboard_versions",
    )
    prompt = models.TextField(blank=True)
    is_adopted = models.BooleanField(default=False)
    metadata = models.JSONField(default=dict, blank=True)


class StoryboardFrame(TimeStampedModel):
    storyboard = models.ForeignKey(StoryboardVersion, on_delete=models.CASCADE, related_name="frames")
    script_segment = models.ForeignKey(
        ScriptSegment,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="storyboard_frames",
    )
    asset = models.ForeignKey("assets.Asset", on_delete=models.PROTECT, related_name="storyboard_frames")
    sort_order = models.PositiveIntegerField(default=0)
    prompt = models.TextField(blank=True)

    class Meta:
        ordering = ["sort_order", "created_at"]


class VideoSegment(TimeStampedModel):
    class Status(models.TextChoices):
        NOT_STARTED = "not_started", "Not Started"
        QUEUED = "queued", "Queued"
        RUNNING = "running", "Running"
        SUCCEEDED = "succeeded", "Succeeded"
        FAILED = "failed", "Failed"

    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="video_segments")
    script_segment = models.ForeignKey(
        ScriptSegment,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="video_segments",
    )
    sort_order = models.PositiveIntegerField(default=0)
    target_duration_seconds = models.PositiveIntegerField(default=15)
    status = models.CharField(max_length=32, choices=Status.choices, default=Status.NOT_STARTED)
    adopted_version = models.ForeignKey(
        "projects.VideoSegmentVersion",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="adopted_by_segments",
    )
    error_message = models.TextField(blank=True)

    class Meta:
        unique_together = [("project", "sort_order")]
        ordering = ["sort_order", "created_at"]


class VideoSegmentVersion(TimeStampedModel):
    video_segment = models.ForeignKey(VideoSegment, on_delete=models.CASCADE, related_name="versions")
    task = models.ForeignKey("ai.AITask", on_delete=models.SET_NULL, null=True, blank=True, related_name="video_versions")
    asset = models.ForeignKey("assets.Asset", on_delete=models.PROTECT, related_name="video_segment_versions")
    prompt = models.TextField(blank=True)
    is_adopted = models.BooleanField(default=False)
    metadata = models.JSONField(default=dict, blank=True)


class Timeline(TimeStampedModel):
    project = models.OneToOneField(Project, on_delete=models.CASCADE, related_name="timeline")
    name = models.CharField(max_length=255, blank=True)
    aspect_ratio = models.CharField(max_length=16, default="9:16")
    resolution = models.CharField(max_length=32, default="1080x1920")
    duration_seconds = models.PositiveIntegerField(default=60)
    metadata = models.JSONField(default=dict, blank=True)


class TimelineClip(TimeStampedModel):
    timeline = models.ForeignKey(Timeline, on_delete=models.CASCADE, related_name="clips")
    asset = models.ForeignKey("assets.Asset", on_delete=models.PROTECT, related_name="timeline_clips")
    sort_order = models.PositiveIntegerField(default=0)
    start_ms = models.PositiveIntegerField(default=0)
    duration_ms = models.PositiveIntegerField(default=15000)
    trim_start_ms = models.PositiveIntegerField(default=0)
    trim_end_ms = models.PositiveIntegerField(null=True, blank=True)

    class Meta:
        ordering = ["sort_order", "created_at"]


class SubtitleTrack(TimeStampedModel):
    timeline = models.ForeignKey(Timeline, on_delete=models.CASCADE, related_name="subtitle_tracks")
    content = models.JSONField(default=list, blank=True)
    style = models.JSONField(default=dict, blank=True)
    enabled = models.BooleanField(default=True)


class BgmTrack(TimeStampedModel):
    timeline = models.ForeignKey(Timeline, on_delete=models.CASCADE, related_name="bgm_tracks")
    asset = models.ForeignKey("assets.Asset", on_delete=models.PROTECT, related_name="bgm_tracks")
    volume = models.PositiveIntegerField(default=60)
    start_ms = models.PositiveIntegerField(default=0)


class ExportJob(TimeStampedModel):
    class Status(models.TextChoices):
        DRAFT = "draft", "Draft"
        QUEUED = "queued", "Queued"
        RUNNING = "running", "Running"
        SUCCEEDED = "succeeded", "Succeeded"
        FAILED = "failed", "Failed"

    timeline = models.ForeignKey(Timeline, on_delete=models.CASCADE, related_name="export_jobs")
    status = models.CharField(max_length=32, choices=Status.choices, default=Status.DRAFT)
    task = models.ForeignKey("ai.AITask", on_delete=models.SET_NULL, null=True, blank=True, related_name="export_jobs")
    output_asset = models.ForeignKey("assets.Asset", on_delete=models.SET_NULL, null=True, blank=True, related_name="export_jobs")
    progress = models.PositiveIntegerField(default=0)
    error_message = models.TextField(blank=True)
    metadata = models.JSONField(default=dict, blank=True)

