BEGIN;

-- MGX: Parc Auto & Moyens Generaux
-- This schema is intentionally reference-driven: all business lists are stored in
-- mgx_referentiels and configured by administrators per company.

CREATE TABLE IF NOT EXISTS mgx_depots (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  code VARCHAR(20) NOT NULL,
  label VARCHAR(200) NOT NULL,
  address TEXT,
  city VARCHAR(100),
  phone VARCHAR(50),
  manager_name VARCHAR(200),
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_depots_company_code UNIQUE (company_id, code)
);

CREATE TABLE IF NOT EXISTS mgx_referentiels (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  category VARCHAR(50) NOT NULL,
  code VARCHAR(50),
  label VARCHAR(200) NOT NULL,
  description TEXT,
  color VARCHAR(7),
  icon VARCHAR(50),
  sort_order INTEGER NOT NULL DEFAULT 0,
  metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_referentiels_color CHECK (
    color IS NULL OR color ~ '^#[0-9A-Fa-f]{6}$'
  ),
  CONSTRAINT chk_mgx_referentiels_category CHECK (
    category IN (
      'vehicle_category',
      'vehicle_status',
      'fuel_type',
      'maintenance_type',
      'document_type',
      'expense_type',
      'purchase_category',
      'consumable_category',
      'service_type',
      'alert_type',
      'payment_method',
      'intervention_status',
      'purchase_status',
      'rental_status',
      'supplier_type',
      'unit_of_measure',
      'kilometer_type',
      'it_asset_type',
      'it_asset_status'
    )
  ),
  CONSTRAINT uq_mgx_referentiels_company_category_code UNIQUE (company_id, category, code)
);

ALTER TABLE mgx_referentiels
  DROP CONSTRAINT IF EXISTS chk_mgx_referentiels_category;

ALTER TABLE mgx_referentiels
  ADD CONSTRAINT chk_mgx_referentiels_category CHECK (
    category IN (
      'vehicle_category',
      'vehicle_status',
      'fuel_type',
      'maintenance_type',
      'document_type',
      'expense_type',
      'purchase_category',
      'consumable_category',
      'service_type',
      'alert_type',
      'payment_method',
      'intervention_status',
      'purchase_status',
      'rental_status',
      'supplier_type',
      'unit_of_measure',
      'kilometer_type',
      'it_asset_type',
      'it_asset_status'
    )
  );

CREATE INDEX IF NOT EXISTS idx_mgx_referentiels_company_category
  ON mgx_referentiels (company_id, category, is_active, sort_order);
CREATE UNIQUE INDEX IF NOT EXISTS uq_mgx_referentiels_company_category_code_full
  ON mgx_referentiels (company_id, category, code);

CREATE TABLE IF NOT EXISTS mgx_settings (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  default_currency VARCHAR(10) NOT NULL DEFAULT 'DZD',
  date_format VARCHAR(20) NOT NULL DEFAULT 'DD/MM/YYYY',
  fuel_anomaly_threshold_pct NUMERIC(8, 2) NOT NULL DEFAULT 30,
  default_alert_days_by_document_type JSONB NOT NULL DEFAULT '{}'::jsonb,
  default_payment_terms INTEGER NOT NULL DEFAULT 30,
  enabled_modules JSONB NOT NULL DEFAULT '{
    "fuel": true,
    "maintenance": true,
    "purchases": true,
    "consumables": true,
    "services": true,
    "rentals": true,
    "treasury": true,
    "it_assets": true,
    "alerts": true,
    "reporting": true
  }'::jsonb,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_settings_company UNIQUE (company_id),
  CONSTRAINT chk_mgx_settings_payment_terms CHECK (default_payment_terms >= 0),
  CONSTRAINT chk_mgx_settings_fuel_threshold CHECK (fuel_anomaly_threshold_pct >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_suppliers (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  supplier_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  code VARCHAR(50) NOT NULL,
  name VARCHAR(300) NOT NULL,
  nif VARCHAR(50),
  rc VARCHAR(50),
  address TEXT,
  city VARCHAR(100),
  wilaya VARCHAR(100),
  phone VARCHAR(50),
  email VARCHAR(200),
  fax VARCHAR(50),
  contact_person VARCHAR(200),
  payment_terms INTEGER NOT NULL DEFAULT 30,
  payment_method_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  credit_limit NUMERIC(15, 2),
  current_balance NUMERIC(15, 2) NOT NULL DEFAULT 0,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  notes TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_suppliers_company_code UNIQUE (company_id, code),
  CONSTRAINT chk_mgx_suppliers_payment_terms CHECK (payment_terms >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_vehicles (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  driver_id BIGINT,
  reference VARCHAR(50) NOT NULL,
  plate_number VARCHAR(30) NOT NULL,
  brand VARCHAR(100),
  model VARCHAR(100),
  category_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  year INTEGER,
  chassis_number VARCHAR(100),
  fuel_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  status_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  km_initial NUMERIC(12, 2) NOT NULL DEFAULT 0,
  km_current NUMERIC(12, 2) NOT NULL DEFAULT 0,
  hour_counter NUMERIC(12, 2),
  acquisition_date DATE,
  acquisition_value NUMERIC(15, 2),
  assigned_driver VARCHAR(200),
  observations TEXT,
  photo_url VARCHAR(500),
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_vehicles_company_reference UNIQUE (company_id, reference),
  CONSTRAINT uq_mgx_vehicles_company_plate UNIQUE (company_id, plate_number),
  CONSTRAINT chk_mgx_vehicles_year CHECK (year IS NULL OR year BETWEEN 1900 AND 2200),
  CONSTRAINT chk_mgx_vehicles_km CHECK (km_initial >= 0 AND km_current >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_drivers (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  code VARCHAR(50) NOT NULL,
  full_name VARCHAR(200) NOT NULL,
  phone VARCHAR(50),
  license_number VARCHAR(100),
  license_category VARCHAR(50),
  license_expiry DATE,
  status VARCHAR(30) NOT NULL DEFAULT 'active',
  notes TEXT,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_drivers_company_code UNIQUE (company_id, code)
);

CREATE TABLE IF NOT EXISTS mgx_staff_profiles (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  role_type VARCHAR(30) NOT NULL,
  code VARCHAR(50) NOT NULL,
  full_name VARCHAR(200) NOT NULL,
  phone VARCHAR(50),
  notes TEXT,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_staff_profiles_company_role_code UNIQUE (company_id, role_type, code),
  CONSTRAINT chk_mgx_staff_profiles_role_type CHECK (
    role_type IN ('chef_parc', 'mecanicien', 'back_office', 'controleur_mgx')
  )
);

CREATE TABLE IF NOT EXISTS mgx_mobile_accounts (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  role_type VARCHAR(30) NOT NULL,
  driver_id BIGINT REFERENCES mgx_drivers (id) ON DELETE CASCADE,
  staff_profile_id BIGINT REFERENCES mgx_staff_profiles (id) ON DELETE CASCADE,
  email VARCHAR(200) NOT NULL,
  password_hash TEXT NOT NULL,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  failed_login_attempts INTEGER NOT NULL DEFAULT 0,
  locked_at TIMESTAMPTZ,
  last_login TIMESTAMPTZ,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_mobile_accounts_role_type CHECK (
    role_type IN ('chauffeur', 'chef_parc', 'mecanicien', 'back_office', 'controleur_mgx')
  ),
  CONSTRAINT chk_mgx_mobile_accounts_link CHECK (
    (role_type = 'chauffeur' AND driver_id IS NOT NULL AND staff_profile_id IS NULL)
    OR
    (role_type <> 'chauffeur' AND driver_id IS NULL AND staff_profile_id IS NOT NULL)
  )
);

DO $$
BEGIN
  ALTER TABLE mgx_staff_profiles
    DROP CONSTRAINT IF EXISTS chk_mgx_staff_profiles_role_type;

  ALTER TABLE mgx_staff_profiles
    ADD CONSTRAINT chk_mgx_staff_profiles_role_type CHECK (
      role_type IN ('chef_parc', 'mecanicien', 'back_office', 'controleur_mgx')
    );
END $$;

DO $$
BEGIN
  ALTER TABLE mgx_mobile_accounts
    DROP CONSTRAINT IF EXISTS chk_mgx_mobile_accounts_role_type;

  ALTER TABLE mgx_mobile_accounts
    ADD CONSTRAINT chk_mgx_mobile_accounts_role_type CHECK (
      role_type IN ('chauffeur', 'chef_parc', 'mecanicien', 'back_office', 'controleur_mgx')
    );
END $$;

ALTER TABLE mgx_vehicles
  ADD COLUMN IF NOT EXISTS driver_id BIGINT;

ALTER TABLE mgx_vehicles
  ADD COLUMN IF NOT EXISTS code_camion VARCHAR(50);

CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_code_camion
  ON mgx_vehicles (company_id, code_camion);

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint WHERE conname = 'fk_mgx_vehicles_driver'
  ) THEN
    ALTER TABLE mgx_vehicles
      ADD CONSTRAINT fk_mgx_vehicles_driver
      FOREIGN KEY (driver_id) REFERENCES mgx_drivers (id) ON DELETE SET NULL;
  END IF;
END $$;

CREATE TABLE IF NOT EXISTS mgx_vehicle_km_history (
  id BIGSERIAL PRIMARY KEY,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  km_value NUMERIC(12, 2) NOT NULL,
  reading_date DATE NOT NULL,
  reading_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  source VARCHAR(50),
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_vehicle_km_history_value CHECK (km_value >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_vehicle_driver_assignments (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  driver_id BIGINT REFERENCES mgx_drivers (id) ON DELETE SET NULL,
  driver_name VARCHAR(200) NOT NULL,
  start_date DATE NOT NULL,
  end_date DATE,
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_vehicle_driver_assignments_dates CHECK (end_date IS NULL OR end_date >= start_date)
);

CREATE TABLE IF NOT EXISTS mgx_vehicle_depot_assignments (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  depot_id BIGINT NOT NULL REFERENCES mgx_depots (id) ON DELETE RESTRICT,
  start_date DATE NOT NULL,
  end_date DATE,
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_vehicle_depot_assignments_dates CHECK (end_date IS NULL OR end_date >= start_date)
);

CREATE TABLE IF NOT EXISTS mgx_it_assets (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  reference VARCHAR(50) NOT NULL,
  asset_tag VARCHAR(100),
  name VARCHAR(200) NOT NULL,
  type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  status_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  brand VARCHAR(100),
  model VARCHAR(100),
  serial_number VARCHAR(150),
  assigned_to VARCHAR(200),
  location VARCHAR(200),
  ip_address VARCHAR(100),
  mac_address VARCHAR(100),
  os_name VARCHAR(200),
  acquisition_date DATE,
  warranty_end_date DATE,
  acquisition_value NUMERIC(15, 2),
  notes TEXT,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_it_assets_company_reference UNIQUE (company_id, reference),
  CONSTRAINT uq_mgx_it_assets_company_asset_tag UNIQUE (company_id, asset_tag),
  CONSTRAINT chk_mgx_it_assets_value CHECK (acquisition_value IS NULL OR acquisition_value >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_vehicle_documents (
  id BIGSERIAL PRIMARY KEY,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  document_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  reference_number VARCHAR(100),
  issuer VARCHAR(200),
  start_date DATE,
  expiry_date DATE NOT NULL,
  amount NUMERIC(15, 2),
  file_url VARCHAR(500),
  notes TEXT,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  alert_days_before INTEGER NOT NULL DEFAULT 30,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_vehicle_documents_status CHECK (
    status IN ('active', 'expired', 'cancelled')
  ),
  CONSTRAINT chk_mgx_vehicle_documents_alert_days CHECK (alert_days_before >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_vehicle_agent_reports (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  submitted_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  report_kind VARCHAR(20) NOT NULL,
  priority VARCHAR(20) NOT NULL DEFAULT 'normal',
  title VARCHAR(200) NOT NULL,
  description TEXT NOT NULL,
  details JSONB NOT NULL DEFAULT '{}'::jsonb,
  status VARCHAR(20) NOT NULL DEFAULT 'new',
  source VARCHAR(30) NOT NULL DEFAULT 'mobile_agent',
  admin_notes TEXT,
  converted_entity_type VARCHAR(40),
  converted_entity_id BIGINT,
  resolved_at TIMESTAMPTZ,
  resolved_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_vehicle_agent_reports_kind CHECK (report_kind IN ('request', 'report')),
  CONSTRAINT chk_mgx_vehicle_agent_reports_priority CHECK (
    priority IN ('low', 'normal', 'high', 'critical')
  ),
  CONSTRAINT chk_mgx_vehicle_agent_reports_status CHECK (
    status IN ('new', 'reviewed', 'converted', 'rejected')
  )
);

ALTER TABLE mgx_vehicle_agent_reports
  ADD COLUMN IF NOT EXISTS details JSONB NOT NULL DEFAULT '{}'::jsonb;

ALTER TABLE mgx_vehicle_agent_reports
  ADD COLUMN IF NOT EXISTS converted_entity_type VARCHAR(40);

ALTER TABLE mgx_vehicle_agent_reports
  ADD COLUMN IF NOT EXISTS converted_entity_id BIGINT;

CREATE TABLE IF NOT EXISTS mgx_fuel_entries (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  fuel_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  entry_date DATE NOT NULL,
  quantity NUMERIC(10, 3) NOT NULL,
  unit_price NUMERIC(10, 4) NOT NULL,
  total_amount NUMERIC(15, 2) NOT NULL,
  km_at_fillup NUMERIC(12, 2),
  km_since_last NUMERIC(10, 2),
  consumption_per_100 NUMERIC(8, 3),
  station_supplier VARCHAR(200),
  station_depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  receipt_number VARCHAR(100),
  file_url VARCHAR(500),
  is_anomaly BOOLEAN NOT NULL DEFAULT FALSE,
  anomaly_reason TEXT,
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_fuel_entries_amounts CHECK (
    quantity > 0 AND unit_price >= 0 AND total_amount >= 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_maintenance_plans (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  maintenance_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  label VARCHAR(200) NOT NULL,
  frequency_km NUMERIC(12, 2),
  frequency_days INTEGER,
  last_done_date DATE,
  last_done_km NUMERIC(12, 2),
  next_due_date DATE,
  next_due_km NUMERIC(12, 2),
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_maintenance_plans_frequency CHECK (
    frequency_km IS NULL OR frequency_km > 0
  ),
  CONSTRAINT chk_mgx_maintenance_plans_frequency_days CHECK (
    frequency_days IS NULL OR frequency_days > 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_interventions (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT NOT NULL REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  intervention_type VARCHAR(20) NOT NULL,
  maintenance_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  label VARCHAR(300),
  description TEXT,
  start_date DATE NOT NULL,
  end_date DATE,
  km_at_intervention NUMERIC(12, 2),
  supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  parts_cost NUMERIC(15, 2) NOT NULL DEFAULT 0,
  labor_cost NUMERIC(15, 2) NOT NULL DEFAULT 0,
  total_cost NUMERIC(15, 2) NOT NULL DEFAULT 0,
  status_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  assigned_to_staff_profile_id BIGINT REFERENCES mgx_staff_profiles (id) ON DELETE SET NULL,
  mobile_status VARCHAR(30) NOT NULL DEFAULT 'assigned',
  mobile_timeline JSONB NOT NULL DEFAULT '[]'::jsonb,
  mobile_photos JSONB NOT NULL DEFAULT '[]'::jsonb,
  invoice_number VARCHAR(100),
  file_url VARCHAR(500),
  notes TEXT,
  work_summary TEXT,
  km_at_close NUMERIC(12, 2),
  next_km NUMERIC(12, 2),
  next_date DATE,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_interventions_type CHECK (
    intervention_type IN ('preventive', 'corrective')
  ),
  CONSTRAINT chk_mgx_interventions_costs CHECK (
    parts_cost >= 0 AND labor_cost >= 0 AND total_cost >= 0
  )
);

ALTER TABLE mgx_interventions
  ADD COLUMN IF NOT EXISTS assigned_to_staff_profile_id BIGINT REFERENCES mgx_staff_profiles (id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS mobile_status VARCHAR(30) NOT NULL DEFAULT 'assigned',
  ADD COLUMN IF NOT EXISTS mobile_timeline JSONB NOT NULL DEFAULT '[]'::jsonb,
  ADD COLUMN IF NOT EXISTS mobile_photos JSONB NOT NULL DEFAULT '[]'::jsonb,
  ADD COLUMN IF NOT EXISTS work_summary TEXT,
  ADD COLUMN IF NOT EXISTS km_at_close NUMERIC(12, 2);

CREATE TABLE IF NOT EXISTS mgx_consumable_items (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  code VARCHAR(50) NOT NULL,
  label VARCHAR(200) NOT NULL,
  category_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  unit_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  is_consumable BOOLEAN NOT NULL DEFAULT TRUE,
  unit_price NUMERIC(10, 4),
  min_stock_qty NUMERIC(10, 3) NOT NULL DEFAULT 0,
  current_stock_qty NUMERIC(10, 3) NOT NULL DEFAULT 0,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_consumable_items_company_code UNIQUE (company_id, code),
  CONSTRAINT chk_mgx_consumable_items_stock CHECK (
    min_stock_qty >= 0 AND current_stock_qty >= 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_intervention_lines (
  id BIGSERIAL PRIMARY KEY,
  intervention_id BIGINT NOT NULL REFERENCES mgx_interventions (id) ON DELETE CASCADE,
  item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL,
  description TEXT NOT NULL,
  quantity NUMERIC(10, 3) NOT NULL DEFAULT 1,
  unit_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  unit_price NUMERIC(10, 4) NOT NULL DEFAULT 0,
  total NUMERIC(15, 2) NOT NULL DEFAULT 0,
  line_type VARCHAR(20),
  CONSTRAINT chk_mgx_intervention_lines_amounts CHECK (
    quantity >= 0 AND unit_price >= 0 AND total >= 0
  ),
  CONSTRAINT chk_mgx_intervention_lines_type CHECK (
    line_type IS NULL OR line_type IN ('part', 'labor', 'service', 'other')
  )
);

CREATE TABLE IF NOT EXISTS mgx_purchase_requests (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE SET NULL,
  supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  requested_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  requested_by_mobile_account_id BIGINT REFERENCES mgx_mobile_accounts (id) ON DELETE SET NULL,
  request_date DATE NOT NULL DEFAULT CURRENT_DATE,
  desired_date DATE,
  category_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  urgency VARCHAR(20),
  justification TEXT,
  file_url VARCHAR(500),
  status VARCHAR(30) NOT NULL DEFAULT 'draft',
  validated_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  validated_by_mobile_account_id BIGINT REFERENCES mgx_mobile_accounts (id) ON DELETE SET NULL,
  rejected_by_mobile_account_id BIGINT REFERENCES mgx_mobile_accounts (id) ON DELETE SET NULL,
  validated_at TIMESTAMPTZ,
  rejected_reason TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_purchase_requests_urgency CHECK (
    urgency IS NULL OR urgency IN ('low', 'normal', 'high', 'urgent')
  )
);

ALTER TABLE mgx_purchase_requests
  ADD COLUMN IF NOT EXISTS vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS desired_date DATE,
  ADD COLUMN IF NOT EXISTS file_url VARCHAR(500),
  ADD COLUMN IF NOT EXISTS requested_by_mobile_account_id BIGINT REFERENCES mgx_mobile_accounts (id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS validated_by_mobile_account_id BIGINT REFERENCES mgx_mobile_accounts (id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS rejected_by_mobile_account_id BIGINT REFERENCES mgx_mobile_accounts (id) ON DELETE SET NULL;

CREATE TABLE IF NOT EXISTS mgx_purchase_request_lines (
  id BIGSERIAL PRIMARY KEY,
  request_id BIGINT NOT NULL REFERENCES mgx_purchase_requests (id) ON DELETE CASCADE,
  item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL,
  description TEXT NOT NULL,
  quantity NUMERIC(10, 3) NOT NULL DEFAULT 1,
  estimated_unit_price NUMERIC(10, 4) NOT NULL DEFAULT 0,
  estimated_total NUMERIC(15, 2) NOT NULL DEFAULT 0,
  unit_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  notes TEXT,
  CONSTRAINT chk_mgx_purchase_request_lines_amounts CHECK (
    quantity >= 0 AND estimated_unit_price >= 0 AND estimated_total >= 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_purchase_orders (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  request_id BIGINT REFERENCES mgx_purchase_requests (id) ON DELETE SET NULL,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  order_number VARCHAR(100) NOT NULL,
  order_date DATE NOT NULL DEFAULT CURRENT_DATE,
  delivery_date_expected DATE,
  payment_terms INTEGER,
  category_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  total_ht NUMERIC(15, 2) NOT NULL DEFAULT 0,
  total_ttc NUMERIC(15, 2) NOT NULL DEFAULT 0,
  status_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_purchase_orders_company_order_number UNIQUE (company_id, order_number),
  CONSTRAINT chk_mgx_purchase_orders_totals CHECK (total_ht >= 0 AND total_ttc >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_purchase_order_lines (
  id BIGSERIAL PRIMARY KEY,
  order_id BIGINT NOT NULL REFERENCES mgx_purchase_orders (id) ON DELETE CASCADE,
  item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL,
  description TEXT NOT NULL,
  quantity_ordered NUMERIC(10, 3) NOT NULL DEFAULT 1,
  quantity_received NUMERIC(10, 3) NOT NULL DEFAULT 0,
  unit_price NUMERIC(10, 4) NOT NULL DEFAULT 0,
  total NUMERIC(15, 2) NOT NULL DEFAULT 0,
  unit_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE SET NULL,
  notes TEXT,
  CONSTRAINT chk_mgx_purchase_order_lines_amounts CHECK (
    quantity_ordered >= 0 AND quantity_received >= 0 AND unit_price >= 0 AND total >= 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_receptions (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  order_id BIGINT REFERENCES mgx_purchase_orders (id) ON DELETE SET NULL,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  reception_date DATE NOT NULL DEFAULT CURRENT_DATE,
  reception_number VARCHAR(100) NOT NULL,
  received_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  invoice_number VARCHAR(100),
  invoice_amount NUMERIC(15, 2),
  file_url VARCHAR(500),
  notes TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_receptions_company_number UNIQUE (company_id, reception_number)
);

CREATE TABLE IF NOT EXISTS mgx_reception_lines (
  id BIGSERIAL PRIMARY KEY,
  reception_id BIGINT NOT NULL REFERENCES mgx_receptions (id) ON DELETE CASCADE,
  order_line_id BIGINT REFERENCES mgx_purchase_order_lines (id) ON DELETE SET NULL,
  item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL,
  description TEXT NOT NULL,
  quantity_received NUMERIC(10, 3) NOT NULL DEFAULT 0,
  unit_price NUMERIC(10, 4) NOT NULL DEFAULT 0,
  total NUMERIC(15, 2) NOT NULL DEFAULT 0,
  is_conforming BOOLEAN NOT NULL DEFAULT TRUE,
  notes TEXT,
  CONSTRAINT chk_mgx_reception_lines_amounts CHECK (
    quantity_received >= 0 AND unit_price >= 0 AND total >= 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_purchase_returns (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  reception_id BIGINT NOT NULL REFERENCES mgx_receptions (id) ON DELETE RESTRICT,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  return_date DATE NOT NULL DEFAULT CURRENT_DATE,
  return_number VARCHAR(100) NOT NULL,
  reason TEXT,
  credit_note_number VARCHAR(100),
  credit_amount NUMERIC(15, 2),
  file_url VARCHAR(500),
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_purchase_returns_company_number UNIQUE (company_id, return_number),
  CONSTRAINT chk_mgx_purchase_returns_amount CHECK (credit_amount IS NULL OR credit_amount >= 0)
);

CREATE TABLE IF NOT EXISTS mgx_services (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE SET NULL,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  service_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  label VARCHAR(300),
  service_date DATE NOT NULL,
  amount NUMERIC(15, 2) NOT NULL,
  invoice_number VARCHAR(100),
  file_url VARCHAR(500),
  payment_status VARCHAR(20) NOT NULL DEFAULT 'pending',
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_services_amount CHECK (amount >= 0),
  CONSTRAINT chk_mgx_services_payment_status CHECK (
    payment_status IN ('pending', 'paid', 'cancelled')
  )
);

CREATE TABLE IF NOT EXISTS mgx_rentals (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE SET NULL,
  supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  rental_type VARCHAR(20) NOT NULL,
  start_date DATE NOT NULL,
  end_date DATE,
  daily_rate NUMERIC(10, 2),
  total_amount NUMERIC(15, 2),
  conditions TEXT,
  file_url VARCHAR(500),
  status_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  alert_days_before INTEGER NOT NULL DEFAULT 15,
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_rentals_type CHECK (rental_type IN ('internal', 'external')),
  CONSTRAINT chk_mgx_rentals_alert_days CHECK (alert_days_before >= 0)
);

ALTER TABLE mgx_rentals
  ADD COLUMN IF NOT EXISTS depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL;

CREATE TABLE IF NOT EXISTS mgx_purchase_return_lines (
  id BIGSERIAL PRIMARY KEY,
  return_id BIGINT NOT NULL REFERENCES mgx_purchase_returns (id) ON DELETE CASCADE,
  reception_line_id BIGINT REFERENCES mgx_reception_lines (id) ON DELETE SET NULL,
  item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL,
  description TEXT NOT NULL,
  quantity_returned NUMERIC(10, 3) NOT NULL DEFAULT 0,
  unit_price NUMERIC(10, 4) NOT NULL DEFAULT 0,
  total NUMERIC(15, 2) NOT NULL DEFAULT 0,
  notes TEXT,
  CONSTRAINT chk_mgx_purchase_return_lines_amounts CHECK (
    quantity_returned >= 0 AND unit_price >= 0 AND total >= 0
  )
);

CREATE TABLE IF NOT EXISTS mgx_consumable_movements (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  item_id BIGINT NOT NULL REFERENCES mgx_consumable_items (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  movement_type VARCHAR(20) NOT NULL,
  movement_date DATE NOT NULL DEFAULT CURRENT_DATE,
  quantity NUMERIC(10, 3) NOT NULL,
  unit_price NUMERIC(10, 4),
  total_value NUMERIC(15, 2),
  reference_type VARCHAR(30),
  reference_id BIGINT,
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_consumable_movements_type CHECK (
    movement_type IN ('in', 'out', 'adjustment', 'transfer')
  ),
  CONSTRAINT chk_mgx_consumable_movements_qty CHECK (quantity > 0)
);

ALTER TABLE mgx_purchase_request_lines
  ADD COLUMN IF NOT EXISTS item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL;

ALTER TABLE mgx_consumable_items
  ADD COLUMN IF NOT EXISTS is_consumable BOOLEAN NOT NULL DEFAULT TRUE;

ALTER TABLE mgx_intervention_lines
  ADD COLUMN IF NOT EXISTS item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL;

ALTER TABLE mgx_intervention_lines
  ADD COLUMN IF NOT EXISTS unit_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL;

ALTER TABLE mgx_purchase_order_lines
  ADD COLUMN IF NOT EXISTS item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL;

ALTER TABLE mgx_reception_lines
  ADD COLUMN IF NOT EXISTS item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE SET NULL;

CREATE TABLE IF NOT EXISTS mgx_treasury_movements (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  depot_id BIGINT REFERENCES mgx_depots (id) ON DELETE SET NULL,
  treasury_type VARCHAR(10) NOT NULL,
  account_name VARCHAR(200) NOT NULL,
  direction VARCHAR(10) NOT NULL,
  movement_date DATE NOT NULL,
  amount NUMERIC(15, 2) NOT NULL,
  label VARCHAR(300),
  expense_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  reference_type VARCHAR(30),
  reference_id BIGINT,
  supplier_id BIGINT REFERENCES mgx_suppliers (id) ON DELETE SET NULL,
  vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE SET NULL,
  payment_method_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  receipt_number VARCHAR(100),
  file_url VARCHAR(500),
  notes TEXT,
  created_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_treasury_movements_type CHECK (treasury_type IN ('cash', 'bank')),
  CONSTRAINT chk_mgx_treasury_movements_direction CHECK (direction IN ('in', 'out')),
  CONSTRAINT chk_mgx_treasury_movements_amount CHECK (amount > 0)
);

CREATE TABLE IF NOT EXISTS mgx_alert_configs (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  alert_type_ref_id BIGINT REFERENCES mgx_referentiels (id) ON DELETE SET NULL,
  label VARCHAR(200) NOT NULL,
  trigger_entity VARCHAR(30) NOT NULL,
  trigger_field VARCHAR(50) NOT NULL,
  threshold_value NUMERIC(12, 3),
  threshold_unit VARCHAR(20),
  criticality VARCHAR(20) NOT NULL,
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_alert_configs_entity CHECK (
    trigger_entity IN ('vehicle', 'document', 'maintenance', 'rental', 'consumable')
  ),
  CONSTRAINT chk_mgx_alert_configs_criticality CHECK (
    criticality IN ('info', 'warning', 'critical')
  )
);

CREATE TABLE IF NOT EXISTS mgx_alerts (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT NOT NULL REFERENCES companies (id) ON DELETE CASCADE,
  alert_config_id BIGINT REFERENCES mgx_alert_configs (id) ON DELETE SET NULL,
  vehicle_id BIGINT REFERENCES mgx_vehicles (id) ON DELETE CASCADE,
  document_id BIGINT REFERENCES mgx_vehicle_documents (id) ON DELETE CASCADE,
  consumable_item_id BIGINT REFERENCES mgx_consumable_items (id) ON DELETE CASCADE,
  rental_id BIGINT REFERENCES mgx_rentals (id) ON DELETE CASCADE,
  title VARCHAR(300) NOT NULL,
  message TEXT,
  due_date DATE,
  days_remaining INTEGER,
  criticality VARCHAR(20),
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  treated_by BIGINT REFERENCES users (id) ON DELETE SET NULL,
  treated_at TIMESTAMPTZ,
  treatment_notes TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT chk_mgx_alerts_status CHECK (status IN ('active', 'treated', 'cancelled')),
  CONSTRAINT chk_mgx_alerts_criticality CHECK (
    criticality IS NULL OR criticality IN ('info', 'warning', 'critical')
  )
);

CREATE TABLE IF NOT EXISTS mgx_audit_log (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies (id) ON DELETE SET NULL,
  user_id BIGINT REFERENCES users (id) ON DELETE SET NULL,
  action VARCHAR(50) NOT NULL,
  entity_type VARCHAR(50) NOT NULL,
  entity_id BIGINT,
  old_data JSONB,
  new_data JSONB,
  ip_address INET,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Reference and depot indexes
CREATE INDEX IF NOT EXISTS idx_mgx_depots_company_id ON mgx_depots (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_depots_active ON mgx_depots (company_id, is_active);
CREATE INDEX IF NOT EXISTS idx_mgx_referentiels_company_id ON mgx_referentiels (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_referentiels_category ON mgx_referentiels (category);
CREATE INDEX IF NOT EXISTS idx_mgx_referentiels_active ON mgx_referentiels (is_active);
CREATE INDEX IF NOT EXISTS idx_mgx_settings_company_id ON mgx_settings (company_id);

-- Supplier indexes
CREATE INDEX IF NOT EXISTS idx_mgx_suppliers_company_id ON mgx_suppliers (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_suppliers_type ON mgx_suppliers (supplier_type_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_suppliers_active ON mgx_suppliers (company_id, is_active);

-- Vehicle indexes
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_company_id ON mgx_vehicles (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_depot_id ON mgx_vehicles (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_driver_id ON mgx_vehicles (driver_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_category ON mgx_vehicles (category_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_fuel_type ON mgx_vehicles (fuel_type_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_status ON mgx_vehicles (status_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicles_active ON mgx_vehicles (company_id, is_active);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_km_history_vehicle_date
  ON mgx_vehicle_km_history (vehicle_id, reading_date DESC);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_driver_assignments_vehicle_dates
  ON mgx_vehicle_driver_assignments (vehicle_id, start_date DESC, id DESC);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_driver_assignments_company_driver
  ON mgx_vehicle_driver_assignments (company_id, driver_name);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_driver_assignments_driver_id
  ON mgx_vehicle_driver_assignments (driver_id);
CREATE INDEX IF NOT EXISTS idx_mgx_drivers_company_active ON mgx_drivers (company_id, is_active);
CREATE INDEX IF NOT EXISTS idx_mgx_drivers_depot_id ON mgx_drivers (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_staff_profiles_company_role_active
  ON mgx_staff_profiles (company_id, role_type, is_active);
CREATE UNIQUE INDEX IF NOT EXISTS uq_mgx_mobile_accounts_email
  ON mgx_mobile_accounts (LOWER(email));
CREATE UNIQUE INDEX IF NOT EXISTS uq_mgx_mobile_accounts_driver_id
  ON mgx_mobile_accounts (driver_id)
  WHERE driver_id IS NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS uq_mgx_mobile_accounts_staff_profile_id
  ON mgx_mobile_accounts (staff_profile_id)
  WHERE staff_profile_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_mgx_mobile_accounts_company_role_active
  ON mgx_mobile_accounts (company_id, role_type, is_active);

CREATE TABLE IF NOT EXISTS mgx_mobile_push_tokens (
  id BIGSERIAL PRIMARY KEY,
  mobile_account_id BIGINT NOT NULL REFERENCES mgx_mobile_accounts (id) ON DELETE CASCADE,
  push_token TEXT NOT NULL,
  platform VARCHAR(30),
  is_active BOOLEAN NOT NULL DEFAULT TRUE,
  last_seen_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  CONSTRAINT uq_mgx_mobile_push_tokens_token UNIQUE (push_token)
);

CREATE TABLE IF NOT EXISTS mgx_mobile_notifications (
  id BIGSERIAL PRIMARY KEY,
  mobile_account_id BIGINT NOT NULL REFERENCES mgx_mobile_accounts (id) ON DELETE CASCADE,
  type VARCHAR(80),
  message TEXT NOT NULL,
  is_read BOOLEAN NOT NULL DEFAULT FALSE,
  entity_id BIGINT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_mgx_mobile_notifications_account_read
  ON mgx_mobile_notifications (mobile_account_id, is_read, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_depot_assignments_vehicle_dates
  ON mgx_vehicle_depot_assignments (vehicle_id, start_date DESC, id DESC);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_depot_assignments_depot
  ON mgx_vehicle_depot_assignments (depot_id, start_date DESC);

-- IT asset indexes
CREATE INDEX IF NOT EXISTS idx_mgx_it_assets_company_id ON mgx_it_assets (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_it_assets_depot_id ON mgx_it_assets (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_it_assets_type ON mgx_it_assets (type_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_it_assets_status ON mgx_it_assets (status_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_it_assets_active ON mgx_it_assets (company_id, is_active);

-- Document indexes
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_documents_company_id
  ON mgx_vehicle_documents (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_documents_vehicle_id
  ON mgx_vehicle_documents (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_documents_type
  ON mgx_vehicle_documents (document_type_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_documents_status
  ON mgx_vehicle_documents (status);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_documents_expiry
  ON mgx_vehicle_documents (expiry_date);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_agent_reports_company_id
  ON mgx_vehicle_agent_reports (company_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_mgx_vehicle_agent_reports_vehicle_status
  ON mgx_vehicle_agent_reports (vehicle_id, status, created_at DESC);

-- Fuel indexes
CREATE INDEX IF NOT EXISTS idx_mgx_fuel_entries_company_id ON mgx_fuel_entries (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_fuel_entries_vehicle_id ON mgx_fuel_entries (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_fuel_entries_depot_id ON mgx_fuel_entries (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_fuel_entries_date ON mgx_fuel_entries (entry_date);
CREATE INDEX IF NOT EXISTS idx_mgx_fuel_entries_anomaly ON mgx_fuel_entries (company_id, is_anomaly);

-- Maintenance indexes
CREATE INDEX IF NOT EXISTS idx_mgx_maintenance_plans_company_id
  ON mgx_maintenance_plans (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_maintenance_plans_vehicle_id
  ON mgx_maintenance_plans (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_maintenance_plans_due_date
  ON mgx_maintenance_plans (next_due_date);
CREATE INDEX IF NOT EXISTS idx_mgx_maintenance_plans_due_km
  ON mgx_maintenance_plans (next_due_km);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_company_id ON mgx_interventions (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_vehicle_id ON mgx_interventions (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_depot_id ON mgx_interventions (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_supplier_id ON mgx_interventions (supplier_id);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_status ON mgx_interventions (status_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_start_date ON mgx_interventions (start_date);
CREATE INDEX IF NOT EXISTS idx_mgx_interventions_assigned_staff
  ON mgx_interventions (assigned_to_staff_profile_id, mobile_status);
CREATE INDEX IF NOT EXISTS idx_mgx_intervention_lines_intervention_id
  ON mgx_intervention_lines (intervention_id);

-- Purchase indexes
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_requests_company_id
  ON mgx_purchase_requests (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_requests_depot_id
  ON mgx_purchase_requests (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_requests_vehicle_id
  ON mgx_purchase_requests (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_requests_supplier_id
  ON mgx_purchase_requests (supplier_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_requests_status
  ON mgx_purchase_requests (status);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_requests_date
  ON mgx_purchase_requests (request_date);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_request_lines_request_id
  ON mgx_purchase_request_lines (request_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_request_lines_item_id
  ON mgx_purchase_request_lines (item_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_orders_company_id
  ON mgx_purchase_orders (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_orders_depot_id
  ON mgx_purchase_orders (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_orders_supplier_id
  ON mgx_purchase_orders (supplier_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_orders_status
  ON mgx_purchase_orders (status_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_orders_date
  ON mgx_purchase_orders (order_date);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_order_lines_order_id
  ON mgx_purchase_order_lines (order_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_order_lines_item_id
  ON mgx_purchase_order_lines (item_id);
CREATE INDEX IF NOT EXISTS idx_mgx_receptions_company_id ON mgx_receptions (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_receptions_order_id ON mgx_receptions (order_id);
CREATE INDEX IF NOT EXISTS idx_mgx_receptions_depot_id ON mgx_receptions (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_receptions_date ON mgx_receptions (reception_date);
CREATE INDEX IF NOT EXISTS idx_mgx_reception_lines_reception_id
  ON mgx_reception_lines (reception_id);
CREATE INDEX IF NOT EXISTS idx_mgx_reception_lines_item_id
  ON mgx_reception_lines (item_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_returns_company_id
  ON mgx_purchase_returns (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_returns_reception_id
  ON mgx_purchase_returns (reception_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_returns_date
  ON mgx_purchase_returns (return_date);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_return_lines_return_id
  ON mgx_purchase_return_lines (return_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_return_lines_reception_line_id
  ON mgx_purchase_return_lines (reception_line_id);
CREATE INDEX IF NOT EXISTS idx_mgx_purchase_return_lines_item_id
  ON mgx_purchase_return_lines (item_id);

-- Service and rental indexes
CREATE INDEX IF NOT EXISTS idx_mgx_services_company_id ON mgx_services (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_services_supplier_id ON mgx_services (supplier_id);
CREATE INDEX IF NOT EXISTS idx_mgx_services_vehicle_id ON mgx_services (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_services_depot_id ON mgx_services (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_services_date ON mgx_services (service_date);
CREATE INDEX IF NOT EXISTS idx_mgx_services_payment_status ON mgx_services (payment_status);
CREATE INDEX IF NOT EXISTS idx_mgx_rentals_company_id ON mgx_rentals (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_rentals_vehicle_id ON mgx_rentals (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_rentals_supplier_id ON mgx_rentals (supplier_id);
CREATE INDEX IF NOT EXISTS idx_mgx_rentals_depot_id ON mgx_rentals (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_rentals_status ON mgx_rentals (status_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_rentals_dates ON mgx_rentals (start_date, end_date);

-- Consumable indexes
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_items_company_id
  ON mgx_consumable_items (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_items_category
  ON mgx_consumable_items (category_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_items_active
  ON mgx_consumable_items (company_id, is_active);
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_movements_company_id
  ON mgx_consumable_movements (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_movements_item_id
  ON mgx_consumable_movements (item_id);
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_movements_depot_id
  ON mgx_consumable_movements (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_consumable_movements_date
  ON mgx_consumable_movements (movement_date);

-- Treasury indexes
CREATE INDEX IF NOT EXISTS idx_mgx_treasury_movements_company_id
  ON mgx_treasury_movements (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_treasury_movements_depot_id
  ON mgx_treasury_movements (depot_id);
CREATE INDEX IF NOT EXISTS idx_mgx_treasury_movements_supplier_id
  ON mgx_treasury_movements (supplier_id);
CREATE INDEX IF NOT EXISTS idx_mgx_treasury_movements_vehicle_id
  ON mgx_treasury_movements (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_treasury_movements_date
  ON mgx_treasury_movements (movement_date);
CREATE INDEX IF NOT EXISTS idx_mgx_treasury_movements_type
  ON mgx_treasury_movements (company_id, treasury_type, direction);

-- Alert indexes
CREATE INDEX IF NOT EXISTS idx_mgx_alert_configs_company_id ON mgx_alert_configs (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alert_configs_type ON mgx_alert_configs (alert_type_ref_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alert_configs_active ON mgx_alert_configs (company_id, is_active);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_company_id ON mgx_alerts (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_config_id ON mgx_alerts (alert_config_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_vehicle_id ON mgx_alerts (vehicle_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_document_id ON mgx_alerts (document_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_consumable_item_id ON mgx_alerts (consumable_item_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_rental_id ON mgx_alerts (rental_id);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_status ON mgx_alerts (status);
CREATE INDEX IF NOT EXISTS idx_mgx_alerts_due_date ON mgx_alerts (due_date);

-- Audit indexes
CREATE INDEX IF NOT EXISTS idx_mgx_audit_log_company_id ON mgx_audit_log (company_id);
CREATE INDEX IF NOT EXISTS idx_mgx_audit_log_user_id ON mgx_audit_log (user_id);
CREATE INDEX IF NOT EXISTS idx_mgx_audit_log_entity ON mgx_audit_log (entity_type, entity_id);
CREATE INDEX IF NOT EXISTS idx_mgx_audit_log_action ON mgx_audit_log (action);
CREATE INDEX IF NOT EXISTS idx_mgx_audit_log_created_at ON mgx_audit_log (created_at);

COMMIT;
