CREATE TABLE IF NOT EXISTS sys_user (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username VARCHAR(64) NOT NULL UNIQUE,
    password_hash VARCHAR(256) NOT NULL,
    real_name VARCHAR(64) NOT NULL,
    email VARCHAR(128),
    position VARCHAR(128),
    department_id INTEGER,
    superior_id INTEGER,
    role VARCHAR(20) NOT NULL DEFAULT 'EMPLOYEE',
    scopes TEXT DEFAULT '[]',
    status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
    disabled_at TEXT,
    left_at TEXT,
    deleted INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS sys_department (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(128) NOT NULL,
    parent_id INTEGER DEFAULT 0,
    leader_id INTEGER,
    sort_order INTEGER DEFAULT 0,
    deleted INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS assessment_period (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(128) NOT NULL,
    period_type VARCHAR(20) NOT NULL DEFAULT 'MONTHLY',
    start_date TEXT NOT NULL,
    end_date TEXT NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'DRAFT',
    created_by INTEGER,
    deleted INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS okr_objective (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    period_id INTEGER NOT NULL,
    user_id INTEGER,
    dept_id INTEGER,
    title VARCHAR(256) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'DRAFT',
    version INTEGER DEFAULT 1,
    aligned_objective_ids TEXT,
    snapshot_json TEXT,
    reviewed_by INTEGER,
    reviewed_at TEXT,
    level VARCHAR(16) NOT NULL DEFAULT 'INDIVIDUAL',
    parent_objective_id INTEGER,
    sort_order INTEGER DEFAULT 0,
    progress REAL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS kr_key_result (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    objective_id INTEGER NOT NULL,
    title VARCHAR(256) NOT NULL,
    target_value REAL DEFAULT 100,
    current_value REAL DEFAULT 0,
    status VARCHAR(20) NOT NULL DEFAULT 'NOT_STARTED',
    weight INTEGER DEFAULT 100,
    assigned_to INTEGER,
    source_kr_id INTEGER,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS kr_progress_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    kr_id INTEGER NOT NULL,
    old_value REAL,
    new_value REAL,
    old_status VARCHAR(20),
    new_status VARCHAR(20),
    remark VARCHAR(512),
    updated_by INTEGER,
    created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS kpi_template (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(128) NOT NULL,
    category VARCHAR(64),
    items_json TEXT,
    created_by INTEGER,
    deleted INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS kpi_config (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    period_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    items_json TEXT,
    version INTEGER DEFAULT 1,
    snapshot_json TEXT,
    locked_at TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS performance_score (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    period_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    evaluator_id INTEGER NOT NULL,
    okr_score REAL DEFAULT 0,
    kpi_score REAL DEFAULT 0,
    bonus REAL DEFAULT 0,
    penalty REAL DEFAULT 0,
    total REAL DEFAULT 0,
    grade VARCHAR(2),
    type VARCHAR(20) NOT NULL,
    status VARCHAR(32),
    comments_json TEXT,
    published_at TEXT,
    confirmed_at TEXT,
    deleted INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS performance_feedback (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    period_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    superior_id INTEGER NOT NULL,
    interview_notes TEXT,
    highlights TEXT,
    issues TEXT,
    improvements TEXT,
    employee_feedback TEXT,
    status VARCHAR(32),
    closed_at TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS operation_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    operator_id INTEGER,
    action VARCHAR(64) NOT NULL,
    entity_type VARCHAR(64) NOT NULL,
    entity_id INTEGER,
    old_data_json TEXT,
    new_data_json TEXT,
    ip VARCHAR(64),
    created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS audit_correction (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    performance_id INTEGER NOT NULL,
    correction_type VARCHAR(32) NOT NULL,
    old_values_json TEXT NOT NULL,
    new_values_json TEXT NOT NULL,
    reason TEXT NOT NULL,
    operated_by INTEGER NOT NULL,
    created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS period_participant (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    period_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
    reason TEXT,
    operated_by INTEGER,
    exempted_at TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE UNIQUE INDEX IF NOT EXISTS uk_period_participant ON period_participant(period_id, user_id);

CREATE TABLE IF NOT EXISTS score_appeal (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    period_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    score_id INTEGER NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'OPEN',
    reason TEXT NOT NULL,
    reply TEXT,
    submitted_at TEXT,
    resolved_by INTEGER,
    resolved_at TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS assessment_dimension (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(64) NOT NULL,
    max_score INTEGER NOT NULL DEFAULT 10,
    sort_order INTEGER DEFAULT 0,
    deleted INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS notification (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    type VARCHAR(32) NOT NULL,
    title VARCHAR(256) NOT NULL,
    content TEXT,
    ref_type VARCHAR(32),
    ref_id INTEGER,
    is_read INTEGER DEFAULT 0,
    read_at TEXT,
    created_at TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_notification_user ON notification(user_id, is_read, created_at);

CREATE TABLE IF NOT EXISTS schema_migration (
    version INTEGER PRIMARY KEY,
    description TEXT NOT NULL,
    applied_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS performance_score_item (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    score_id INTEGER NOT NULL,
    item_type VARCHAR(20) NOT NULL,
    reference_id INTEGER,
    name VARCHAR(256) NOT NULL,
    max_score REAL,
    score REAL NOT NULL DEFAULT 0,
    description TEXT,
    sort_order INTEGER DEFAULT 0,
    snapshot_json TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_score_item_score ON performance_score_item(score_id, sort_order);
