"""Unit tests for profile/preset/sequence bundle import/export."""

import json
import sys
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PROJECT_ROOT / "src"))

from models.pallet import Palette  # noqa: E402
from models.preset import Preset  # noqa: E402
from models.profile import Profile  # noqa: E402
from models.sequence import Sequence  # noqa: E402
from models.zone import Zone  # noqa: E402
from util.profile_bundle import (  # noqa: E402
    export_preset_bundle,
    export_profile_bundle,
    export_sequence_bundle,
    import_preset_bundle,
    import_profile_bundle,
    import_sequence_bundle,
)


def _fresh_models(tmp_path, monkeypatch):
    import models.model as model_mod

    db = tmp_path / "db"
    db.mkdir()
    monkeypatch.setattr(model_mod, "_db_dir", lambda: str(db))

    for cls in (Profile, Zone, Preset, Sequence, Palette):
        if hasattr(cls, "_instance"):
            delattr(cls, "_instance")

    profiles = Profile()
    zones = Zone()
    presets = Preset()
    sequences = Sequence()
    palette = Palette()
    return profiles, zones, presets, sequences, palette


def test_profile_export_import_round_trip(tmp_path, monkeypatch):
    profiles, zones, presets, sequences, palette = _fresh_models(tmp_path, monkeypatch)

    pid = profiles.create("Source")
    zid = zones.create(name="main")
    preset_id = presets.create(pid)
    presets.update(
        preset_id,
        {
            "name": "Test preset",
            "pattern": "blink",
            "colors": ["#ff0000"],
            "brightness": 200,
            "delay": 50,
        },
    )
    zones.update(
        zid,
        {
            "presets_flat": [str(preset_id)],
            "default_preset": str(preset_id),
        },
    )
    seq_id = sequences.create(pid)
    sequences.update(
        seq_id,
        {
            "name": "Beat seq",
            "lanes": [[{"preset_id": str(preset_id), "group_ids": [], "beats": 2}]],
            "lanes_group_ids": [[]],
        },
    )
    zones.update(zid, {"sequence_ids": [str(seq_id)]})
    profiles.update(pid, {"zones": [str(zid)]})
    palette_id = profiles.read(pid)["palette_id"]
    palette.update(palette_id, {"colors": ["#112233", "#445566"]})

    bundle = export_profile_bundle(
        str(pid), profiles, zones, presets, sequences, palette
    )
    assert bundle["kind"] == "profile"
    assert str(preset_id) in bundle["presets"]
    assert str(seq_id) in bundle["sequences"]
    assert bundle["palette"]["colors"] == ["#112233", "#445566"]

    new_pid, _ = import_profile_bundle(
        bundle, profiles, zones, presets, sequences, palette, name="Imported"
    )
    assert new_pid != str(pid)
    found = [
        presets.read(k)
        for k in presets.list()
        if isinstance(presets.read(k), dict)
        and str(presets.read(k).get("profile_id")) == str(new_pid)
        and presets.read(k).get("name") == "Test preset"
    ]
    assert found


def test_preset_export_import(tmp_path, monkeypatch):
    profiles, zones, presets, sequences, palette = _fresh_models(tmp_path, monkeypatch)
    pid = profiles.create("P")
    preset_id = presets.create(pid)
    presets.update(preset_id, {"name": "Solo", "pattern": "on", "colors": ["#00ff00"]})

    bundle = export_preset_bundle(str(preset_id), presets)
    assert bundle["kind"] == "preset"

    new_id, data = import_preset_bundle(bundle, presets, str(pid))
    assert new_id != str(preset_id)
    assert data["name"] == "Solo"


def test_sequence_export_import_with_presets(tmp_path, monkeypatch):
    profiles, zones, presets, sequences, palette = _fresh_models(tmp_path, monkeypatch)
    pid = profiles.create("P")
    preset_id = presets.create(pid)
    presets.update(preset_id, {"name": "Step", "pattern": "off"})
    seq_id = sequences.create(pid)
    sequences.update(
        seq_id,
        {"name": "S", "lanes": [[{"preset_id": str(preset_id), "beats": 1}]]},
    )

    bundle = export_sequence_bundle(str(seq_id), sequences, presets, profile_id=str(pid))
    assert str(preset_id) in bundle["presets"]

    new_seq_id, doc = import_sequence_bundle(bundle, sequences, presets, str(pid))
    assert new_seq_id != str(seq_id)
    assert doc["lanes"][0][0]["preset_id"] != str(preset_id)
