#  Copyright (c) 2025  Jeffrey Hsu - JITToolBox
#  #
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  #
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  #
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import json
from abc import ABC, abstractmethod
from os import PathLike
from typing import Optional

import openpyxl
from openpyxl.workbook import Workbook
from openpyxl.worksheet.worksheet import Worksheet

from toolbox.models.data_model import ClassInfo
from toolbox.models.config import AESConfig


class BaseExcelService(ABC):
    _file_path: str | PathLike
    _workbook: Optional[Workbook]
    _sheet: None

    @abstractmethod
    def open(self, *args, **kwargs) -> 'BaseExcelService':
        ...

    @abstractmethod
    def save(self) -> 'BaseExcelService':
        ...

    @abstractmethod
    def close(self) -> None:
        ...

    @abstractmethod
    def active_sheet(self, sheet_name: str) -> 'BaseExcelService':
        ...

    @property
    @abstractmethod
    def cur_active_sheet(self) -> Worksheet:
        ...


class ExcelService(BaseExcelService):
    def __init__(self, file_path: str | PathLike):
        self._file_path = file_path
        self._workbook = None
        self._sheet = None

    def open(self, *args, **kwargs):
        self._workbook = openpyxl.load_workbook(self._file_path, *args, **kwargs)
        return self

    def save(self):
        self._workbook.save(self._file_path)
        return self

    def close(self):
        self._workbook.close()

    def active_sheet(self, sheet_name: str):
        self._sheet = self._workbook[sheet_name]
        return self

    @property
    def cur_active_sheet(self):
        return self._sheet

    def load_value(self, cell: str):
        if self._sheet is None:
            raise ValueError("No active sheet. Please set an active sheet first.")
        return self._sheet[cell].value


class AchievementExcelService(ExcelService):
    version = ''
    config = {}

    def __init__(self, file_path: str | PathLike):
        super().__init__(file_path)
        self.open(read_only=True, data_only=True)

    def load_config(self, config_path: str | PathLike):
        self.config = AESConfig(config_path)

    def read_class_info(self) -> list[ClassInfo]:
        lst = []
        self.active_sheet('初始录入')
        full_name = self.load_value(self.config['class_full_name'].position)

        for i in range(self.config['class_single_name'].start, self.config['class_single_name'].end):
            name = self.load_value(self.config['class_single_name'].fposition.format(i))
            number = self.load_value(self.config['class_single_number'].fposition.format(i))

            if name is None or number is None:
                break

            ci = ClassInfo(name, number)
            ci.full_name = full_name
            lst.append(ci)

        if len(lst) == 0:
            raise ValueError("No class information found in the Excel file.")

        return lst

    def read_course_info(self):
        ...
