-- ═══════════════════════════════════════════════════════════════════════════
-- NIS2 Agile - Schema Database Iniziale
-- Database: nis2_agile_db
-- Versione: 1.0.0
-- Data: 2026-02-17
-- ═══════════════════════════════════════════════════════════════════════════

CREATE DATABASE IF NOT EXISTS nis2_agile_db
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

USE nis2_agile_db;

-- ═══════════════════════════════════════════════════════════════════════════
-- CORE: Organizzazioni e Utenti
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE organizations (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    vat_number VARCHAR(20),
    fiscal_code VARCHAR(16),
    sector ENUM(
        'energy','transport','banking','health','water','digital_infra',
        'public_admin','manufacturing','postal','chemical','food',
        'waste','ict_services','digital_providers','space','research','other'
    ) NOT NULL DEFAULT 'other',
    entity_type ENUM('essential','important','not_applicable') DEFAULT 'not_applicable',
    employee_count INT,
    annual_turnover_eur DECIMAL(15,2),
    country VARCHAR(2) DEFAULT 'IT',
    city VARCHAR(100),
    address VARCHAR(255),
    website VARCHAR(255),
    contact_email VARCHAR(255),
    contact_phone VARCHAR(30),
    subscription_plan ENUM('free','professional','enterprise') DEFAULT 'free',
    is_active TINYINT(1) DEFAULT 1,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_sector (sector),
    INDEX idx_entity_type (entity_type),
    INDEX idx_subscription (subscription_plan)
) ENGINE=InnoDB;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(255) NOT NULL,
    phone VARCHAR(30),
    role ENUM(
        'super_admin','org_admin','compliance_manager',
        'board_member','auditor','employee','consultant'
    ) NOT NULL DEFAULT 'employee',
    preferred_language VARCHAR(5) DEFAULT 'it',
    is_active TINYINT(1) DEFAULT 1,
    email_verified_at DATETIME,
    last_login_at DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_email (email),
    INDEX idx_role (role),
    INDEX idx_active (is_active)
) ENGINE=InnoDB;

CREATE TABLE user_organizations (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    organization_id INT NOT NULL,
    role ENUM('org_admin','compliance_manager','board_member','auditor','employee') NOT NULL DEFAULT 'employee',
    is_primary TINYINT(1) DEFAULT 0,
    joined_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    UNIQUE KEY uk_user_org (user_id, organization_id),
    INDEX idx_user (user_id),
    INDEX idx_org (organization_id)
) ENGINE=InnoDB;

CREATE TABLE refresh_tokens (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    token VARCHAR(255) NOT NULL,
    expires_at DATETIME NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_token (token),
    INDEX idx_expires (expires_at)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- GAP ANALYSIS & ASSESSMENT
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE assessments (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    assessment_type ENUM('initial','periodic','post_incident') DEFAULT 'initial',
    status ENUM('draft','in_progress','completed') DEFAULT 'draft',
    overall_score DECIMAL(5,2),
    category_scores JSON,
    completed_by INT,
    completed_at DATETIME,
    ai_summary TEXT,
    ai_recommendations JSON,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (completed_by) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_status (status)
) ENGINE=InnoDB;

CREATE TABLE assessment_responses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    assessment_id INT NOT NULL,
    question_code VARCHAR(50) NOT NULL,
    nis2_article VARCHAR(20),
    iso27001_control VARCHAR(20),
    category VARCHAR(100),
    question_text TEXT NOT NULL,
    response_value ENUM('not_implemented','partial','implemented','not_applicable'),
    maturity_level TINYINT,
    evidence_description TEXT,
    notes TEXT,
    answered_by INT,
    answered_at DATETIME,
    FOREIGN KEY (assessment_id) REFERENCES assessments(id) ON DELETE CASCADE,
    FOREIGN KEY (answered_by) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_assessment (assessment_id),
    INDEX idx_category (category),
    UNIQUE KEY uk_assessment_question (assessment_id, question_code)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- RISK MANAGEMENT
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE risks (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    risk_code VARCHAR(20),
    title VARCHAR(255) NOT NULL,
    description TEXT,
    category ENUM('cyber','operational','compliance','supply_chain','physical','human') NOT NULL,
    threat_source VARCHAR(255),
    vulnerability VARCHAR(255),
    affected_assets JSON,
    likelihood TINYINT,
    impact TINYINT,
    inherent_risk_score TINYINT,
    treatment ENUM('mitigate','accept','transfer','avoid') DEFAULT 'mitigate',
    residual_likelihood TINYINT,
    residual_impact TINYINT,
    residual_risk_score TINYINT,
    status ENUM('identified','analyzing','treating','monitored','closed') DEFAULT 'identified',
    owner_user_id INT,
    review_date DATE,
    nis2_article VARCHAR(20),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (owner_user_id) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_status (status),
    INDEX idx_category (category),
    UNIQUE KEY uk_org_risk_code (organization_id, risk_code)
) ENGINE=InnoDB;

CREATE TABLE risk_treatments (
    id INT AUTO_INCREMENT PRIMARY KEY,
    risk_id INT NOT NULL,
    action_description TEXT NOT NULL,
    responsible_user_id INT,
    due_date DATE,
    status ENUM('planned','in_progress','completed','overdue') DEFAULT 'planned',
    completion_date DATE,
    notes TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (risk_id) REFERENCES risks(id) ON DELETE CASCADE,
    FOREIGN KEY (responsible_user_id) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_risk (risk_id),
    INDEX idx_status (status)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- INCIDENT MANAGEMENT (Art. 23)
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE incidents (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    incident_code VARCHAR(20),
    title VARCHAR(255) NOT NULL,
    description TEXT,
    classification ENUM(
        'cyber_attack','data_breach','system_failure',
        'human_error','natural_disaster','supply_chain','other'
    ) NOT NULL,
    severity ENUM('low','medium','high','critical') NOT NULL,
    is_significant TINYINT(1) DEFAULT 0,
    status ENUM(
        'detected','analyzing','containing','eradicating',
        'recovering','closed','post_mortem'
    ) DEFAULT 'detected',
    detected_at DATETIME NOT NULL,
    -- NIS2 Art.23 milestones
    early_warning_due DATETIME,
    early_warning_sent_at DATETIME,
    notification_due DATETIME,
    notification_sent_at DATETIME,
    final_report_due DATETIME,
    final_report_sent_at DATETIME,
    -- Impact
    affected_services TEXT,
    affected_users_count INT,
    cross_border_impact TINYINT(1) DEFAULT 0,
    malicious_action TINYINT(1) DEFAULT 0,
    -- Resolution
    root_cause TEXT,
    remediation_actions TEXT,
    lessons_learned TEXT,
    reported_by INT,
    assigned_to INT,
    closed_at DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (reported_by) REFERENCES users(id) ON DELETE SET NULL,
    FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_status (status),
    INDEX idx_severity (severity),
    UNIQUE KEY uk_org_incident_code (organization_id, incident_code)
) ENGINE=InnoDB;

CREATE TABLE incident_timeline (
    id INT AUTO_INCREMENT PRIMARY KEY,
    incident_id INT NOT NULL,
    event_type ENUM('detection','escalation','notification','action','update','resolution') NOT NULL,
    description TEXT NOT NULL,
    created_by INT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE,
    FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_incident (incident_id)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- POLICY & PROCEDURE MANAGEMENT
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE policies (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    category ENUM(
        'information_security','access_control','incident_response',
        'business_continuity','supply_chain','encryption','hr_security',
        'asset_management','network_security','vulnerability_management'
    ) NOT NULL,
    nis2_article VARCHAR(20),
    version VARCHAR(10) DEFAULT '1.0',
    status ENUM('draft','review','approved','published','archived') DEFAULT 'draft',
    content LONGTEXT,
    approved_by INT,
    approved_at DATETIME,
    next_review_date DATE,
    ai_generated TINYINT(1) DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (approved_by) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_status (status),
    INDEX idx_category (category)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- SUPPLY CHAIN SECURITY (Art. 21.2.d)
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE suppliers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    name VARCHAR(255) NOT NULL,
    vat_number VARCHAR(20),
    contact_email VARCHAR(255),
    contact_name VARCHAR(255),
    service_type VARCHAR(255),
    service_description TEXT,
    criticality ENUM('low','medium','high','critical') DEFAULT 'medium',
    risk_score TINYINT,
    last_assessment_date DATE,
    next_assessment_date DATE,
    contract_start_date DATE,
    contract_expiry_date DATE,
    security_requirements_met TINYINT(1) DEFAULT 0,
    assessment_responses JSON,
    notes TEXT,
    status ENUM('active','under_review','suspended','terminated') DEFAULT 'active',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    INDEX idx_org (organization_id),
    INDEX idx_criticality (criticality),
    INDEX idx_status (status)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- TRAINING & AWARENESS (Art. 20)
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE training_courses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    target_role ENUM('all','board_member','compliance_manager','employee','technical') DEFAULT 'all',
    nis2_article VARCHAR(20),
    is_mandatory TINYINT(1) DEFAULT 0,
    duration_minutes INT,
    content JSON,
    quiz JSON,
    passing_score TINYINT DEFAULT 70,
    is_active TINYINT(1) DEFAULT 1,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    INDEX idx_org (organization_id),
    INDEX idx_role (target_role)
) ENGINE=InnoDB;

CREATE TABLE training_assignments (
    id INT AUTO_INCREMENT PRIMARY KEY,
    course_id INT NOT NULL,
    user_id INT NOT NULL,
    organization_id INT NOT NULL,
    status ENUM('assigned','in_progress','completed','overdue') DEFAULT 'assigned',
    due_date DATE,
    started_at DATETIME,
    completed_at DATETIME,
    quiz_score TINYINT,
    certificate_url VARCHAR(255),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (course_id) REFERENCES training_courses(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    INDEX idx_user (user_id),
    INDEX idx_org (organization_id),
    INDEX idx_status (status),
    UNIQUE KEY uk_course_user (course_id, user_id)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- ASSET MANAGEMENT (Art. 21.2.i)
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE assets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    name VARCHAR(255) NOT NULL,
    asset_type ENUM('hardware','software','network','data','service','personnel','facility') NOT NULL,
    category VARCHAR(100),
    description TEXT,
    criticality ENUM('low','medium','high','critical') DEFAULT 'medium',
    owner_user_id INT,
    location VARCHAR(255),
    ip_address VARCHAR(45),
    vendor VARCHAR(255),
    version VARCHAR(50),
    serial_number VARCHAR(100),
    purchase_date DATE,
    warranty_expiry DATE,
    status ENUM('active','maintenance','decommissioned') DEFAULT 'active',
    dependencies JSON,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (owner_user_id) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_type (asset_type),
    INDEX idx_criticality (criticality),
    INDEX idx_status (status)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- AUDIT & COMPLIANCE TRACKING
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE compliance_controls (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    control_code VARCHAR(50) NOT NULL,
    framework ENUM('nis2','iso27001','both') DEFAULT 'nis2',
    title VARCHAR(255) NOT NULL,
    description TEXT,
    status ENUM('not_started','in_progress','implemented','verified') DEFAULT 'not_started',
    implementation_percentage TINYINT DEFAULT 0,
    evidence_description TEXT,
    responsible_user_id INT,
    last_verified_at DATETIME,
    next_review_date DATE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (responsible_user_id) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_framework (framework),
    INDEX idx_status (status),
    UNIQUE KEY uk_org_control (organization_id, control_code)
) ENGINE=InnoDB;

CREATE TABLE evidence_files (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    control_id INT,
    entity_type VARCHAR(50),
    entity_id INT,
    file_name VARCHAR(255) NOT NULL,
    file_path VARCHAR(500) NOT NULL,
    file_size INT,
    mime_type VARCHAR(100),
    uploaded_by INT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (control_id) REFERENCES compliance_controls(id) ON DELETE SET NULL,
    FOREIGN KEY (uploaded_by) REFERENCES users(id) ON DELETE SET NULL,
    INDEX idx_org (organization_id),
    INDEX idx_entity (entity_type, entity_id)
) ENGINE=InnoDB;

CREATE TABLE audit_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    organization_id INT,
    action VARCHAR(255) NOT NULL,
    entity_type VARCHAR(100),
    entity_id INT,
    details JSON,
    ip_address VARCHAR(45),
    user_agent VARCHAR(500),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user (user_id),
    INDEX idx_org (organization_id),
    INDEX idx_action (action),
    INDEX idx_entity (entity_type, entity_id),
    INDEX idx_created (created_at)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- AI INTERACTIONS LOG
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE ai_interactions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    organization_id INT NOT NULL,
    user_id INT NOT NULL,
    interaction_type ENUM(
        'gap_analysis','risk_suggestion','policy_draft',
        'incident_classification','qa','report_generation'
    ) NOT NULL,
    prompt_summary VARCHAR(500),
    response_summary TEXT,
    tokens_used INT,
    model_used VARCHAR(50),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    INDEX idx_org (organization_id),
    INDEX idx_type (interaction_type)
) ENGINE=InnoDB;

-- ═══════════════════════════════════════════════════════════════════════════
-- RATE LIMITING
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE rate_limits (
    id INT AUTO_INCREMENT PRIMARY KEY,
    rate_key VARCHAR(255) NOT NULL,
    ip_address VARCHAR(45) NOT NULL,
    attempts INT DEFAULT 1,
    window_start DATETIME NOT NULL,
    INDEX idx_key_ip (rate_key, ip_address),
    INDEX idx_window (window_start)
) ENGINE=InnoDB;
