-- ====================================
-- HR Portal Database Schema
-- ====================================
-- 創建時間: 2026-02-08
-- 資料庫: PostgreSQL 16
-- ====================================

-- 設定時區
SET timezone = 'Asia/Taipei';

-- ====================================
-- 1. 事業部表 (Business Units)
-- ====================================
CREATE TABLE IF NOT EXISTS business_units (
    id SERIAL PRIMARY KEY,
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    name_en VARCHAR(100),
    description TEXT,
    manager_id INTEGER,  -- 將在建立 employees 表後設定外鍵
    email_domain VARCHAR(50),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 初始資料
INSERT INTO business_units (code, name, name_en, email_domain, description) VALUES
('wind-energy', '玄鐵風能授權服務事業部', 'Wind Energy Licensing', 'ease.taipei', '風力發電技術授權與風場評估服務'),
('carbon-credit', '國際碳權申請服務事業部', 'Carbon Credit Services', 'ease.taipei', '碳權申請、碳盤查與碳交易媒合服務'),
('smart-rd', '智能研發服務事業部', 'Smart R&D Services', 'lab.taipei', 'AI/ML、IoT 與能源管理系統研發'),
('management', '管理部門', 'Management', 'porscheworld.tw', '人資、財務、行政、資訊等管理部門')
ON CONFLICT (code) DO NOTHING;

-- ====================================
-- 2. 部門表 (Divisions)
-- ====================================
CREATE TABLE IF NOT EXISTS divisions (
    id SERIAL PRIMARY KEY,
    business_unit_id INTEGER REFERENCES business_units(id) ON DELETE CASCADE,
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    name_en VARCHAR(100),
    manager_id INTEGER,  -- 將在建立 employees 表後設定外鍵
    email VARCHAR(100),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 初始資料 - 玄鐵風能授權服務
INSERT INTO divisions (business_unit_id, code, name, name_en, email) VALUES
(1, 'wind-licensing', '技術授權部', 'Technical Licensing', 'wind-licensing@ease.taipei'),
(1, 'wind-assessment', '風場評估部', 'Wind Assessment', 'wind-assessment@ease.taipei'),
(1, 'wind-service', '客戶服務部', 'Customer Service', 'wind-service@ease.taipei')
ON CONFLICT (code) DO NOTHING;

-- 國際碳權申請服務
INSERT INTO divisions (business_unit_id, code, name, name_en, email) VALUES
(2, 'carbon-apply', '碳權申請部', 'Carbon Application', 'carbon-apply@ease.taipei'),
(2, 'carbon-audit', '碳盤查部', 'Carbon Audit', 'carbon-audit@ease.taipei'),
(2, 'carbon-trade', '碳交易部', 'Carbon Trading', 'carbon-trade@ease.taipei')
ON CONFLICT (code) DO NOTHING;

-- 智能研發服務
INSERT INTO divisions (business_unit_id, code, name, name_en, email) VALUES
(3, 'software-dev', '軟體研發部', 'Software Development', 'software@lab.taipei'),
(3, 'hardware-dev', '硬體研發部', 'Hardware Development', 'hardware@lab.taipei'),
(3, 'product-mgmt', '產品管理部', 'Product Management', 'product@lab.taipei')
ON CONFLICT (code) DO NOTHING;

-- 管理部門
INSERT INTO divisions (business_unit_id, code, name, name_en, email) VALUES
(4, 'hr', '人力資源部', 'Human Resources', 'hr@porscheworld.tw'),
(4, 'finance', '財務部', 'Finance', 'finance@porscheworld.tw'),
(4, 'admin', '行政部', 'Administration', 'admin@porscheworld.tw'),
(4, 'it', '資訊部', 'Information Technology', 'it@porscheworld.tw')
ON CONFLICT (code) DO NOTHING;

-- ====================================
-- 3. 員工表 (Employees)
-- ====================================
CREATE TABLE IF NOT EXISTS employees (
    id SERIAL PRIMARY KEY,
    keycloak_user_id UUID UNIQUE,
    employee_id VARCHAR(20) UNIQUE NOT NULL,
    username VARCHAR(100) UNIQUE NOT NULL,

    -- 基本資料
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    chinese_name VARCHAR(50),
    email VARCHAR(255) UNIQUE NOT NULL,
    phone VARCHAR(20),
    mobile VARCHAR(20),

    -- 任職資訊
    business_unit_id INTEGER REFERENCES business_units(id),
    division_id INTEGER REFERENCES divisions(id),
    team VARCHAR(100),
    position VARCHAR(100),
    job_title VARCHAR(100),
    job_level VARCHAR(20),  -- C-Level, VP, Director, Manager, Senior, Staff, etc.
    employment_type VARCHAR(20) DEFAULT 'full-time',  -- full-time, part-time, contractor, intern

    -- 日期
    hire_date DATE,
    termination_date DATE,

    -- 狀態
    status VARCHAR(20) DEFAULT 'active',  -- active, inactive, suspended, terminated

    -- 審計
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(100),
    updated_by VARCHAR(100)
);

-- 索引
CREATE INDEX idx_employees_keycloak_id ON employees(keycloak_user_id);
CREATE INDEX idx_employees_status ON employees(status);
CREATE INDEX idx_employees_business_unit ON employees(business_unit_id);
CREATE INDEX idx_employees_division ON employees(division_id);
CREATE INDEX idx_employees_email ON employees(email);

-- 新增外鍵到 business_units 和 divisions
ALTER TABLE business_units ADD CONSTRAINT fk_business_unit_manager
    FOREIGN KEY (manager_id) REFERENCES employees(id) ON DELETE SET NULL;

ALTER TABLE divisions ADD CONSTRAINT fk_division_manager
    FOREIGN KEY (manager_id) REFERENCES employees(id) ON DELETE SET NULL;

-- ====================================
-- 4. 郵件帳號表 (Email Accounts)
-- ====================================
CREATE TABLE IF NOT EXISTS email_accounts (
    id SERIAL PRIMARY KEY,
    employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE,
    email_address VARCHAR(255) UNIQUE NOT NULL,
    mailbox_quota_mb INTEGER DEFAULT 1024,
    mailbox_used_mb INTEGER DEFAULT 0,

    -- 郵件設定
    forward_to VARCHAR(255),
    auto_reply BOOLEAN DEFAULT FALSE,
    auto_reply_message TEXT,

    -- 狀態
    is_active BOOLEAN DEFAULT TRUE,

    -- 審計
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(100)
);

CREATE INDEX idx_email_accounts_employee ON email_accounts(employee_id);
CREATE INDEX idx_email_accounts_email ON email_accounts(email_address);

-- ====================================
-- 5. 網路硬碟表 (Network Drives)
-- ====================================
CREATE TABLE IF NOT EXISTS network_drives (
    id SERIAL PRIMARY KEY,
    employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE,

    -- 硬碟資訊
    drive_name VARCHAR(100) NOT NULL,
    drive_path VARCHAR(500) NOT NULL,
    quota_gb INTEGER DEFAULT 10,
    used_gb DECIMAL(10,2) DEFAULT 0,

    -- 存取設定
    webdav_url VARCHAR(500),
    smb_path VARCHAR(500),

    -- 權限
    can_share BOOLEAN DEFAULT FALSE,

    -- 狀態
    is_active BOOLEAN DEFAULT TRUE,

    -- 審計
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_network_drives_employee ON network_drives(employee_id);

-- ====================================
-- 6. 系統權限表 (System Permissions)
-- ====================================
CREATE TABLE IF NOT EXISTS system_permissions (
    id SERIAL PRIMARY KEY,
    employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE,
    system_name VARCHAR(100) NOT NULL,
    system_url VARCHAR(500),
    access_level VARCHAR(50),  -- admin, user, readonly

    -- 狀態
    is_active BOOLEAN DEFAULT TRUE,
    granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    granted_by VARCHAR(100),
    revoked_at TIMESTAMP,
    revoked_by VARCHAR(100),

    UNIQUE(employee_id, system_name)
);

CREATE INDEX idx_system_permissions_employee ON system_permissions(employee_id);
CREATE INDEX idx_system_permissions_system ON system_permissions(system_name);

-- ====================================
-- 7. 專案表 (Projects)
-- ====================================
CREATE TABLE IF NOT EXISTS projects (
    id SERIAL PRIMARY KEY,
    business_unit_id INTEGER REFERENCES business_units(id),

    project_code VARCHAR(50) UNIQUE NOT NULL,
    project_name VARCHAR(200) NOT NULL,
    description TEXT,
    client_name VARCHAR(200),

    -- 專案狀態
    status VARCHAR(20) DEFAULT 'planning',  -- planning, active, on-hold, completed, cancelled

    -- 專案經理
    project_manager_id INTEGER REFERENCES employees(id),

    -- 時間
    start_date DATE,
    end_date DATE,
    actual_end_date DATE,

    -- 預算
    budget_amount DECIMAL(15,2),
    budget_currency VARCHAR(10) DEFAULT 'TWD',

    -- 專案空間
    nas_path VARCHAR(500),
    git_repo VARCHAR(200),

    -- 審計
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(100)
);

CREATE INDEX idx_projects_business_unit ON projects(business_unit_id);
CREATE INDEX idx_projects_status ON projects(status);
CREATE INDEX idx_projects_manager ON projects(project_manager_id);

-- ====================================
-- 8. 專案成員表 (Project Members)
-- ====================================
CREATE TABLE IF NOT EXISTS project_members (
    id SERIAL PRIMARY KEY,
    project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
    employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE,

    role VARCHAR(50),  -- project-manager, developer, consultant, support
    allocation_percentage INTEGER DEFAULT 100,  -- 0-100

    joined_date DATE DEFAULT CURRENT_DATE,
    left_date DATE,

    UNIQUE(project_id, employee_id)
);

CREATE INDEX idx_project_members_project ON project_members(project_id);
CREATE INDEX idx_project_members_employee ON project_members(employee_id);

-- ====================================
-- 9. 審計日誌表 (Audit Logs)
-- ====================================
CREATE TABLE IF NOT EXISTS audit_logs (
    id SERIAL PRIMARY KEY,
    employee_id INTEGER REFERENCES employees(id),

    action VARCHAR(50) NOT NULL,  -- create, update, delete, login, logout
    resource_type VARCHAR(50),    -- employee, email, drive, project
    resource_id INTEGER,

    old_value JSONB,
    new_value JSONB,

    ip_address VARCHAR(50),
    user_agent TEXT,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_audit_logs_employee ON audit_logs(employee_id);
CREATE INDEX idx_audit_logs_action ON audit_logs(action);
CREATE INDEX idx_audit_logs_resource ON audit_logs(resource_type, resource_id);
CREATE INDEX idx_audit_logs_created_at ON audit_logs(created_at DESC);

-- ====================================
-- 10. 更新時間觸發器函數
-- ====================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 為需要的表新增觸發器
CREATE TRIGGER update_business_units_updated_at BEFORE UPDATE ON business_units
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_divisions_updated_at BEFORE UPDATE ON divisions
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_employees_updated_at BEFORE UPDATE ON employees
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_email_accounts_updated_at BEFORE UPDATE ON email_accounts
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_network_drives_updated_at BEFORE UPDATE ON network_drives
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_projects_updated_at BEFORE UPDATE ON projects
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ====================================
-- 11. 建立視圖 (Views)
-- ====================================

-- 員工完整資訊視圖
CREATE OR REPLACE VIEW v_employees_full AS
SELECT
    e.*,
    bu.name as business_unit_name,
    bu.name_en as business_unit_name_en,
    d.name as division_name,
    d.name_en as division_name_en
FROM employees e
LEFT JOIN business_units bu ON e.business_unit_id = bu.id
LEFT JOIN divisions d ON e.division_id = d.id;

-- 專案人力統計視圖
CREATE OR REPLACE VIEW v_project_stats AS
SELECT
    p.id,
    p.project_code,
    p.project_name,
    p.status,
    COUNT(pm.id) as member_count,
    SUM(pm.allocation_percentage) as total_allocation
FROM projects p
LEFT JOIN project_members pm ON p.id = pm.project_id AND pm.left_date IS NULL
GROUP BY p.id, p.project_code, p.project_name, p.status;

-- 部門人力統計視圖
CREATE OR REPLACE VIEW v_division_headcount AS
SELECT
    bu.name as business_unit_name,
    d.name as division_name,
    COUNT(e.id) as employee_count,
    COUNT(CASE WHEN e.status = 'active' THEN 1 END) as active_count
FROM divisions d
LEFT JOIN business_units bu ON d.business_unit_id = bu.id
LEFT JOIN employees e ON e.division_id = d.id
GROUP BY bu.name, d.name;

-- ====================================
-- 完成
-- ====================================
-- 授予權限 (依實際用戶名調整)
-- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO hr_user;
-- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO hr_user;

SELECT 'HR Portal Database Schema 初始化完成!' as message;
