# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""Polling adapters for Native stateful streaming scans."""

import asyncio
from copy import copy
from typing import AsyncGenerator, Iterator

from pypaimon.execution.native.read.plan import native_stream_scan, _from_native_plan
from pypaimon.read.plan import Plan


class StreamTableScan:
    """Python iterator adapter for Rust's stateful StreamTableScan.

    Rust owns snapshot selection, split planning, checkpoints and consumer
    persistence. Python only polls, converts splits and acknowledges a yielded
    plan when the caller resumes the iterator after processing it.
    """

    def __init__(self, table, predicate=None, read_type=None, poll_interval_ms=1000,
                 bucket_filter=None, consumer_id=None):
        self.table = table
        self.poll_interval = poll_interval_ms / 1000.0
        self._scan = native_stream_scan(
            table, predicate=predicate, read_type=read_type,
            bucket_filter=bucket_filter, consumer_id=consumer_id)
        self._pending_consumer_snapshot = None
        self._pending_consumer_owner = None
        self._closed = False
        self._generation = 0

    @property
    def next_snapshot_id(self):
        return self.checkpoint()

    @next_snapshot_id.setter
    def next_snapshot_id(self, next_snapshot_id):
        self.restore(next_snapshot_id)

    def checkpoint(self):
        return self._scan.checkpoint()

    def watermark(self):
        return self._scan.watermark()

    def restore(self, next_snapshot_id=None):
        self._require_open()
        self._scan.restore(next_snapshot_id)
        self._generation += 1
        self._pending_consumer_snapshot = None
        self._pending_consumer_owner = None

    def notify_checkpoint_complete(self, next_snapshot):
        self._require_open()
        self._scan.notify_checkpoint_complete(next_snapshot)

    def plan(self):
        self._require_open()
        # Decode before returning or acknowledging progress. A failed conversion
        # must leave the selected frame available for retry.
        previous = copy(self._scan)
        generation = self._generation
        native_plan = self._scan.plan()
        self._check_generation(generation)
        if native_plan is None:
            return None
        try:
            plan = _from_native_plan(self.table, native_plan)
            self._check_generation(generation)
            return plan
        except Exception:
            if not self._closed and generation == self._generation:
                self._scan = previous
            raise

    def _flush_pending_consumer(self):
        if self._pending_consumer_snapshot is not None:
            self.notify_checkpoint_complete(self._pending_consumer_snapshot)
            self._pending_consumer_snapshot = None
            self._pending_consumer_owner = None

    async def stream(self) -> AsyncGenerator[Plan, None]:
        owner = object()
        try:
            while True:
                self._flush_pending_consumer()
                checkpoint = self.checkpoint()
                plan = self.plan()
                if plan is None:
                    next_snapshot = self.checkpoint()
                    if next_snapshot is not None and next_snapshot != checkpoint:
                        # Skipped frames have no rows awaiting caller processing.
                        self._pending_consumer_snapshot = next_snapshot
                        self._pending_consumer_owner = owner
                        self._flush_pending_consumer()
                    await asyncio.sleep(self.poll_interval)
                    continue
                self._pending_consumer_snapshot = self.checkpoint()
                self._pending_consumer_owner = owner
                yield plan
        except (GeneratorExit, asyncio.CancelledError):
            if self._pending_consumer_owner is owner:
                self._pending_consumer_snapshot = None
                self._pending_consumer_owner = None
            raise

    def stream_sync(self) -> Iterator[Plan]:
        loop = asyncio.new_event_loop()
        iterator = self.stream()
        try:
            while True:
                yield loop.run_until_complete(iterator.__anext__())
        finally:
            try:
                loop.run_until_complete(iterator.aclose())
            finally:
                loop.close()

    def _require_open(self):
        if self._closed:
            raise RuntimeError("stream scan is closed")

    def _check_generation(self, generation):
        self._require_open()
        if generation != self._generation:
            raise RuntimeError("stream scan was restored during planning")

    def cancel_prefetch(self):
        """Native plans frames on demand, with no speculative frame to cancel."""

    def close(self):
        """Stop polling without acknowledging a plan still owned by the caller."""
        self._closed = True
        self._generation += 1
        self._pending_consumer_snapshot = None
        self._pending_consumer_owner = None
