# 定义一个图书类
import atexit
import os

import yaml


class Book:

    # 使用构造函数，接收实例化类时需要传入的参数
    def __init__(self, bid, name, price, summary):
        # 使用实例属性接收传入的值
        self.bid = bid
        self.name = name
        self.price = price
        self.summary = summary

    # 重写对象的显示格式方法
    def __str__(self):
        return f"Bid: {self.bid} --- Name: {self.name} --- Price: {self.price} --- Summary: {self.summary}"


# 封装管理类
class BookManagement:

    def __init__(self, filename='D:\\python脚本\\project_book\\book_data.yaml'):
        # 定义一个实例变量，用来保存图书的信息，方便各个方法之间进行访问
        # 把这个实例变量设置为私有，只能让类中方法对其进行操作
        self.filename = filename
        self.__books = []
        atexit.register(self.save_data)
        self.load_data()

    def __menu(self):
        '''
        菜单函数：展示图书管理系统菜单信息，并获取用户输入
        :return:  用户输入的编号字符串
        '''
        print("*****************************")
        print("*      图书管理系统           *")
        print("* 1. 添加新图书信息           *")
        print("* 2. 通过编号修改图书信息      *")
        print("* 3. 通过编号删除图书信息      *")
        print("* 4. 通过书名删除图书信息      *")
        print("* 5. 通过编号查询图书信息      *")
        print("* 6. 通过书名查询图书信息      *")
        print("* 7. 显示所有图书信息         *")
        print("* 8. 退出系统                *")
        print("*****************************")
        select_op = input("输入编号选择操作：")
        return select_op

    def __get_bid(self):
        '''
        获取用户输入的图书编号
        :return: 返回编号字符串
        '''
        bid = input("请输入图书编号:")
        return bid

    def __get_name(self):
        '''
        获取用户输入的名字
        :return: 返回名字字符串
        '''
        name = input("请输入图书名字：")
        return name

    def __get_price(self):
        '''
        获取用户输入的价格
        :return: 返回价格字符串
        '''
        while True:
            price = input("请输入图书价格：")
            if price.isdigit():
                return int(price)
            else:
                print("输入价格不合法，请输入数字")

    def __get_summary(self):
        '''
        获取用户输入的简介
        :return: 返回简介字符串
        '''
        summary = input("请输入图书简介：")
        return summary

    def add_book(self, bid, name, price, summary):
        '''
        添加图书
        :param bid: 图书编号 id
        :param name: 图书名字
        :param price: 图书价格
        :param summary: 图书简介
        :return: 操作提示信息
        '''
        for s in self.__books:
            if s["bid"] == bid:
                print("图书编号已存在，添加失败")
                return "添加失败"
        else:
            book = Book(bid, name, price, summary)
            self.__books.append({
                'bid': bid,
                'name': name,
                'price': price,
                'summary': summary
            })
            print(f"添加图书{book}成功")
            return '添加成功'

    def modify_book_by_id(self, bid, name, price, summary):
        '''
        通过编号修改图书信息
        :param bid: 图书编号
        :return: 操作提示信息
        '''
        for s in self.__books:
            if s["bid"] == bid:
                s['name'] = name
                s["price"] = price
                s["summary"] = summary
                print("修改成功")
                return "修改成功"
        else:
            print(f'没有 {bid} 对应的图书信息')
            return "修改失败"

    def delete_book_by_id(self, bid):
        '''
        通过ID删除图书信息
        :param bid: 图书编号
        :return: 操作提示信息
        '''
        for s in self.__books:
            if s["bid"] == bid:
                self.__books.remove(s)
                print("删除成功")
                return "删除成功"
        else:
            print(f'没有 {bid} 对应的学生信息')
            return "删除失败"

    def delete_book_by_name(self, name):
        '''
        通过图书名称 删除所有符合的图书
        :param name: 图书名称
        :return: 操作提示信息
        '''
        exist_s = []
        # 找出所有要删除的图书
        for s in self.__books:
            if s["name"] == name:
                exist_s.append(s)

        # 开始删除
        if len(exist_s) > 0:
            for s in exist_s:
                self.__books.remove(s)
                print(f"名字为 {name} 的图书删除成功")
            else:
                print(f"成功删除 {len(exist_s)} 本图书")
                return "删除成功"
        else:
            print(f"图书【{name}】不存在，无法删除")
            return "删除失败"

    def query_book_by_id(self, bid):
        '''
        通过编号查询图书信息
        :param bid: 图书编号
        :return: 操作提示信息
        '''
        for s in self.__books:
            if s["bid"] == bid:
                print(f"图书编号 {bid} 的图书信息如下：")
                print(f"编号：{s['bid']}，名字：{s['name']}，价格：{s['price']}，简介：{s['summary']}")
                return "查询成功"
        else:
            print(f"图书编号 {bid} 的图书不存在")
            return "查询失败"

    def query_book_by_name(self, name):
        '''
        通过名字查询图书信息
        :param name:
        :return: 操作提示信息
        '''
        exist_s = []
        for s in self.__books:
            if s["name"] == name:
                exist_s.append(s)

        if len(exist_s) > 0:
            print(f"名字为 {name} 的图书共 {len(exist_s)} 本，信息如下：")
            for s in exist_s:
                print(f"编号：{s['bid']}，名字：{s['name']}，价格：{s['price']}，简介：{s['summary']}")
            return "查询成功"
        else:
            print(f"名字为 {name} 的图书不存在")
            return "查询失败"

    def show(self):
        '''
        显示所有图书信息
        :return: 格式化的图书信息
        '''
        print("所有图书信息如下：")
        for s in self.__books:
            print(f"编号：{s['bid']}，姓名：{s['name']}，价格：{s['price']}，简介：{s['summary']}")

    def save_data(self):
        with open(self.filename, 'w') as f:
            yaml.dump(self.__books, f)
        print(f"数据已保存至 {self.filename}")

    def load_data(self):
        if os.path.exists(self.filename):
            with open(self.filename) as f:
                self.__books = yaml.safe_load(f) or []
            print(f"成功从 {self.filename} 加载数据")
        else:
            self.__books = []
            print("数据文件不存在，已初始化空列表")

    def manager(self):
        '''
        管理方法
        :return:
        '''
        while True:
            select_op = self.__menu()
            if len(select_op) == 1 and select_op in "12345678":
                if select_op == "1":
                    bid = self.__get_bid()
                    name = self.__get_name()
                    age = self.__get_price()
                    gender = self.__get_summary()
                    self.add_book(bid, name, age, gender)
                elif select_op == "2":
                    bid = self.__get_bid()
                    name = self.__get_name()
                    age = self.__get_price()
                    gender = self.__get_summary()
                    self.modify_book_by_id(bid, name, age, gender)
                elif select_op == "3":
                    bid = self.__get_bid()
                    self.delete_book_by_id(bid)
                elif select_op == "4":
                    name = self.__get_name()
                    self.delete_book_by_name(name)
                elif select_op == "5":
                    bid = self.__get_bid()
                    self.query_book_by_id(bid)
                elif select_op == "6":
                    name = self.__get_name()
                    self.query_book_by_name(name)
                elif select_op == "7":
                    self.show()
                else:
                    break
            else:
                print("输入的数据不合法，请输入在合法范围内的操作编号！！！")


# 程序入口
if __name__ == '__main__':
    # 获取图书管理系统实例
    bm = BookManagement()
    # 通过实例调用实例方法
    bm.manager()
