-- ===========================================
-- 班级操行分管理系统 - 数据库初始化脚本
-- ===========================================
-- 开发者: Canglan
-- 联系方式: admin@sea-studio.top
-- 版权归属: Sea Network Technology Studio
-- 许可证: MIT License
-- 版权所有: Copyright (c) 2024 Sea Network Technology Studio
-- ===========================================
-- 数据库: classmanagerdb
-- 字符集: utf8mb4
-- ===========================================

-- 创建数据库（如果不存在）
CREATE DATABASE IF NOT EXISTS `classmanagerdb` 
CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;

USE `classmanagerdb`;

-- ===========================================
-- 1. 班级表
-- ===========================================
DROP TABLE IF EXISTS `classes`;
CREATE TABLE `classes` (
    `class_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '班级ID',
    `class_name` VARCHAR(50) NOT NULL COMMENT '班级名称',
    `grade` VARCHAR(20) DEFAULT NULL COMMENT '年级',
    `academic_year` VARCHAR(20) DEFAULT NULL COMMENT '学年',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    INDEX `idx_class_name` (`class_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='班级表';

-- ===========================================
-- 2. 科目表（支持动态增删）
-- ===========================================
DROP TABLE IF EXISTS `subjects`;
CREATE TABLE `subjects` (
    `subject_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '科目ID',
    `subject_name` VARCHAR(50) NOT NULL COMMENT '科目名称',
    `subject_code` VARCHAR(20) DEFAULT NULL COMMENT '科目代码',
    `is_active` TINYINT DEFAULT 1 COMMENT '是否启用（0禁用/1启用）',
    `sort_order` INT DEFAULT 0 COMMENT '排序序号',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    INDEX `idx_active` (`is_active`),
    UNIQUE KEY `uk_subject_name` (`subject_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='科目表';

-- ===========================================
-- 3. 学生表
-- ===========================================
DROP TABLE IF EXISTS `students`;
CREATE TABLE `students` (
    `student_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '学生ID',
    `student_no` VARCHAR(20) NOT NULL COMMENT '学号',
    `name` VARCHAR(50) NOT NULL COMMENT '学生姓名',
    `class_id` INT NOT NULL COMMENT '班级ID',
    `total_points` INT DEFAULT 100 COMMENT '操行分总分',
    `parent_phone` VARCHAR(20) DEFAULT NULL COMMENT '家长手机号',
    `status` TINYINT DEFAULT 1 COMMENT '状态（0离校/1在校）',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT,
    UNIQUE KEY `uk_student_no` (`student_no`),
    INDEX `idx_class_id` (`class_id`),
    INDEX `idx_parent_phone` (`parent_phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学生表';

-- ===========================================
-- 4. 用户表（统一账号）
-- ===========================================
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
    `user_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
    `username` VARCHAR(50) NOT NULL COMMENT '登录账号',
    `password_hash` VARCHAR(64) NOT NULL COMMENT '密码哈希（SHA1+MD5）',
    `real_name` VARCHAR(50) NOT NULL COMMENT '真实姓名',
    `user_type` ENUM('student', 'parent', 'admin') NOT NULL COMMENT '用户类型',
    `student_id` INT DEFAULT NULL COMMENT '关联学生ID（学生/家长）',
    `status` TINYINT DEFAULT 1 COMMENT '状态（0禁用/1启用）',
    `need_change_password` TINYINT DEFAULT 1 COMMENT '是否需要修改密码（1需要/0不需要）',
    `last_login_time` DATETIME DEFAULT NULL COMMENT '最后登录时间',
    `last_login_ip` VARCHAR(45) DEFAULT NULL COMMENT '最后登录IP',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    UNIQUE KEY `uk_username` (`username`),
    INDEX `idx_user_type` (`user_type`),
    INDEX `idx_student_id` (`student_id`),
    FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';

-- ===========================================
-- 5. 管理员角色表
-- ===========================================
DROP TABLE IF EXISTS `admin_roles`;
CREATE TABLE `admin_roles` (
    `admin_role_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '管理员角色ID',
    `user_id` INT NOT NULL COMMENT '用户ID',
    `role_type` ENUM('班主任', '班长', '科代表', '考勤委员', '劳动委员') NOT NULL COMMENT '角色类型',
    `class_id` INT NOT NULL COMMENT '管理的班级ID',
    `subject_id` INT DEFAULT NULL COMMENT '关联科目ID（科代表专用）',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) ON DELETE CASCADE,
    FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE CASCADE,
    FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`) ON DELETE CASCADE,
    INDEX `idx_user_id` (`user_id`),
    INDEX `idx_role_type` (`role_type`),
    UNIQUE KEY `uk_user_class_subject` (`user_id`, `class_id`, `subject_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='管理员角色表';

-- ===========================================
-- 6. 操行分记录表
-- ===========================================
DROP TABLE IF EXISTS `conduct_records`;
CREATE TABLE `conduct_records` (
    `record_id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '记录ID',
    `student_id` INT NOT NULL COMMENT '学生ID',
    `points_change` INT NOT NULL COMMENT '分数变动（正数加分，负数扣分）',
    `reason` VARCHAR(255) NOT NULL COMMENT '变动原因',
    `recorder_id` INT NOT NULL COMMENT '操作人ID',
    `recorder_name` VARCHAR(50) DEFAULT NULL COMMENT '操作人姓名（冗余字段）',
    `related_type` ENUM('manual', 'homework', 'attendance') DEFAULT 'manual' COMMENT '关联类型',
    `related_id` INT DEFAULT NULL COMMENT '关联ID（作业ID/考勤ID）',
    `is_revoked` TINYINT DEFAULT 0 COMMENT '是否已撤销（0未撤销/1已撤销）',
    `revoked_by` INT DEFAULT NULL COMMENT '撤销人ID',
    `revoked_at` DATETIME DEFAULT NULL COMMENT '撤销时间',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE,
    FOREIGN KEY (`recorder_id`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT,
    FOREIGN KEY (`revoked_by`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT,
    INDEX `idx_student_id` (`student_id`),
    INDEX `idx_recorder_id` (`recorder_id`),
    INDEX `idx_created_at` (`created_at`),
    INDEX `idx_related` (`related_type`, `related_id`),
    INDEX `idx_is_revoked` (`is_revoked`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操行分记录表';

-- ===========================================
-- 7. 作业表
-- ===========================================
DROP TABLE IF EXISTS `assignments`;
CREATE TABLE `assignments` (
    `assignment_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '作业ID',
    `class_id` INT NOT NULL COMMENT '班级ID',
    `subject_id` INT NOT NULL COMMENT '科目ID',
    `title` VARCHAR(100) NOT NULL COMMENT '作业标题',
    `description` TEXT COMMENT '作业描述',
    `deadline` DATE NOT NULL COMMENT '截止日期',
    `created_by` INT NOT NULL COMMENT '发布人ID',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE CASCADE,
    FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`) ON DELETE RESTRICT,
    FOREIGN KEY (`created_by`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT,
    INDEX `idx_class_id` (`class_id`),
    INDEX `idx_deadline` (`deadline`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业表';

-- ===========================================
-- 8. 作业提交记录表
-- ===========================================
DROP TABLE IF EXISTS `homework_submissions`;
CREATE TABLE `homework_submissions` (
    `submission_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '提交记录ID',
    `assignment_id` INT NOT NULL COMMENT '作业ID',
    `student_id` INT NOT NULL COMMENT '学生ID',
    `status` ENUM('submitted', 'not_submitted', 'late') DEFAULT 'not_submitted' COMMENT '提交状态',
    `submit_time` DATETIME DEFAULT NULL COMMENT '提交时间',
    `comments` TEXT COMMENT '备注',
    `deduction_applied` TINYINT DEFAULT 0 COMMENT '是否已应用扣分',
    `deduction_record_id` BIGINT DEFAULT NULL COMMENT '关联的扣分记录ID',
    `updated_by` INT DEFAULT NULL COMMENT '最后更新人ID',
    `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    FOREIGN KEY (`assignment_id`) REFERENCES `assignments`(`assignment_id`) ON DELETE CASCADE,
    FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE,
    FOREIGN KEY (`updated_by`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT,
    FOREIGN KEY (`deduction_record_id`) REFERENCES `conduct_records`(`record_id`) ON DELETE SET NULL,
    INDEX `idx_assignment_id` (`assignment_id`),
    INDEX `idx_student_id` (`student_id`),
    INDEX `idx_status` (`status`),
    UNIQUE KEY `uk_assignment_student` (`assignment_id`, `student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业提交记录表';

-- ===========================================
-- 9. 考勤记录表
-- ===========================================
DROP TABLE IF EXISTS `attendance_records`;
CREATE TABLE `attendance_records` (
    `attendance_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '考勤记录ID',
    `student_id` INT NOT NULL COMMENT '学生ID',
    `date` DATE NOT NULL COMMENT '考勤日期',
    `status` ENUM('present', 'absent', 'late', 'leave') DEFAULT 'present' COMMENT '考勤状态',
    `reason` VARCHAR(255) DEFAULT NULL COMMENT '原因',
    `recorder_id` INT NOT NULL COMMENT '记录人ID',
    `deduction_applied` TINYINT DEFAULT 0 COMMENT '是否已应用扣分',
    `deduction_record_id` BIGINT DEFAULT NULL COMMENT '关联的扣分记录ID',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE,
    FOREIGN KEY (`recorder_id`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT,
    FOREIGN KEY (`deduction_record_id`) REFERENCES `conduct_records`(`record_id`) ON DELETE SET NULL,
    INDEX `idx_student_id` (`student_id`),
    INDEX `idx_date` (`date`),
    INDEX `idx_status` (`status`),
    UNIQUE KEY `uk_student_date` (`student_id`, `date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='考勤记录表';

-- ===========================================
-- 10. 操作日志表
-- ===========================================
DROP TABLE IF EXISTS `operation_logs`;
CREATE TABLE `operation_logs` (
    `log_id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '日志ID',
    `operator_id` INT NOT NULL COMMENT '操作人ID',
    `operator_name` VARCHAR(50) DEFAULT NULL COMMENT '操作人姓名',
    `operator_role` VARCHAR(50) DEFAULT NULL COMMENT '操作人角色',
    `operation_type` VARCHAR(50) NOT NULL COMMENT '操作类型',
    `target_type` VARCHAR(50) DEFAULT NULL COMMENT '目标类型',
    `target_id` INT DEFAULT NULL COMMENT '目标ID',
    `details` TEXT COMMENT '详细信息',
    `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'IP地址',
    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    INDEX `idx_operator_id` (`operator_id`),
    INDEX `idx_operation_type` (`operation_type`),
    INDEX `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志表';

-- ===========================================
-- 11. 登录日志表
-- ===========================================
DROP TABLE IF EXISTS `login_logs`;
CREATE TABLE `login_logs` (
    `log_id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '日志ID',
    `username` VARCHAR(50) NOT NULL COMMENT '登录账号',
    `login_result` TINYINT NOT NULL COMMENT '登录结果（0失败/1成功）',
    `fail_reason` VARCHAR(100) DEFAULT NULL COMMENT '失败原因',
    `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'IP地址',
    `user_agent` VARCHAR(255) DEFAULT NULL COMMENT '用户代理',
    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    INDEX `idx_username` (`username`),
    INDEX `idx_created_at` (`created_at`),
    INDEX `idx_login_result` (`login_result`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录日志表';

-- ===========================================
-- 创建存储过程：撤销扣分记录
-- ===========================================
DROP PROCEDURE IF EXISTS `revoke_conduct_record`;
DELIMITER //

CREATE PROCEDURE `revoke_conduct_record`(
    IN p_record_id BIGINT,
    IN p_revoker_id INT
)
BEGIN
    DECLARE v_student_id INT;
    DECLARE v_points_change INT;
    DECLARE v_is_revoked TINYINT;
    
    SELECT `student_id`, `points_change`, `is_revoked` 
    INTO v_student_id, v_points_change, v_is_revoked
    FROM `conduct_records` 
    WHERE `record_id` = p_record_id;
    
    IF v_is_revoked = 1 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '该记录已被撤销';
    END IF;
    
    UPDATE `conduct_records` 
    SET `is_revoked` = 1, 
        `revoked_by` = p_revoker_id, 
        `revoked_at` = NOW()
    WHERE `record_id` = p_record_id;
    
    UPDATE `students` 
    SET `total_points` = `total_points` - v_points_change
    WHERE `student_id` = v_student_id;
    
END //

DELIMITER ;

-- ===========================================
-- 创建触发器：更新学生总分
-- ===========================================
DROP TRIGGER IF EXISTS `update_student_points_on_insert`;
DELIMITER //

CREATE TRIGGER `update_student_points_on_insert`
AFTER INSERT ON `conduct_records`
FOR EACH ROW
BEGIN
    IF NEW.is_revoked = 0 THEN
        UPDATE `students` 
        SET `total_points` = `total_points` + NEW.points_change
        WHERE `student_id` = NEW.student_id;
    END IF;
END //

DELIMITER ;

-- ===========================================
-- 创建视图：学生操行分排行榜
-- ===========================================
DROP VIEW IF EXISTS `v_student_ranking`;
CREATE VIEW `v_student_ranking` AS
SELECT 
    s.student_id,
    s.student_no,
    s.name,
    c.class_name,
    s.total_points,
    RANK() OVER (PARTITION BY s.class_id ORDER BY s.total_points DESC) as rank_in_class
FROM `students` s
JOIN `classes` c ON s.class_id = c.class_id
WHERE s.status = 1;

-- ===========================================
-- 创建视图：今日考勤汇总
-- ===========================================
DROP VIEW IF EXISTS `v_today_attendance`;
CREATE VIEW `v_today_attendance` AS
SELECT 
    c.class_name,
    COUNT(CASE WHEN a.status = 'present' THEN 1 END) as present_count,
    COUNT(CASE WHEN a.status = 'absent' THEN 1 END) as absent_count,
    COUNT(CASE WHEN a.status = 'late' THEN 1 END) as late_count,
    COUNT(CASE WHEN a.status = 'leave' THEN 1 END) as leave_count,
    COUNT(*) as total_count
FROM `attendance_records` a
JOIN `students` s ON a.student_id = s.student_id
JOIN `classes` c ON s.class_id = c.class_id
WHERE a.date = CURDATE()
GROUP BY c.class_id;