#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum {
    STATUS_RETURNED = 0,   /* 已归还/在馆 */
    STATUS_BORROWED = 1    /* 已借出 */
} BookStatus;

typedef struct Book {
    char title[50];
    char publisher[50];
    char borrow_date[20];
    char return_date[20];
    BookStatus status;
    struct Book *next;
} Book;

Book *head = NULL;          /* 链表头指针 */

/* ---------- 输入辅助：读一整行，去掉换行 ---------- */
void read_line(char *buf, size_t size) {
    if (fgets(buf, (int)size, stdin) == NULL) {
        buf[0] = '\0';
        return;
    }
    if (strchr(buf, '\n') == NULL) {          /* 输入超长，清掉残留 */
        int c;
        while ((c = getchar()) != '\n' && c != EOF) { }
    } else {
        buf[strcspn(buf, "\n")] = '\0';
    }
}

const char *status_text(BookStatus s) {
    return s == STATUS_BORROWED ? "借出" : "归还";
}

/* ---------- 添加图书（尾插，保持录入顺序） ---------- */
void add_book(void) {
    Book *b = (Book *)malloc(sizeof(Book));
    if (b == NULL) { printf("内存分配失败！\n"); return; }

    printf("书名: ");
    read_line(b->title, sizeof(b->title));
    if (b->title[0] == '\0') { printf("书名不能为空！\n"); free(b); return; }

    printf("出版社: ");
    read_line(b->publisher, sizeof(b->publisher));
    printf("借出时间(如 2024-05-01，可为 -): ");
    read_line(b->borrow_date, sizeof(b->borrow_date));
    printf("归还时间(如 2024-06-01，可为 -): ");
    read_line(b->return_date, sizeof(b->return_date));

    char line[16];
    printf("状态(0=归还/在馆, 1=借出): ");
    read_line(line, sizeof(line));
    b->status = (atoi(line) == 1) ? STATUS_BORROWED : STATUS_RETURNED;

    b->next = NULL;
    if (head == NULL) {
        head = b;
    } else {
        Book *p = head;
        while (p->next != NULL) p = p->next;
        p->next = b;
    }
    printf("添加成功！\n");
}

/* ---------- 显示辅助 ---------- */
void print_header(void) {
    printf("%-20s %-20s %-14s %-14s %-6s\n",
           "书名", "出版社", "借出时间", "归还时间", "状态");
    printf("--------------------------------------------------------------------------------\n");
}

void print_book(Book *b) {
    printf("%-20s %-20s %-14s %-14s %-6s\n",
           b->title, b->publisher,
           b->borrow_date, b->return_date,
           status_text(b->status));
}

/* ---------- 查找：按书名（模糊匹配） ---------- */
void search_by_title(void) {
    char key[50];
    printf("输入书名关键字: ");
    read_line(key, sizeof(key));

    int count = 0;
    print_header();
    for (Book *p = head; p != NULL; p = p->next) {
        if (strstr(p->title, key) != NULL) {
            print_book(p);
            count++;
        }
    }
    printf("共找到 %d 本图书\n", count);
}

/* ---------- 查找：按出版社（模糊匹配） ---------- */
void search_by_publisher(void) {
    char key[50];
    printf("输入出版社关键字: ");
    read_line(key, sizeof(key));

    int count = 0;
    print_header();
    for (Book *p = head; p != NULL; p = p->next) {
        if (strstr(p->publisher, key) != NULL) {
            print_book(p);
            count++;
        }
    }
    printf("共找到 %d 本图书\n", count);
}

/* ---------- 删除的匹配函数 ---------- */
int match_title(Book *b, const char *key) {
    return strcmp(b->title, key) == 0;
}

int match_publisher(Book *b, const char *key) {
    return strcmp(b->publisher, key) == 0;
}

/* 通用删除：删除所有匹配节点，返回删除数量 */
int delete_books(int (*match)(Book *, const char *), const char *key) {
    Book *prev = NULL;
    Book *cur = head;
    int count = 0;

    while (cur != NULL) {
        if (match(cur, key)) {
            Book *del = cur;
            if (prev == NULL) head = cur->next;   /* 删除头节点 */
            else prev->next = cur->next;          /* 删除中间/尾节点 */
            cur = cur->next;
            free(del);
            count++;
        } else {
            prev = cur;
            cur = cur->next;
        }
    }
    return count;
}

void delete_by_title(void) {
    char key[50];
    printf("输入要删除的书名(完整): ");
    read_line(key, sizeof(key));
    int n = delete_books(match_title, key);
    if (n > 0) printf("已删除 %d 本图书\n", n);
    else printf("未找到该书\n");
}

void delete_by_publisher(void) {
    char key[50];
    printf("输入要删除的出版社(完整): ");
    read_line(key, sizeof(key));
    int n = delete_books(match_publisher, key);
    if (n > 0) printf("已删除 %d 本图书\n", n);
    else printf("未找到该出版社的图书\n");
}

/* ---------- 借出 / 归还登记（修改状态和时间） ---------- */
void change_status(void) {
    char title[50];
    printf("输入书名: ");
    read_line(title, sizeof(title));

    Book *p = head;
    while (p != NULL && strcmp(p->title, title) != 0) p = p->next;
    if (p == NULL) { printf("未找到该书\n"); return; }

    char line[16];
    printf("1=借出 0=归还: ");
    read_line(line, sizeof(line));
    if (atoi(line) == 1) {
        p->status = STATUS_BORROWED;
        printf("借出时间: ");
        read_line(p->borrow_date, sizeof(p->borrow_date));
    } else {
        p->status = STATUS_RETURNED;
        printf("归还时间: ");
        read_line(p->return_date, sizeof(p->return_date));
    }
    printf("状态已更新\n");
}

/* ---------- 显示全部 ---------- */
void list_books(void) {
    if (head == NULL) { printf("暂无图书\n"); return; }
    print_header();
    for (Book *p = head; p != NULL; p = p->next) print_book(p);
}

/* ---------- 释放整条链表 ---------- */
void free_all(void) {
    Book *p = head;
    while (p != NULL) {
        Book *next = p->next;
        free(p);
        p = next;
    }
    head = NULL;
}

/* ---------- 主函数 ---------- */
int main(void) {
    char line[32];
    while (1) {
        printf("\n========== 图书管理系统(链表版) ==========\n");
        printf("1. 添加图书\n");
        printf("2. 按书名查找\n");
        printf("3. 按出版社查找\n");
        printf("4. 按书名删除\n");
        printf("5. 按出版社删除\n");
        printf("6. 显示全部图书\n");
        printf("7. 借出/归还登记\n");
        printf("0. 退出\n");
        printf("请选择: ");

        read_line(line, sizeof(line));
        int choice = atoi(line);

        switch (choice) {
            case 1: add_book(); break;
            case 2: search_by_title(); break;
            case 3: search_by_publisher(); break;
            case 4: delete_by_title(); break;
            case 5: delete_by_publisher(); break;
            case 6: list_books(); break;
            case 7: change_status(); break;
            case 0:
                free_all();
                printf("再见！\n");
                return 0;
            default:
                printf("无效选项，请重新输入\n");
        }
    }
    return 0;
}