from pathlib import Path
from threading import Lock

from task.errors import TaskCallbackFailedError
from task.states.base import TaskStateBase
from task.states.error import TaskErrorState

log_lock = Lock()


class TaskReadyState(TaskStateBase):
    @property
    def name(self):
        return "ready"

    def run(self):
        self._task.logger.info("Calculation has finished")

        # Read and truncate the log file if necessary
        log_file_path = Path(self._task.log_file_handler.baseFilename)
        calculation_log = log_file_path.read_text()

        if len(calculation_log) > 20000:
            calculation_log = (
                f"{calculation_log[:10000]}\n...\n...\n...\n{calculation_log[-10000:]}"
            )

        try:
            # Send callback with result and truncated log
            self._task.send_callbacks(
                {"result": self._task.calculation.result, "log": calculation_log}
            )
            self._task.set_finished(True)
        except TaskCallbackFailedError as ex:
            self._task.logger.critical("Cannot send callback. Transitioning to error state.")
            self._task.logger.exception(ex)
            self._task.change_state(TaskErrorState(self._task))
            # Early return to avoid cleaning up the log file; error state may need it.
            return

        # Safely remove log handler and delete log file
        with log_lock:
            try:
                self._task.logger.logger.handlers.remove(self._task.log_file_handler)
                if log_file_path.exists():
                    log_file_path.unlink()  # Delete log file
                    self._task.logger.info(f"Log file {log_file_path} successfully removed.")
            except (OSError, ValueError) as exc:
                self._task.logger.warning(
                    f"Failed to remove or delete log file ({log_file_path}): {exc}"
                )
