import csv
import logging
from datetime import datetime

from dateutil.parser import parse as parse_datetime
from django.utils import timezone
from people.models import Person
from scrobbles.models import Scrobble
from scrobbles.notifications import ScrobbleNtfyNotification

logger = logging.getLogger(__name__)


def _parse_udisc_datetime(raw: str) -> datetime:
    dt = parse_datetime(raw)
    if timezone.is_naive(dt):
        return timezone.make_aware(dt)
    return dt


def _resolve_player(name: str, user_id: int) -> Person:
    name = name.strip()
    existing = Person.objects.filter(name=name, created_by_id=user_id).first()
    if existing:
        return existing
    return Person.objects.create(name=name, created_by_id=user_id)


def import_udisc_csv(
    file_path: str, user_id: int, record_error=None
) -> list[Scrobble]:
    from discgolf.models import DiscGolfCourse

    new_scrobbles = []

    with open(file_path, newline="", encoding="utf-8-sig") as f:
        reader = csv.DictReader(f)
        rows = list(reader)

    if not rows:
        return []

    par_row = None
    player_rows = []
    for row in rows:
        name = row.get("PlayerName", "").strip()
        if name.lower() == "par":
            par_row = row
        else:
            player_rows.append(row)

    if not par_row:
        return []

    course_name = par_row.get("CourseName", "").strip()
    layout_name = par_row.get("LayoutName", "").strip()
    start_date_raw = par_row.get("StartDate", "").strip()
    start_dt = _parse_udisc_datetime(start_date_raw) if start_date_raw else timezone.now()

    number_of_holes = sum(1 for k in par_row if k.startswith("Hole") and k[4:].isdigit())
    par_total_str = par_row.get("Total", "").strip()
    par_total = int(par_total_str) if par_total_str.isdigit() else None

    par_per_hole = {}
    for k, v in par_row.items():
        if k.startswith("Hole") and k[4:].isdigit() and v:
            hole_num = int(k[4:])
            try:
                par_per_hole[f"hole_{hole_num}"] = int(v)
            except (ValueError, TypeError):
                pass

    course, _ = DiscGolfCourse.objects.get_or_create(
        title=course_name,
        defaults={
            "layout_name": layout_name,
            "number_of_holes": number_of_holes,
            "par_total": par_total,
            "par_per_hole": par_per_hole or None,
        },
    )

    is_teams = "+" in player_rows[0].get("PlayerName", "") if player_rows else False
    round_type = "Teams" if is_teams else "Singles"

    scores = {}
    for row in player_rows:
        player_name = row.get("PlayerName", "").strip()
        hole_scores = {}
        for k, v in row.items():
            if k.startswith("Hole") and k[4:].isdigit() and v:
                hole_num = int(k[4:])
                try:
                    hole_scores[f"hole_{hole_num}"] = int(v)
                except (ValueError, TypeError):
                    pass
        total_str = row.get("Total", "").strip()
        total = int(total_str) if total_str.isdigit() else None
        if total is not None:
            hole_scores["total"] = total

        if is_teams:
            people = player_name.split("+")
            person_ids = [_resolve_player(p.strip(), user_id).id for p in people]
            hole_scores["person_ids"] = person_ids
        else:
            person = _resolve_player(player_name, user_id)
            hole_scores["person_id"] = person.id

        scores[player_name] = hole_scores

    log = {
        "scores": scores,
        "course_name": course_name,
        "par": par_total,
        "round_type": round_type,
    }

    scrobble_dict = {
        "user_id": user_id,
        "timestamp": start_dt,
        "source": "uDisc",
        "playback_position_seconds": 0,
        "log": log,
    }

    scrobble = Scrobble.create_or_update(course, user_id, scrobble_dict)
    if scrobble:
        new_scrobbles.append(scrobble)
        ScrobbleNtfyNotification(scrobble).send()

    return new_scrobbles
