"""Independent material-cleanup definitions using the existing single worker."""
from copy import deepcopy

from .errors import require
from .bag_cleanup_plan import normalize_cleanup
from .life_queue import LifeQueue, LifeQueueLists, _queue_row, run_identity


class BagCleanupQueue(LifeQueue):
    KEY="bag_cleanup"

    def snapshot(self):
        state=super().snapshot()
        for row in state["items"]:normalize_cleanup(row["params"])
        return state

    def add(self,payload):
        normalize_cleanup(payload)
        return super().add(payload)

    def update(self,identifier,payload):
        normalize_cleanup(payload)
        return super().update(identifier,payload)

    def load_tasks(self,tasks,mode="replace"):
        require(isinstance(tasks,list),"가방정리 목록 형식 오류")
        for task in tasks:normalize_cleanup(task)
        return super().load_tasks(tasks,mode)

    def selected(self,ids=None):
        rows=self.snapshot()["items"]
        if ids is None:
            require(bool(rows),"실행할 가방정리 조건이 없습니다.")
            return rows
        require(isinstance(ids,list) and bool(ids) and all(isinstance(v,str) and v for v in ids) and
                len(ids)==len(set(ids)),"선택한 가방정리 항목을 확인해 주세요.")
        selected=set(ids)
        require(selected<={row["id"] for row in rows},"선택한 가방정리 조건이 변경되었습니다.")
        return [row for row in rows if row["id"] in selected]

    def run(self,service,ids=None):
        with self.store.lock:
            self._require_editable()
            rows=self.selected(ids)
            pending=self.store.value.get("bag_cleanup_pending")
            if pending:
                require(pending.get("task_identity")==rows[0]["id"],"미확정 판매 항목을 먼저 같은 순서로 재개해 주세요.")
            # Each explicit start may re-evaluate completed conditions against
            # fresh inventory. Interrupted/uncertain work keeps its receipt.
            completed={row["id"] for row in rows if row.get("status")=="complete" and
                       (not pending or pending.get("task_identity")!=row["id"])}
            if completed:
                before=self.store.value
                queue=self.snapshot()
                for row in queue["items"]:
                    if row["id"] in completed:
                        row.update(status="pending")
                        row.pop("progress",None);row.pop("error",None)
                updated=deepcopy(before)
                updated[self.KEY]=queue
                if run_identity(updated.get("run",{})) in completed:updated.pop("run",None)
                self.store.value=updated
                try:self.store.save()
                except BaseException:
                    self.store.value=before
                    raise
                rows=self.selected(ids)
            self._executing=True
        try:return self._run_once(service,rows=rows)
        finally:
            with self.store.lock:self._executing=False

    def to_life_queue(self,ids,life_queue):
        """Copy selected definitions with fresh IDs; source conditions/run stay intact."""
        require(life_queue.store is self.store and life_queue.KEY=="life_queue","대상 큐 연결 오류")
        require(isinstance(ids,list) and bool(ids),"등록할 가방정리 조건을 선택해 주세요.")
        with self.store.lock:
            self._require_editable();life_queue._require_editable()
            source=self.snapshot();target=life_queue.snapshot()
            self._require_replaceable(source);life_queue._require_replaceable(target)
            rows=self.selected(ids)
            for row in rows:
                params,label=normalize_cleanup(row["params"])
                target["items"].append(_queue_row(dict(params=params,label=label)))
            before=self.store.value
            updated=deepcopy(before)
            updated[life_queue.KEY]=target
            self.store.value=updated
            try:self.store.save()
            except BaseException:
                self.store.value=before
                raise
            return dict(bag_cleanup=deepcopy(source),life_queue=deepcopy(target))


class BagCleanupLists(LifeQueueLists):
    KEY="bag_cleanup_lists"

    def snapshot(self):
        state=super().snapshot()
        for row in state["items"]:
            for task in row["tasks"]:normalize_cleanup(task["params"])
        return state

    def create(self,title,tasks):
        require(isinstance(tasks,list),"가방정리 저장목록 형식 오류")
        for task in tasks:normalize_cleanup(task)
        return super().create(title,tasks)

    def update(self,identifier,title,tasks,expected_revision):
        require(isinstance(tasks,list),"가방정리 저장목록 형식 오류")
        for task in tasks:normalize_cleanup(task)
        return super().update(identifier,title,tasks,expected_revision)
