import json

from django import forms
from workouts.models import Exercise, WorkoutSetEntry
from workouts.utils import display_value, normalize_weight, weight_label


class WorkoutSetsWidget(forms.Widget):
    template_name = "workouts/workout_sets_widget.html"

    class Media:
        js = ("workouts/workout_sets.js",)

    def __init__(self, *args, **kwargs):
        self.units = kwargs.pop("units", "metric")
        super().__init__(*args, **kwargs)

    def value_from_datadict(self, data, files, name):
        exercise_ids = data.getlist(f"{name}_exercise_id")
        sets_list = data.getlist(f"{name}_sets")
        reps_list = data.getlist(f"{name}_reps")
        weights = data.getlist(f"{name}_weight")
        notes = data.getlist(f"{name}_notes")
        return {
            "exercise_id": exercise_ids,
            "sets": sets_list,
            "reps": reps_list,
            "weight": weights,
            "notes": notes,
        }

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        rows = []
        if value:
            if isinstance(value, str):
                try:
                    value = json.loads(value)
                except (json.JSONDecodeError, TypeError):
                    value = []
            for item in value or []:
                if isinstance(item, dict):
                    entry = WorkoutSetEntry(**item)
                    rows.append(
                        {
                            "exercise_id": entry.exercise_id,
                            "sets": entry.sets,
                            "reps": entry.reps,
                            "weight": display_value(entry.weight_kg, self.units),
                            "notes": entry.notes,
                        }
                    )
        context["widget"]["rows"] = rows
        context["widget"]["exercises"] = Exercise.objects.all().order_by("name")
        context["widget"]["weight_label"] = weight_label(self.units)
        return context


class WorkoutSetsField(forms.Field):
    widget = WorkoutSetsWidget

    def __init__(self, *args, **kwargs):
        self.units = kwargs.pop("units", "metric")
        super().__init__(*args, **kwargs)

    def clean(self, value):
        if not value:
            return None
        result = []
        if isinstance(value, dict):
            exercise_ids = value.get("exercise_id", [])
            sets_list = value.get("sets", [])
            reps_list = value.get("reps", [])
            weights = value.get("weight", [])
            notes = value.get("notes", [])
        else:
            return None

        if not isinstance(exercise_ids, list):
            return None

        for i, exercise_id in enumerate(exercise_ids):
            if not exercise_id:
                continue
            try:
                exercise_id = int(exercise_id)
            except (ValueError, TypeError):
                continue
            sets_val = sets_list[i] if i < len(sets_list) else ""
            reps_val = reps_list[i] if i < len(reps_list) else ""
            weight_val = weights[i] if i < len(weights) else ""
            note = notes[i] if i < len(notes) else ""

            try:
                sets = int(sets_val) if sets_val else None
            except (ValueError, TypeError):
                sets = None
            try:
                reps = int(reps_val) if reps_val else None
            except (ValueError, TypeError):
                reps = None
            weight_kg = normalize_weight(weight_val, self.units)

            entry = WorkoutSetEntry(
                exercise_id=exercise_id,
                sets=sets,
                reps=reps,
                weight_kg=weight_kg,
                notes=note or None,
            )
            result.append(entry.asdict)

        return result if result else None
