CREATE TABLE IF NOT EXISTS committee (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(120) NOT NULL,
  committee_type VARCHAR(50) NOT NULL DEFAULT 'general',
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS app_user (
  id BIGSERIAL PRIMARY KEY,
  full_name VARCHAR(120) NOT NULL,
  email VARCHAR(255) UNIQUE NOT NULL,
  password_hash TEXT NOT NULL DEFAULT '',
  role role_type NOT NULL DEFAULT 'member',
  committee_id BIGINT REFERENCES committee(id),
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  security_classification VARCHAR(30) NOT NULL DEFAULT 'standard',
  force_password_reset BOOLEAN NOT NULL DEFAULT FALSE,
  two_factor_enabled BOOLEAN NOT NULL DEFAULT FALSE,
  last_mfa_at TIMESTAMPTZ,
  last_login_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS refresh_token (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  token_hash TEXT NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS br_case (
  id BIGSERIAL PRIMARY KEY,
  case_number VARCHAR(50) UNIQUE NOT NULL,
  title VARCHAR(255) NOT NULL,
  case_type VARCHAR(50) NOT NULL,
  status VARCHAR(50) NOT NULL DEFAULT 'neu',
  priority VARCHAR(20) NOT NULL DEFAULT 'mittel',
  confidentiality_level conf_level NOT NULL DEFAULT 'intern',
  summary TEXT,
  affected_employee_name VARCHAR(120),
  department VARCHAR(120),
  committee_id BIGINT REFERENCES committee(id),
  owner_user_id BIGINT NOT NULL REFERENCES app_user(id),
  legal_hold BOOLEAN NOT NULL DEFAULT FALSE,
  created_by BIGINT REFERENCES app_user(id),
  updated_by BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deleted_at TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS deadline (
  id BIGSERIAL PRIMARY KEY,
  case_id BIGINT REFERENCES br_case(id) ON DELETE CASCADE,
  title VARCHAR(255) NOT NULL,
  deadline_type VARCHAR(50) NOT NULL,
  due_date TIMESTAMPTZ NOT NULL,
  status VARCHAR(30) NOT NULL DEFAULT 'offen',
  remind_days_before INTEGER NOT NULL DEFAULT 2,
  created_by BIGINT REFERENCES app_user(id),
  updated_by BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deleted_at TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS meeting (
  id BIGSERIAL PRIMARY KEY,
  meeting_number VARCHAR(50) UNIQUE NOT NULL,
  title VARCHAR(255) NOT NULL,
  meeting_type VARCHAR(50) NOT NULL DEFAULT 'ordentlich',
  meeting_date DATE NOT NULL,
  start_time TIME,
  end_time TIME,
  location VARCHAR(255),
  status VARCHAR(30) NOT NULL DEFAULT 'geplant',
  protocol_text TEXT,
  is_quorate BOOLEAN,
  quorum_recorded_at TIMESTAMPTZ,
  quorum_recorded_by BIGINT REFERENCES app_user(id),
  committee_id BIGINT REFERENCES committee(id),
  chair_user_id BIGINT REFERENCES app_user(id),
  secretary_user_id BIGINT REFERENCES app_user(id),
  created_by BIGINT REFERENCES app_user(id),
  updated_by BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS meeting_agenda_item (
  id BIGSERIAL PRIMARY KEY,
  meeting_id BIGINT NOT NULL REFERENCES meeting(id) ON DELETE CASCADE,
  agenda_number VARCHAR(20) NOT NULL,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  duration_minutes INTEGER,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS decision (
  id BIGSERIAL PRIMARY KEY,
  decision_number VARCHAR(50) UNIQUE NOT NULL,
  meeting_id BIGINT REFERENCES meeting(id) ON DELETE SET NULL,
  agenda_item_id BIGINT REFERENCES meeting_agenda_item(id) ON DELETE SET NULL,
  case_id BIGINT REFERENCES br_case(id) ON DELETE SET NULL,
  title VARCHAR(255) NOT NULL,
  decision_text TEXT NOT NULL,
  status VARCHAR(30) NOT NULL DEFAULT 'offen',
  votes_yes INTEGER NOT NULL DEFAULT 0,
  votes_no INTEGER NOT NULL DEFAULT 0,
  votes_abstain INTEGER NOT NULL DEFAULT 0,
  responsible_user_id BIGINT REFERENCES app_user(id),
  due_date TIMESTAMPTZ,
  created_by BIGINT REFERENCES app_user(id),
  updated_by BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS task (
  id BIGSERIAL PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  status VARCHAR(30) NOT NULL DEFAULT 'offen',
  priority VARCHAR(20) NOT NULL DEFAULT 'mittel',
  assigned_user_id BIGINT REFERENCES app_user(id),
  backup_user_id BIGINT REFERENCES app_user(id),
  case_id BIGINT REFERENCES br_case(id) ON DELETE SET NULL,
  meeting_id BIGINT REFERENCES meeting(id) ON DELETE SET NULL,
  decision_id BIGINT REFERENCES decision(id) ON DELETE SET NULL,
  due_date TIMESTAMPTZ,
  confidentiality_level conf_level NOT NULL DEFAULT 'intern',
  created_by BIGINT REFERENCES app_user(id),
  updated_by BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deleted_at TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS document_item (
  id BIGSERIAL PRIMARY KEY,
  document_number VARCHAR(50) UNIQUE NOT NULL,
  title VARCHAR(255) NOT NULL,
  document_type VARCHAR(50) NOT NULL,
  description TEXT,
  version_label VARCHAR(30) NOT NULL DEFAULT 'v1',
  file_name VARCHAR(255),
  storage_path TEXT,
  storage_provider VARCHAR(20) NOT NULL DEFAULT 'local',
  mime_type VARCHAR(100),
  size_bytes BIGINT,
  sha256_hash VARCHAR(64),
  confidentiality_level conf_level NOT NULL DEFAULT 'intern',
  case_id BIGINT REFERENCES br_case(id) ON DELETE SET NULL,
  meeting_id BIGINT REFERENCES meeting(id) ON DELETE SET NULL,
  decision_id BIGINT REFERENCES decision(id) ON DELETE SET NULL,
  uploaded_by BIGINT REFERENCES app_user(id),
  is_signed BOOLEAN NOT NULL DEFAULT FALSE,
  scan_status scan_status_type NOT NULL DEFAULT 'pending',
  scan_engine VARCHAR(50),
  scan_result TEXT,
  uploaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deleted_at TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS document_scan_event (
  id BIGSERIAL PRIMARY KEY,
  document_id BIGINT NOT NULL REFERENCES document_item(id) ON DELETE CASCADE,
  scanned_by_user_id BIGINT REFERENCES app_user(id),
  status scan_status_type NOT NULL,
  engine VARCHAR(50) NOT NULL,
  result_text TEXT,
  scanned_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS comment_item (
  id BIGSERIAL PRIMARY KEY,
  entity_type VARCHAR(50) NOT NULL,
  entity_id BIGINT NOT NULL,
  comment_text TEXT NOT NULL,
  visibility VARCHAR(30) NOT NULL DEFAULT 'intern',
  author_user_id BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deleted_at TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS template_item (
  id BIGSERIAL PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  category VARCHAR(50) NOT NULL,
  description TEXT,
  content TEXT NOT NULL,
  version_label VARCHAR(30) NOT NULL DEFAULT 'v1',
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_by BIGINT REFERENCES app_user(id),
  updated_by BIGINT REFERENCES app_user(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS notification_item (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  notification_type VARCHAR(50) NOT NULL,
  title VARCHAR(255) NOT NULL,
  entity_type VARCHAR(50),
  entity_id BIGINT,
  is_read BOOLEAN NOT NULL DEFAULT FALSE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS audit_log (
  id BIGSERIAL PRIMARY KEY,
  actor_user_id BIGINT REFERENCES app_user(id),
  action VARCHAR(100) NOT NULL,
  entity_type VARCHAR(50),
  entity_id BIGINT,
  metadata JSONB,
  ip_address INET,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS auth_challenge (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  challenge_type VARCHAR(40) NOT NULL,
  challenge_value TEXT NOT NULL,
  metadata JSONB,
  expires_at TIMESTAMPTZ NOT NULL,
  used_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS webauthn_challenge (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  flow_type VARCHAR(40) NOT NULL,
  challenge TEXT NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  used_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS webauthn_credential (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  credential_id TEXT NOT NULL UNIQUE,
  public_key TEXT NOT NULL,
  counter BIGINT NOT NULL DEFAULT 0,
  transports JSONB,
  credential_device_type VARCHAR(50),
  credential_backed_up BOOLEAN NOT NULL DEFAULT FALSE,
  nickname VARCHAR(120),
  last_used_at TIMESTAMPTZ,
  revoked_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS user_totp_secret (
  user_id BIGINT PRIMARY KEY REFERENCES app_user(id) ON DELETE CASCADE,
  secret_base32 TEXT NOT NULL,
  is_verified BOOLEAN NOT NULL DEFAULT FALSE,
  verified_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
