CREATE DATABASE IF NOT EXISTS mzh_library
  DEFAULT CHARACTER SET utf8mb4
  DEFAULT COLLATE utf8mb4_unicode_ci;

USE mzh_library;

CREATE TABLE IF NOT EXISTS roles (
  code VARCHAR(32) PRIMARY KEY,
  name VARCHAR(64) NOT NULL,
  description VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS permissions (
  code VARCHAR(64) PRIMARY KEY,
  name VARCHAR(96) NOT NULL,
  description VARCHAR(255) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS role_permissions (
  role_code VARCHAR(32) NOT NULL,
  permission_code VARCHAR(64) NOT NULL,
  PRIMARY KEY (role_code, permission_code),
  CONSTRAINT fk_role_permissions_role
    FOREIGN KEY (role_code) REFERENCES roles (code),
  CONSTRAINT fk_role_permissions_permission
    FOREIGN KEY (permission_code) REFERENCES permissions (code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS users (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(64) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  display_name VARCHAR(100) NOT NULL,
  role_code VARCHAR(32) NOT NULL,
  active TINYINT(1) NOT NULL DEFAULT 1,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_users_username (username),
  KEY idx_users_role_code (role_code),
  CONSTRAINT fk_users_role
    FOREIGN KEY (role_code) REFERENCES roles (code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS system_logs (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  operator_id BIGINT NULL,
  operator_role VARCHAR(32) NULL,
  operation_type VARCHAR(64) NOT NULL,
  target_table VARCHAR(64) NULL,
  target_id VARCHAR(64) NULL,
  result_status VARCHAR(32) NOT NULL,
  message VARCHAR(500) NULL,
  request_ip VARCHAR(64) NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY idx_system_logs_operator_id (operator_id),
  KEY idx_system_logs_operation_type (operation_type),
  KEY idx_system_logs_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS readers (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  reader_identifier VARCHAR(64) NOT NULL,
  user_id BIGINT NULL,
  full_name VARCHAR(100) NOT NULL,
  phone VARCHAR(32) NULL,
  email VARCHAR(120) NULL,
  status VARCHAR(32) NOT NULL DEFAULT 'active',
  max_borrow_count INT NOT NULL DEFAULT 5,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_readers_identifier (reader_identifier),
  UNIQUE KEY uk_readers_user_id (user_id),
  KEY idx_readers_full_name (full_name),
  KEY idx_readers_phone (phone),
  KEY idx_readers_email (email),
  KEY idx_readers_status (status),
  CONSTRAINT fk_readers_user
    FOREIGN KEY (user_id) REFERENCES users (id),
  CONSTRAINT chk_readers_status
    CHECK (status IN ('active', 'suspended', 'inactive')),
  CONSTRAINT chk_readers_max_borrow_count
    CHECK (max_borrow_count BETWEEN 1 AND 50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS book_categories (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(96) NOT NULL,
  description VARCHAR(255) NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_book_categories_name (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS books (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  book_identifier VARCHAR(64) NOT NULL,
  title VARCHAR(200) NOT NULL,
  author VARCHAR(120) NOT NULL,
  category_id BIGINT NOT NULL,
  total_copies INT NOT NULL DEFAULT 0,
  available_copies INT NOT NULL DEFAULT 0,
  status VARCHAR(32) NOT NULL DEFAULT 'available',
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_books_identifier (book_identifier),
  KEY idx_books_title (title),
  KEY idx_books_author (author),
  KEY idx_books_category_id (category_id),
  KEY idx_books_status (status),
  CONSTRAINT fk_books_category
    FOREIGN KEY (category_id) REFERENCES book_categories (id),
  CONSTRAINT chk_books_total_copies
    CHECK (total_copies >= 0),
  CONSTRAINT chk_books_available_copies
    CHECK (available_copies >= 0 AND available_copies <= total_copies),
  CONSTRAINT chk_books_status
    CHECK (status IN ('available', 'unavailable', 'archived'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS borrow_records (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  reader_id BIGINT NOT NULL,
  book_id BIGINT NOT NULL,
  borrowed_at DATETIME NOT NULL,
  due_at DATETIME NOT NULL,
  returned_at DATETIME NULL,
  renewal_count INT NOT NULL DEFAULT 0,
  status VARCHAR(32) NOT NULL DEFAULT 'active',
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  KEY idx_borrow_records_reader_id (reader_id),
  KEY idx_borrow_records_book_id (book_id),
  KEY idx_borrow_records_status (status),
  KEY idx_borrow_records_due_at (due_at),
  CONSTRAINT fk_borrow_records_reader
    FOREIGN KEY (reader_id) REFERENCES readers (id),
  CONSTRAINT fk_borrow_records_book
    FOREIGN KEY (book_id) REFERENCES books (id),
  CONSTRAINT chk_borrow_records_renewal_count
    CHECK (renewal_count >= 0),
  CONSTRAINT chk_borrow_records_status
    CHECK (status IN ('active', 'returned'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO roles (code, name, description) VALUES
  ('administrator', 'Administrator', 'Full system administration role'),
  ('librarian', 'Librarian', 'Library operation and borrowing management role'),
  ('reader', 'Reader', 'Reader self-service role')
ON DUPLICATE KEY UPDATE
  name = VALUES(name),
  description = VALUES(description);

INSERT INTO permissions (code, name, description) VALUES
  ('manage_users', 'Manage users', 'Create and maintain administrator, librarian, and reader accounts'),
  ('manage_books', 'Manage books', 'Create, update, delete, and categorize books'),
  ('manage_readers', 'Manage readers', 'Maintain reader profiles and eligibility'),
  ('manage_borrowing', 'Manage borrowing', 'Borrow, return, renew, and process overdue records'),
  ('view_reports', 'View reports', 'View search, ranking, inventory, and overdue reports'),
  ('view_system_logs', 'View system logs', 'View system maintenance and exception logs'),
  ('view_catalog', 'View catalog', 'Search and view library books'),
  ('borrow_books', 'Borrow books', 'Borrow and renew own books')
ON DUPLICATE KEY UPDATE
  name = VALUES(name),
  description = VALUES(description);

INSERT IGNORE INTO role_permissions (role_code, permission_code) VALUES
  ('administrator', 'manage_users'),
  ('administrator', 'manage_books'),
  ('administrator', 'manage_readers'),
  ('administrator', 'manage_borrowing'),
  ('administrator', 'view_reports'),
  ('administrator', 'view_system_logs'),
  ('administrator', 'view_catalog'),
  ('librarian', 'manage_books'),
  ('librarian', 'manage_readers'),
  ('librarian', 'manage_borrowing'),
  ('librarian', 'view_reports'),
  ('librarian', 'view_catalog'),
  ('reader', 'view_catalog'),
  ('reader', 'borrow_books');

-- Demo accounts for local scaffold verification only. Change or remove them
-- before using a non-local database.
INSERT IGNORE INTO users (username, password_hash, display_name, role_code, active) VALUES
  ('admin', 'pbkdf2_sha256$60000$bXpoLWFkbWluLWRlbW8tc2FsdA==$RwBCvhf3Wsc0jemnHlir4mdNZF4ZhHjrfHx/b1Bera0=', 'System Administrator', 'administrator', 1),
  ('librarian', 'pbkdf2_sha256$60000$bXpoLWxpYnJhcmlhbi1kZW1vLXNhbHQ=$StIdJGDRIiF4aCr+qKuwvob5sL3+6j1caF2sQNqFi78=', 'Library Staff', 'librarian', 1),
  ('reader', 'pbkdf2_sha256$60000$bXpoLXJlYWRlci1kZW1vLXNhbHQ=$iaiZPGhaIQ+2R2o9UQRj6wsrmYSJ4efqS3jCzM/XU7g=', 'Demo Reader', 'reader', 1);

INSERT IGNORE INTO readers (reader_identifier, user_id, full_name, phone, email, status, max_borrow_count) VALUES
  ('RD-0001', (SELECT id FROM users WHERE username = 'reader'), 'Demo Reader', '13800000000',
    'reader@example.com', 'active', 5),
  ('RD-0002', NULL, 'Suspended Reader', '13900000000', 'suspended.reader@example.com', 'suspended', 3);

INSERT INTO book_categories (name, description) VALUES
  ('Computer Science', 'Programming, software engineering, and systems books'),
  ('Literature', 'Classic and modern literature'),
  ('History', 'World and regional history'),
  ('Science', 'Natural science and popular science')
ON DUPLICATE KEY UPDATE
  description = VALUES(description);

INSERT IGNORE INTO books (book_identifier, title, author, category_id, total_copies, available_copies, status) VALUES
  ('BK-0001', 'Effective Java', 'Joshua Bloch',
    (SELECT id FROM book_categories WHERE name = 'Computer Science'), 5, 4, 'available'),
  ('BK-0002', 'Clean Code', 'Robert C. Martin',
    (SELECT id FROM book_categories WHERE name = 'Computer Science'), 4, 2, 'available'),
  ('BK-0003', 'Pride and Prejudice', 'Jane Austen',
    (SELECT id FROM book_categories WHERE name = 'Literature'), 3, 3, 'available'),
  ('BK-0004', 'A Brief History of Time', 'Stephen Hawking',
    (SELECT id FROM book_categories WHERE name = 'Science'), 2, 1, 'available');
