-- 假设当前操作的学生是 张三 (学号 S2023001)，我们先获取其 student_id
-- 在实际应用中，这个 ID 通常来自登录会话
DO $$
DECLARE
    v_student_id bigint;
BEGIN
    SELECT student_id INTO v_student_id FROM students WHERE stu_no = 'S2023001';
    -- 将 v_student_id 设为会话级变量，方便后续查询使用
    -- 注意: 这是一种在 psql 或特定SQL工具中设置变量的方式，
    -- 在应用代码中，你会直接使用从会话中获取的 student_id 变量。
    EXECUTE 'SET app.current_student_id = ' || v_student_id;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RAISE NOTICE '学生 S2023001 未找到。请确保测试数据已插入。';
        -- 或者你可以在这里直接硬编码一个存在的 student_id 用于测试
        -- EXECUTE 'SET app.current_student_id = 1';
END $$;

-- 如果上面的 DO $$ 块由于环境限制无法执行 SET app.current_student_id，
-- 后续查询中请手动替换 current_setting('app.current_student_id')::bigint 为实际的 student_id (例如 1)

-- (1). 多条件组合查询图书
RAISE NOTICE '---------- (1) 多条件组合查询图书 ----------';

-- 按书名模糊查询 (使用 pg_trgm GIN 索引)
RAISE NOTICE '-- 按书名模糊查询 "计算机":';
SELECT book_id, isbn, title, authors, available_copies
FROM books
WHERE title LIKE '%计算机%' AND status = 'normal';

RAISE NOTICE '-- 按书名精确查询 (如果知道全名):';
SELECT book_id, isbn, title, authors, available_copies
FROM books
WHERE title = '数学之美' AND status = 'normal';

-- 按作者查询 (使用 GIN 索引)
RAISE NOTICE '-- 按作者查询包含 "吴军":';
SELECT book_id, isbn, title, authors, available_copies
FROM books
WHERE authors @> ARRAY['吴军'] AND status = 'normal'; -- '@>' 表示数组包含

-- 按分类号查询
RAISE NOTICE '-- 按分类号查询 "TP301":';
SELECT book_id, isbn, title, authors, classification_no, available_copies
FROM books
WHERE classification_no = 'TP301' AND status = 'normal';

-- 按ISBN精确查询
RAISE NOTICE '-- 按ISBN查询 "9787111624927":';
SELECT book_id, isbn, title, authors, available_copies
FROM books
WHERE isbn = '9787111624927' AND status = 'normal';

-- 组合查询：书名包含 "编程" 且 作者包含 "Eric Matthes"
RAISE NOTICE '-- 组合查询：书名包含 "编程" 且 作者包含 "Eric Matthes":';
SELECT book_id, isbn, title, authors, available_copies
FROM books
WHERE title LIKE '%编程%' AND authors @> ARRAY['Eric Matthes'] AND status = 'normal';

-- (2). 查看图书详情及当前可借状态
RAISE NOTICE '---------- (2) 查看图书详情及当前可借状态 ----------';
-- 假设查看 ISBN 为 '9787111624927' (深入理解计算机系统) 的图书详情
-- 首先获取 book_id
DO $$
DECLARE
    v_book_id bigint;
BEGIN
    SELECT book_id INTO v_book_id FROM books WHERE isbn = '9787111624927';
    EXECUTE 'SET app.current_book_id = ' || v_book_id;
END $$;

RAISE NOTICE '-- 查看图书 (ISBN: 9787111624927) 的详情:';
SELECT
    book_id,
    isbn,
    title,
    authors,
    publisher,
    publish_date,
    price,
    classification_no,
    location,
    total_copies,
    available_copies,
    status,
    description,
    cover_url,
    CASE
        WHEN status = 'normal' AND available_copies > 0 THEN '可借阅'
        WHEN status = 'normal' AND available_copies = 0 THEN '已全部借出'
        ELSE '不可借阅 (' || status::text || ')'
    END as borrow_availability
FROM books
WHERE book_id = current_setting('app.current_book_id')::bigint;

-- (3). 在线预约热门图书（当所有副本都被借出时）
RAISE NOTICE '---------- (3) 在线预约热门图书 ----------';
-- 假设要预约的书是 'Java核心技术 卷I' (book_id=7)，其 available_copies 在测试数据中为0
-- 首先确认该书确实没有可借副本
DO $$
DECLARE
    v_target_book_id bigint := 7; -- Java核心技术 卷I
    v_available int;
BEGIN
    SELECT available_copies INTO v_available FROM books WHERE book_id = v_target_book_id AND status = 'normal';
    IF v_available = 0 THEN
        RAISE NOTICE '-- 图书ID % (Java核心技术 卷I) 当前无可用副本，可以进行预约。';
        -- 学生张三 (student_id=1) 进行预约
        -- 检查是否已预约过
        IF NOT EXISTS (SELECT 1 FROM reservations
                       WHERE book_id = v_target_book_id
                         AND student_id = current_setting('app.current_student_id')::bigint
                         AND status IN ('waiting', 'available'))
        THEN
            INSERT INTO reservations (book_id, student_id, reserve_date, status)
            VALUES (v_target_book_id, current_setting('app.current_student_id')::bigint, current_date, 'waiting');
            RAISE NOTICE '-- 学生ID % 已成功预约图书ID %。', current_setting('app.current_student_id')::bigint, v_target_book_id;
        ELSE
            RAISE NOTICE '-- 学生ID % 已预约过图书ID % 或预约已可取。', current_setting('app.current_student_id')::bigint, v_target_book_id;
        END IF;
    ELSE
        RAISE NOTICE '-- 图书ID % 当前有 % 本可借，无需预约。', v_target_book_id, v_available;
    END IF;
END $$;

-- 查看张三的预约记录来确认
RAISE NOTICE '-- 查看学生张三的当前预约:';
SELECT r.reservation_id, b.title, r.reserve_date, r.status
FROM reservations r
JOIN books b ON r.book_id = b.book_id
WHERE r.student_id = current_setting('app.current_student_id')::bigint AND r.status IN ('waiting', 'available');


-- (4). 查看个人借阅历史、当前借阅情况和预约状态
RAISE NOTICE '---------- (4) 查看个人借阅历史、当前借阅情况和预约状态 ----------';

RAISE NOTICE '-- 学生张三 (ID: %) 的当前借阅情况:';
SELECT br.borrow_id, b.title, b.isbn, br.borrow_date, br.due_date, br.renew_times, br.status
FROM borrow_records br
JOIN books b ON br.book_id = b.book_id
WHERE br.student_id = current_setting('app.current_student_id')::bigint
  AND br.status IN ('borrowed', 'overdue');

RAISE NOTICE '-- 学生张三 (ID: %) 的借阅历史 (已还):';
SELECT br.borrow_id, b.title, b.isbn, br.borrow_date, br.return_date, br.status
FROM borrow_records br
JOIN books b ON br.book_id = b.book_id
WHERE br.student_id = current_setting('app.current_student_id')::bigint
  AND br.status = 'returned';

RAISE NOTICE '-- 学生张三 (ID: %) 的当前预约状态:'; -- 重复上面的预约查询，为了完整性
SELECT r.reservation_id, b.title, r.reserve_date, r.status
FROM reservations r
JOIN books b ON r.book_id = b.book_id
WHERE r.student_id = current_setting('app.current_student_id')::bigint AND r.status IN ('waiting', 'available');

-- (5). 在线续借图书（有限制条件）
RAISE NOTICE '---------- (5) 在线续借图书 ----------';
-- 假设张三要续借他借阅的《深入理解计算机系统》(book_id=1)
-- borrow_id 需要从他的当前借阅中找到，假设其 borrow_id 为 1 (根据你的测试数据)
DO $$
DECLARE
    v_borrow_id_to_renew bigint;
    v_student_id bigint := current_setting('app.current_student_id')::bigint;
    v_book_id_of_borrow bigint;
    v_max_renew_times int;
    v_borrow_duration_days int;
    v_current_renew_times int;
    v_current_due_date date;
    v_current_status borrow_status_enum;
    v_is_reserved boolean;
BEGIN
    -- 找到张三正在借阅的《深入理解计算机系统》的 borrow_id
    SELECT br.borrow_id, br.book_id, br.renew_times, br.due_date, br.status
    INTO v_borrow_id_to_renew, v_book_id_of_borrow, v_current_renew_times, v_current_due_date, v_current_status
    FROM borrow_records br
    JOIN books b ON br.book_id = b.book_id
    WHERE br.student_id = v_student_id
      AND b.isbn = '9787111624927' -- 《深入理解计算机系统》
      AND br.status = 'borrowed'
    LIMIT 1;

    IF NOT FOUND THEN
        RAISE NOTICE '-- 未找到学生ID % 对图书ISBN 9787111624927 的可续借记录。';
        RETURN;
    END IF;

    RAISE NOTICE '-- 尝试为学生ID % 续借 borrow_id % (Book ID: %)', v_student_id, v_borrow_id_to_renew, v_book_id_of_borrow;

    -- 获取系统参数
    SELECT setting_value::int INTO v_max_renew_times FROM system_settings WHERE setting_key = 'max_renew_times';
    SELECT setting_value::int INTO v_borrow_duration_days FROM system_settings WHERE setting_key = 'borrow_duration_days';

    -- 检查条件：
    -- 1. 状态为 'borrowed' (不能是 'overdue' 或 'lost')
    IF v_current_status != 'borrowed' THEN
        RAISE NOTICE '-- 续借失败: 图书状态为 %，不是 "borrowed"。', v_current_status;
        RETURN;
    END IF;

    -- 2. 续借次数未达上限
    IF v_current_renew_times >= v_max_renew_times THEN
        RAISE NOTICE '-- 续借失败: 已达到最大续借次数 (%)。', v_max_renew_times;
        RETURN;
    END IF;

    -- 3. 该书没有其他人预约
    SELECT EXISTS (SELECT 1 FROM reservations WHERE book_id = v_book_id_of_borrow AND status = 'waiting')
    INTO v_is_reserved;
    IF v_is_reserved THEN
        RAISE NOTICE '-- 续借失败: 该图书已被其他用户预约。';
        RETURN;
    END IF;

    -- 执行续借
    UPDATE borrow_records
    SET due_date = v_current_due_date + (v_borrow_duration_days || ' days')::interval, -- 从原应还日期开始计算
        renew_times = renew_times + 1
    WHERE borrow_id = v_borrow_id_to_renew;

    RAISE NOTICE '-- 续借成功! borrow_id: %, 新的应还日期: %, 当前续借次数: %',
                 v_borrow_id_to_renew,
                 (SELECT due_date FROM borrow_records WHERE borrow_id = v_borrow_id_to_renew),
                 (SELECT renew_times FROM borrow_records WHERE borrow_id = v_borrow_id_to_renew);

EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RAISE NOTICE '-- 未找到相关借阅记录或系统参数。';
    WHEN OTHERS THEN
        RAISE NOTICE '续借操作发生错误: %', SQLERRM;
END $$;

-- (6). 查看和缴纳罚款
RAISE NOTICE '---------- (6) 查看和缴纳罚款 ----------';
-- 假设学生王五 (S2022003, student_id=3) 有未缴罚款
DO $$
DECLARE
    v_student_id_wangwu bigint;
    v_fine_id_to_pay bigint;
    v_amount_to_pay numeric;
BEGIN
    SELECT student_id INTO v_student_id_wangwu FROM students WHERE stu_no = 'S2022003';
    IF NOT FOUND THEN
        RAISE NOTICE '学生 S2022003 未找到。';
        RETURN;
    END IF;

    RAISE NOTICE '-- 查看学生王五 (ID: %) 的未缴罚款:';
    SELECT fine_id, amount, reason, status, issue_date
    FROM fines
    WHERE student_id = v_student_id_wangwu AND status = 'unpaid';

    -- 假设王五要缴纳 fine_id 为 (从上面查询结果中选取一个，例如第一个未缴罚款)
    SELECT fine_id, amount INTO v_fine_id_to_pay, v_amount_to_pay
    FROM fines
    WHERE student_id = v_student_id_wangwu AND status = 'unpaid'
    ORDER BY issue_date
    LIMIT 1;

    IF v_fine_id_to_pay IS NOT NULL THEN
        RAISE NOTICE '-- 模拟缴纳学生王五 (ID: %) 的罚款 fine_id: %, 金额: %', v_student_id_wangwu, v_fine_id_to_pay, v_amount_to_pay;
        UPDATE fines
        SET status = 'paid'
        WHERE fine_id = v_fine_id_to_pay;
        -- 触发器 trg_freeze_account 会在此 UPDATE 后执行，可能解冻账户

        RAISE NOTICE '-- 缴纳后，再次查看学生王五 (ID: %) 的未缴罚款:';
        SELECT fine_id, amount, reason, status, issue_date
        FROM fines
        WHERE student_id = v_student_id_wangwu AND status = 'unpaid';

        RAISE NOTICE '-- 查看学生王五 (ID: %) 的账户状态 (可能已因罚款缴纳而解冻):';
        SELECT stu_no, name, account_status FROM students WHERE student_id = v_student_id_wangwu;
    ELSE
        RAISE NOTICE '-- 学生王五 (ID: %) 没有未缴罚款可供缴纳。';
    END IF;
END $$;

-- (7). 对已借阅图书进行评分和评论
RAISE NOTICE '---------- (7) 对已借阅图书进行评分和评论 ----------';
-- 假设张三 (student_id=1) 要对他借阅过的《深入理解计算机系统》(book_id=1)进行评价
-- （假设他已经借过或者正在借阅）
DO $$
DECLARE
    v_student_id bigint := current_setting('app.current_student_id')::bigint;
    v_book_id_to_review bigint;
BEGIN
    SELECT book_id INTO v_book_id_to_review FROM books WHERE isbn = '9787111624927'; -- 深入理解计算机系统

    -- 检查是否已经评论过 (因为有 UNIQUE(book_id, student_id) 约束)
    IF EXISTS (SELECT 1 FROM reviews WHERE student_id = v_student_id AND book_id = v_book_id_to_review) THEN
        RAISE NOTICE '-- 学生ID % 已评价过图书ID %。';
        UPDATE reviews
        SET rating = 5, content = '更新评价：太经典了，常看常新！', review_time = now()
        WHERE student_id = v_student_id AND book_id = v_book_id_to_review;
        RAISE NOTICE '-- 已更新学生ID % 对图书ID % 的评价。';
    ELSE
        -- 应用层面通常会检查该学生是否实际借阅过这本书，这里我们直接插入
        INSERT INTO reviews (book_id, student_id, rating, content, review_time)
        VALUES (v_book_id_to_review, v_student_id, 5, '这本书写得太好了，深入浅出，对我帮助很大！', now());
        RAISE NOTICE '-- 学生ID % 已成功评价图书ID %。';
    END IF;

    RAISE NOTICE '-- 查看图书ID % 的所有评价:';
    SELECT s.name as student_name, r.rating, r.content, r.review_time
    FROM reviews r
    JOIN students s ON r.student_id = s.student_id
    WHERE r.book_id = v_book_id_to_review
    ORDER BY r.review_time DESC;
END $$;

-- (8). 查看图书推荐（如基于热门被借阅图书）
RAISE NOTICE '---------- (8) 查看图书推荐（热门图书） ----------';
RAISE NOTICE '-- 查看当前热门图书 (基于 v_hot_books 视图):';
SELECT b.isbn, b.title, b.authors, vhb.borrow_cnt
FROM v_hot_books vhb
JOIN books b ON vhb.book_id = b.book_id
ORDER BY vhb.borrow_cnt DESC;

-- 另一种推荐思路：基于用户所在院系的热门图书
RAISE NOTICE '-- 查看学生张三所在院系的热门图书 (示例):';
WITH student_department AS (
    SELECT department FROM students WHERE student_id = current_setting('app.current_student_id')::bigint
),
department_borrows AS (
    SELECT
        br.book_id,
        COUNT(*) as dept_borrow_count
    FROM borrow_records br
    JOIN students s ON br.student_id = s.student_id
    WHERE s.department = (SELECT department FROM student_department)
    GROUP BY br.book_id
)
SELECT b.title, b.authors, db.dept_borrow_count
FROM department_borrows db
JOIN books b ON db.book_id = b.book_id
ORDER BY db.dept_borrow_count DESC
LIMIT 10;

RAISE NOTICE '---------- 学生功能SQL示例演示完毕 ----------';