# ============================================================
# MODULE 6: Arbo & Veiligheid Dienst Transformatie
# FASE 6 — RI&E Generator, Risicoanalyse, PBM, Inspecties, Jaarverslag
# ============================================================

import os
import json
import sqlite3
from datetime import datetime, timedelta
from flask import jsonify, request
from search import get_db, DB_PATH


# ─── Risk Matrix Helper ────────────────────────────────────────────────────

RISK_MATRIX_5x5 = {
    # (likelihood, effect) -> category, color
    # likelihood: 1=Zeer onwaarschijnlijk, 2=Onwaarschijnlijk, 3=Mogelijk, 4=Waarschijnlijk, 5=Zeer waarschijnlijk
    # effect: 1=Verwaarloosbaar, 2=Gering, 3=Matig, 4=Ernstig, 5=Catastrofaal
}

LIKELIHOOD_LABELS = {1: 'Zeer onwaarschijnlijk', 2: 'Onwaarschijnlijk', 3: 'Mogelijk', 4: 'Waarschijnlijk', 5: 'Zeer waarschijnlijk'}
EFFECT_LABELS = {1: 'Verwaarloosbaar', 2: 'Gering', 3: 'Matig', 4: 'Ernstig', 5: 'Catastrofaal'}

def _risk_score(L, E):
    s = L * E
    if s >= 20: return s, 'extreme', '#FEE2E2'
    if s >= 12: return s, 'high', '#FFEDD5'
    if s >= 6: return s, 'medium', '#FEF3C7'
    return s, 'low', '#D1FAE5'

# PBM mapping per risk category
PBM_MAPPING = {
    'fysiek': [
        {'pbm_type': 'Veiligheidsschoenen', 'norm': 'NEN-EN ISO 20345 S3', 'keurmerk': 'CE'},
        {'pbm_type': 'Werkhandschoenen', 'norm': 'NEN-EN 388', 'keurmerk': 'CE'},
        {'pbm_type': 'Gehoorbescherming', 'norm': 'NEN-EN 352', 'keurmerk': 'CE'},
        {'pbm_type': 'Valbeveiliging', 'norm': 'NEN-EN 363', 'keurmerk': 'CE'},
        {'pbm_type': 'Werkkleding', 'norm': 'NEN-EN ISO 13688', 'keurmerk': 'CE'},
        {'pbm_type': 'Hoofdbescherming', 'norm': 'NEN-EN 397', 'keurmerk': 'CE'},
    ],
    'chemisch': [
        {'pbm_type': 'Adembescherming', 'norm': 'NEN-EN 149 (FFP2/FFP3)', 'keurmerk': 'CE'},
        {'pbm_type': 'Veiligheidsbril', 'norm': 'NEN-EN 166', 'keurmerk': 'CE'},
        {'pbm_type': 'Chemische handschoenen', 'norm': 'NEN-EN 374', 'keurmerk': 'CE'},
        {'pbm_type': 'Chemische beschermkleding', 'norm': 'NEN-EN 14605 Type 3/4', 'keurmerk': 'CE'},
        {'pbm_type': 'Gezichtsscherm', 'norm': 'NEN-EN 166', 'keurmerk': 'CE'},
    ],
    'biologisch': [
        {'pbm_type': 'Adembescherming', 'norm': 'NEN-EN 149 FFP3', 'keurmerk': 'CE'},
        {'pbm_type': 'Nitril handschoenen', 'norm': 'NEN-EN 455', 'keurmerk': 'CE'},
        {'pbm_type': 'Beschermkleding wegwerp', 'norm': 'NEN-EN 14126', 'keurmerk': 'CE'},
    ],
    'psychosociaal': [
        {'pbm_type': 'N.v.t. — maatregelen zijn organisatorisch', 'norm': '', 'keurmerk': ''},
    ],
    'ergonomisch': [
        {'pbm_type': 'Ergonomische werkplekinrichting', 'norm': 'NEN-ISO 9241', 'keurmerk': ''},
        {'pbm_type': 'Kniebeschermers', 'norm': 'NEN-EN 14404', 'keurmerk': 'CE'},
        {'pbm_type': 'Tillband / tilhulpmiddelen', 'norm': 'NEN-EN 13155', 'keurmerk': 'CE'},
    ],
}

# Sector-specific risk profiles
SECTOR_RISKS = {
    'C-MFG': {  # Metaalindustrie
        'name': 'Metaalindustrie',
        'risico_types': ['fysiek', 'chemisch', 'ergonomisch'],
        'common_risks': [
            {'title': 'Bewerken van metaal (slijpen, snijden)', 'category': 'fysiek', 'likelihood': 4, 'effect': 3},
            {'title': 'Blootstelling aan koel- en smeerolie', 'category': 'chemisch', 'likelihood': 3, 'effect': 3},
            {'title': 'Geluidbelasting >80 dB(A)', 'category': 'fysiek', 'likelihood': 5, 'effect': 3},
            {'title': 'Tillen van zware werkstukken', 'category': 'ergonomisch', 'likelihood': 4, 'effect': 2},
        ],
    },
    'C-CHM': {
        'name': 'Chemische industrie',
        'risico_types': ['chemisch', 'fysiek', 'psychosociaal'],
        'common_risks': [
            {'title': 'Blootstelling gevaarlijke stoffen', 'category': 'chemisch', 'likelihood': 3, 'effect': 5},
            {'title': 'LEL-explosiegevaar', 'category': 'fysiek', 'likelihood': 2, 'effect': 5},
            {'title': 'Werken in besloten ruimten', 'category': 'fysiek', 'likelihood': 3, 'effect': 4},
        ],
    },
    'C-CON': {
        'name': 'Bouw en constructie',
        'risico_types': ['fysiek', 'ergonomisch'],
        'common_risks': [
            {'title': 'Vallen van hoogte', 'category': 'fysiek', 'likelihood': 3, 'effect': 5},
            {'title': 'Beukeld gevaar', 'category': 'fysiek', 'likelihood': 3, 'effect': 4},
            {'title': 'Fysieke belasting tilwerk', 'category': 'ergonomisch', 'likelihood': 5, 'effect': 3},
        ],
    },
    'C-OIL': {
        'name': 'Olie, gas, petrochemie',
        'risico_types': ['chemisch', 'fysiek', 'psychosociaal'],
        'common_risks': [
            {'title': 'Process safety (LOPC)', 'category': 'fysiek', 'likelihood': 2, 'effect': 5},
            {'title': 'H2S blootstelling', 'category': 'chemisch', 'likelihood': 3, 'effect': 5},
            {'title': 'Confined space entry', 'category': 'fysiek', 'likelihood': 3, 'effect': 4},
        ],
    },
}

# Inspection templates
INSPECTION_TEMPLATES = {
    'werkplaats': [
        'Vloer schoon en vrij van obstakels',
        'Nooduitgangen vrij en gemarkeerd',
        'Brandblusser aanwezig en gekeurd',
        'EHBO-doos compleet en geldig',
        'Verlichting toereikend',
        'Geluidsniveau acceptabel',
        'Ventilatie adequaat',
        'PBM beschikbaar en gedragen',
        'Werkplekinstructies aanwezig',
        'Veiligheidsborden zichtbaar',
    ],
    'kantoor': [
        'Ergonomische werkplek (stoel, bureau, beeldscherm)',
        'Kabelmanagement ordelijk',
        'Vloer vrij van struikelgevaar',
        'Nooduitgangen vrij',
        'Brandblusser aanwezig',
        'Verlichting toereikend',
        'EHBO-doos aanwezig',
    ],
    'magazijn': [
        'Stellingen stabiel en niet overbelast',
        'Vrijpaden minimaal 80 cm',
        'Heftruckpaden gemarkeerd',
        'PBM gedragen (schoenen, handschoenen)',
        'Laad- en lospleinen veilig',
        'Geluidsniveau acceptabel',
        'Brandblussers aanwezig',
    ],
    'laboratorium': [
        'Chemische stoffen correct opgeslagen',
        'Veiligheidsinformatiebladen beschikbaar',
        'Adembescherming beschikbaar',
        'Oogdouches en nooddouches functioneel',
        'Afzuiging adequaat',
        'PBM voorgeschreven en gedragen',
        'Afval gescheiden opgeslagen',
        'Etikettering van stoffen up-to-date',
    ],
}


# ─── DB Init ────────────────────────────────────────────────────────────────

def init_db_arbo():
    try:
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()

        # Arbo risk assessments (per werkplek/taak)
        c.execute('''CREATE TABLE IF NOT EXISTS arb_risk_assessments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            assessment_code TEXT UNIQUE,
            title TEXT NOT NULL,
            workplace TEXT,
            task TEXT,
            risk_category TEXT,
            likelihood INTEGER DEFAULT 1,
            effect INTEGER DEFAULT 1,
            risk_score INTEGER,
            risk_category_level TEXT,
            description TEXT,
            existing_measures TEXT,
            additional_measures TEXT,
            responsible TEXT,
            deadline TEXT,
            status TEXT DEFAULT 'open',
            dlv_lifecycle_id INTEGER,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # PBM items
        c.execute('''CREATE TABLE IF NOT EXISTS arb_pbm_items (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            pbm_type TEXT NOT NULL,
            norm TEXT,
            keurmerk TEXT,
            risk_category TEXT,
            risk_assessment_id INTEGER,
            replacement_date TEXT,
            condition TEXT DEFAULT 'good',
            quantity INTEGER DEFAULT 1,
            location TEXT,
            notes TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (risk_assessment_id) REFERENCES arb_risk_assessments(id)
        )''')

        # Workplace inspections
        c.execute('''CREATE TABLE IF NOT EXISTS arb_inspections (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            inspection_code TEXT UNIQUE,
            title TEXT NOT NULL,
            workplace_type TEXT,
            location TEXT,
            inspector TEXT,
            inspection_date DATE,
            status TEXT DEFAULT 'planned',
            checklist_data TEXT,
            findings TEXT,
            score INTEGER,
            total_items INTEGER DEFAULT 0,
            passed_items INTEGER DEFAULT 0,
            failed_items INTEGER DEFAULT 0,
            action_items TEXT,
            dlv_lifecycle_id INTEGER,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # Annual reports
        c.execute('''CREATE TABLE IF NOT EXISTS arb_annual_reports (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            year INTEGER NOT NULL,
            company_name TEXT,
            sbi_code TEXT,
            employee_count INTEGER,
            generated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            report_data TEXT,
            dlv_lifecycle_id INTEGER,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        # RI&E documents
        c.execute('''CREATE TABLE IF NOT EXISTS arb_rie_documents (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            rie_code TEXT UNIQUE,
            title TEXT NOT NULL,
            sbi_code TEXT,
            sector TEXT,
            employee_count INTEGER,
            risk_profile TEXT,
            rie_data TEXT,
            status TEXT DEFAULT 'draft',
            dlv_lifecycle_id INTEGER,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )''')

        c.execute('CREATE INDEX IF NOT EXISTS idx_arb_risk_status ON arb_risk_assessments(status)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_arb_risk_cat ON arb_risk_assessments(risk_category)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_arb_insp_status ON arb_inspections(status)')
        c.execute('CREATE INDEX IF NOT EXISTS idx_arb_pbm_risk ON arb_pbm_items(risk_assessment_id)')

        conn.commit()
        conn.close()
        print("[OK] Arbo & Veiligheid tables initialized")
    except Exception as e:
        print(f"[WARN] init_db_arbo: {e}")


def _generate_code(prefix, table, db):
    year = datetime.now().strftime('%Y')
    p = f'{prefix}-{year}-'
    row = db.execute(f"SELECT {prefix}_code FROM {table} WHERE {prefix}_code LIKE ? ORDER BY {prefix}_code DESC LIMIT 1", (p+'%',)).fetchone()
    col = f'{prefix}_code'
    nxt = (int(row[col].split('-')[-1]) + 1) if row else 1
    return f'{p}{nxt:03d}'


def _create_dlv(title, dtype, service, content, db):
    """Create deliverable lifecycle entry and return ID."""
    content_json = json.dumps(content) if isinstance(content, (dict, list)) else content
    cur = db.execute(
        'INSERT INTO dlv_lifecycle (title, type, service, content, created_by) VALUES (?,?,?,?,?)',
        (title, dtype, service, content_json, 'module_arbo')
    )
    db.commit()
    return cur.lastrowid


# ═══════════════════════════════════════════════════════════════════════════
# 1. RI&E GENERATOR (Enhanced)
# ═══════════════════════════════════════════════════════════════════════════

def _rie_generate():
    data = request.get_json()
    if not data:
        return jsonify({'error': 'No data'}), 400

    sbi_code = data.get('sbi_code', '')
    employee_count = data.get('employee_count', 10)
    risk_profile = data.get('risk_profile', ['fysiek', 'chemisch'])
    company_name = data.get('company_name', 'Onbekend')

    # Determine sector
    sector_key = sbi_code[:5] if sbi_code else 'C-MFG'
    sector = SECTOR_RISKS.get(sector_key, SECTOR_RISKS['C-MFG'])

    # Build RI&E sections based on risk profile
    sections = []
    risk_matrix_data = []
    all_risks = []

    for cat in risk_profile:
        cat_risks = sector.get('common_risks', [])
        cat_specific = [r for r in cat_risks if r['category'] == cat]

        if not cat_specific:
            # Generate generic risks for category
            cat_specific = [
                {'title': f'Algemeen risico {cat}', 'category': cat, 'likelihood': 3, 'effect': 3}
            ]

        for risk in cat_specific:
            score, cat_level, color = _risk_score(risk['likelihood'], risk['effect'])
            risk_entry = {
                'title': risk['title'],
                'category': cat,
                'likelihood': risk['likelihood'],
                'likelihood_label': LIKELIHOOD_LABELS.get(risk['likelihood'], ''),
                'effect': risk['effect'],
                'effect_label': EFFECT_LABELS.get(risk['effect'], ''),
                'risk_score': score,
                'risk_level': cat_level,
                'color': color,
            }
            all_risks.append(risk_entry)
            risk_matrix_data.append({
                'L': risk['likelihood'], 'E': risk['effect'],
                'score': score, 'category': cat_level
            })

    # Generate PBMs
    pbm_recommendations = {}
    for cat in risk_profile:
        if cat in PBM_MAPPING:
            pbm_recommendations[cat] = PBM_MAPPING[cat]

    # Employee-based obligations
    obligations = []
    if employee_count > 25:
        obligations.append('Preventiemedewerker verplicht (Arbowet art. 13)')
        obligations.append('Bedrijfsarts contract verplicht')
    if employee_count > 15:
        obligations.append('RI&E moet getoetst zijn door gecertificeerde arbodienst')
    obligations.append('Preventiebeleid opstellen en uitvoeren')
    obligations.append('Werkplekken periodiek inspecteren')
    obligations.append('PBM beschikbaar stellen en onderhouden')

    rie_doc = {
        'company_name': company_name,
        'sbi_code': sbi_code,
        'sector': sector['name'],
        'employee_count': employee_count,
        'risk_profile': risk_profile,
        'generated_date': datetime.utcnow().isoformat(),
        'obligations': obligations,
        'risks': all_risks,
        'risk_matrix': risk_matrix_data,
        'pbm_recommendations': pbm_recommendations,
        'summary': {
            'total_risks': len(all_risks),
            'extreme': sum(1 for r in all_risks if r['risk_level'] == 'extreme'),
            'high': sum(1 for r in all_risks if r['risk_level'] == 'high'),
            'medium': sum(1 for r in all_risks if r['risk_level'] == 'medium'),
            'low': sum(1 for r in all_risks if r['risk_level'] == 'low'),
        }
    }

    # Save to DB
    db = get_db()
    try:
        code = _generate_code('rie', 'arb_rie_documents', db)
        dlv_id = _create_dlv(f'RI&E {company_name} {datetime.now().year}', 'rie', 'arbo', rie_doc, db)
        db.execute(
            'INSERT INTO arb_rie_documents (rie_code, title, sbi_code, sector, employee_count, risk_profile, rie_data, status, dlv_lifecycle_id) VALUES (?,?,?,?,?,?,?,?,?)',
            (code, f'RI&E {company_name}', sbi_code, sector['name'], employee_count,
             json.dumps(risk_profile), json.dumps(rie_doc), 'generated', dlv_id)
        )
        db.commit()
    finally:
        db.close()

    return jsonify({'status': 'generated', 'rie_code': code, 'dlv_id': dlv_id, 'document': rie_doc})


def _rie_list():
    db = get_db()
    try:
        rows = db.execute('SELECT * FROM arb_rie_documents ORDER BY created_at DESC').fetchall()
        return jsonify([dict(r) for r in rows])
    finally:
        db.close()


def _rie_get(rie_id):
    db = get_db()
    try:
        row = db.execute('SELECT * FROM arb_rie_documents WHERE id=?', (rie_id,)).fetchone()
        if not row:
            return jsonify({'error': 'Not found'}), 404
        d = dict(row)
        if d.get('rie_data'):
            try: d['rie_data'] = json.loads(d['rie_data'])
            except: pass
        return jsonify(d)
    finally:
        db.close()


# ═══════════════════════════════════════════════════════════════════════════
# 2. ARBO RISICOANALYSE TOOL
# ═══════════════════════════════════════════════════════════════════════════

def _risk_list():
    db = get_db()
    try:
        cat = request.args.get('category')
        status = request.args.get('status')
        q = 'SELECT * FROM arb_risk_assessments WHERE 1=1'
        params = []
        if cat:
            q += ' AND risk_category = ?'; params.append(cat)
        if status:
            q += ' AND status = ?'; params.append(status)
        q += ' ORDER BY risk_score DESC'
        rows = db.execute(q, params).fetchall()
        return jsonify([dict(r) for r in rows])
    finally:
        db.close()


def _risk_create():
    data = request.get_json()
    if not data or not data.get('title'):
        return jsonify({'error': 'title required'}), 400

    L = data.get('likelihood', 1)
    E = data.get('effect', 1)
    score, cat_level, color = _risk_score(L, E)

    db = get_db()
    try:
        code = _generate_code('ARA', 'arb_risk_assessments', db)
        dlv_id = _create_dlv(data['title'], 'inspection_checklist', 'arbo', data, db)
        cur = db.execute(
            'INSERT INTO arb_risk_assessments (assessment_code, title, workplace, task, risk_category, likelihood, effect, risk_score, risk_category_level, description, existing_measures, additional_measures, responsible, deadline, dlv_lifecycle_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
            (code, data['title'], data.get('workplace'), data.get('task'),
             data.get('risk_category'), L, E, score, cat_level,
             data.get('description'), data.get('existing_measures'),
             data.get('additional_measures'), data.get('responsible'),
             data.get('deadline'), dlv_id)
        )
        db.commit()
        return jsonify({'id': cur.lastrowid, 'code': code, 'risk_score': score, 'risk_level': cat_level, 'dlv_id': dlv_id}), 201
    finally:
        db.close()


def _risk_update(rid):
    data = request.get_json()
    db = get_db()
    try:
        if not db.execute('SELECT id FROM arb_risk_assessments WHERE id=?', (rid,)).fetchone():
            return jsonify({'error': 'Not found'}), 404

        fields, vals = [], []
        for k in ('title', 'workplace', 'task', 'risk_category', 'description',
                   'existing_measures', 'additional_measures', 'responsible', 'deadline', 'status'):
            if k in data:
                fields.append(f'{k}=?'); vals.append(data[k])

        L = data.get('likelihood')
        E = data.get('effect')
        if L is not None and E is not None:
            score, cat_level, _ = _risk_score(L, E)
            fields.extend(['likelihood=?', 'effect=?', 'risk_score=?', 'risk_category_level=?'])
            vals.extend([L, E, score, cat_level])

        if fields:
            fields.append('updated_at=CURRENT_TIMESTAMP')
            vals.append(rid)
            db.execute(f'UPDATE arb_risk_assessments SET {",".join(fields)} WHERE id=?', vals)
            db.commit()
        return jsonify({'status': 'updated'})
    finally:
        db.close()


def _risk_dashboard():
    db = get_db()
    try:
        total = db.execute('SELECT COUNT(*) as c FROM arb_risk_assessments').fetchone()['c']
        by_cat = {r['risk_category']: r['c'] for r in db.execute('SELECT risk_category, COUNT(*) as c FROM arb_risk_assessments GROUP BY risk_category')}
        by_level = {r['risk_category_level']: r['c'] for r in db.execute('SELECT risk_category_level, COUNT(*) as c FROM arb_risk_assessments GROUP BY risk_category_level')}
        by_status = {r['status']: r['c'] for r in db.execute('SELECT status, COUNT(*) as c FROM arb_risk_assessments GROUP BY status')}
        open_items = db.execute("SELECT COUNT(*) as c FROM arb_risk_assessments WHERE status IN ('open','in_progress') AND risk_category_level IN ('extreme','high')").fetchone()['c']
        overdue = db.execute("SELECT COUNT(*) as c FROM arb_risk_assessments WHERE status='open' AND deadline < date('now')").fetchone()['c']
        return jsonify({
            'total': total, 'by_category': by_cat, 'by_level': by_level,
            'by_status': by_status, 'critical_open': open_items, 'overdue': overdue
        })
    finally:
        db.close()


# ═══════════════════════════════════════════════════════════════════════════
# 3. PBM CHECKLIST GENERATOR
# ═══════════════════════════════════════════════════════════════════════════

def _pbm_generate():
    data = request.get_json() or {}
    risk_categories = data.get('risk_categories', ['fysiek', 'chemisch'])

    checklist = []
    for cat in risk_categories:
        items = PBM_MAPPING.get(cat, [])
        for item in items:
            checklist.append({
                'pbm_type': item['pbm_type'],
                'norm': item['norm'],
                'keurmerk': item['keurmerk'],
                'risk_category': cat,
                'replacement_interval': _pbm_replacement_interval(item['pbm_type']),
                'status': 'required',
            })

    # Check existing PBM items in DB
    db = get_db()
    try:
        existing = db.execute('SELECT * FROM arb_pbm_items').fetchall()
        existing_map = {}
        for r in existing:
            key = (r['pbm_type'], r['risk_category'])
            existing_map[key] = dict(r)

        for item in checklist:
            key = (item['pbm_type'], item['risk_category'])
            if key in existing_map:
                item['exists'] = True
                item['condition'] = existing_map[key].get('condition', 'unknown')
                item['existing_id'] = existing_map[key]['id']
                item['replacement_date'] = existing_map[key].get('replacement_date')
            else:
                item['exists'] = False
    finally:
        db.close()

    # Save as deliverable
    dlv_id = _create_dlv(
        f'PBM Checklist {datetime.now().strftime("%Y-%m-%d")}',
        'inspection_checklist', 'arbo', checklist, db
    )

    return jsonify({
        'status': 'generated', 'dlv_id': dlv_id,
        'total_items': len(checklist),
        'checklist': checklist
    })


def _pbm_list():
    db = get_db()
    try:
        rows = db.execute('SELECT * FROM arb_pbm_items ORDER BY risk_category, pbm_type').fetchall()
        return jsonify([dict(r) for r in rows])
    finally:
        db.close()


def _pbm_create():
    data = request.get_json()
    if not data or not data.get('pbm_type'):
        return jsonify({'error': 'pbm_type required'}), 400
    db = get_db()
    try:
        cur = db.execute(
            'INSERT INTO arb_pbm_items (pbm_type, norm, keurmerk, risk_category, risk_assessment_id, replacement_date, condition, quantity, location, notes) VALUES (?,?,?,?,?,?,?,?,?,?)',
            (data['pbm_type'], data.get('norm'), data.get('keurmerk'),
             data.get('risk_category'), data.get('risk_assessment_id'),
             data.get('replacement_date'), data.get('condition', 'good'),
             data.get('quantity', 1), data.get('location'), data.get('notes'))
        )
        db.commit()
        return jsonify({'id': cur.lastrowid, 'status': 'created'}), 201
    finally:
        db.close()


def _pbm_update(pid):
    data = request.get_json()
    db = get_db()
    try:
        if not db.execute('SELECT id FROM arb_pbm_items WHERE id=?', (pid,)).fetchone():
            return jsonify({'error': 'Not found'}), 404
        fields, vals = [], []
        for k in ('pbm_type', 'norm', 'keurmerk', 'risk_category', 'risk_assessment_id',
                   'replacement_date', 'condition', 'quantity', 'location', 'notes'):
            if k in data:
                fields.append(f'{k}=?'); vals.append(data[k])
        if fields:
            vals.append(pid)
            db.execute(f'UPDATE arb_pbm_items SET {",".join(fields)} WHERE id=?', vals)
            db.commit()
        return jsonify({'status': 'updated'})
    finally:
        db.close()


def _pbm_dashboard():
    db = get_db()
    try:
        total = db.execute('SELECT COUNT(*) as c FROM arb_pbm_items').fetchone()['c']
        by_cat = {r['risk_category']: r['c'] for r in db.execute('SELECT risk_category, COUNT(*) as c FROM arb_pbm_items GROUP BY risk_category')}
        needs_replacement = db.execute("SELECT COUNT(*) as c FROM arb_pbm_items WHERE condition IN ('worn','expired') OR replacement_date <= date('now', '+30 days')").fetchone()['c']
        by_condition = {r['condition']: r['c'] for r in db.execute('SELECT condition, COUNT(*) as c FROM arb_pbm_items GROUP BY condition')}
        return jsonify({
            'total': total, 'by_category': by_cat, 'needs_replacement': needs_replacement,
            'by_condition': by_condition
        })
    finally:
        db.close()


def _pbm_replacement_interval(pbm_type):
    intervals = {
        'Adembescherming': '6 maanden (wegwerp) / jaarlijks (halfgelaatsmasker)',
        'Veiligheidsschoenen': 'Jaarlijks',
        'Werkhandschoenen': 'Per gebruik / wekelijks',
        'Chemische handschoenen': 'Per gebruik',
        'Gehoorbescherming': '6 maanden',
        'Valbeveiliging': 'Jaarlijks (keuring)',
        'Werkkleding': '6 maanden',
        'Hoofdbescherming': '3 jaar (max 5 jaar na productie)',
        'Veiligheidsbril': '2 jaar',
        'Gezichtsscherm': 'Jaarlijks',
    }
    return intervals.get(pbm_type, 'Volg fabrikantvoorschrift')


# ═══════════════════════════════════════════════════════════════════════════
# 4. WERKPLEKINSPECTIE APP
# ═══════════════════════════════════════════════════════════════════════════

def _inspection_list():
    db = get_db()
    try:
        status = request.args.get('status')
        wtype = request.args.get('workplace_type')
        q = 'SELECT * FROM arb_inspections WHERE 1=1'
        params = []
        if status:
            q += ' AND status = ?'; params.append(status)
        if wtype:
            q += ' AND workplace_type = ?'; params.append(wtype)
        q += ' ORDER BY inspection_date DESC'
        rows = db.execute(q, params).fetchall()
        return jsonify([dict(r) for r in rows])
    finally:
        db.close()


def _inspection_create():
    data = request.get_json()
    if not data or not data.get('title'):
        return jsonify({'error': 'title required'}), 400

    wtype = data.get('workplace_type', 'werkplaats')
    template = INSPECTION_TEMPLATES.get(wtype, INSPECTION_TEMPLATES['werkplaats'])

    # Initialize checklist from template
    checklist_data = {}
    findings = []
    passed = 0
    failed = 0

    for item in template:
        checklist_data[item] = 'pass'
        passed += 1

    db = get_db()
    try:
        code = _generate_code('INS', 'arb_inspections', db)
        insp_data = {
            'checklist_template': template,
            'workplace_type': wtype,
        }
        dlv_id = _create_dlv(data['title'], 'inspection_checklist', 'arbo', insp_data, db)
        cur = db.execute(
            'INSERT INTO arb_inspections (inspection_code, title, workplace_type, location, inspector, inspection_date, status, checklist_data, findings, score, total_items, passed_items, failed_items, dlv_lifecycle_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
            (code, data['title'], wtype, data.get('location'), data.get('inspector'),
             data.get('inspection_date', datetime.now().strftime('%Y-%m-%d')),
             'planned', json.dumps(checklist_data), json.dumps(findings),
             100 if passed > 0 else 0, len(template), passed, failed, dlv_id)
        )
        db.commit()
        return jsonify({
            'id': cur.lastrowid, 'code': code, 'dlv_id': dlv_id,
            'checklist': checklist_data, 'template': template
        }), 201
    finally:
        db.close()


def _inspection_update(insp_id):
    data = request.get_json()
    db = get_db()
    try:
        row = db.execute('SELECT * FROM arb_inspections WHERE id=?', (insp_id,)).fetchone()
        if not row:
            return jsonify({'error': 'Not found'}), 404

        checklist_data = data.get('checklist_data')
        findings = data.get('findings', [])
        inspector = data.get('inspector', row['inspector'])
        status = data.get('status', row['status'])

        total = 0
        passed = 0
        failed = 0
        if checklist_data:
            total = len(checklist_data)
            for item, result in checklist_data.items():
                if result == 'pass':
                    passed += 1
                elif result in ('fail', 'na'):
                    failed += 1
                    findings.append({'item': item, 'result': result, 'type': 'observation'})

        score = round((passed / total * 100)) if total > 0 else 0

        db.execute(
            'UPDATE arb_inspections SET checklist_data=?, findings=?, inspector=?, status=?, score=?, total_items=?, passed_items=?, failed_items=?, updated_at=CURRENT_TIMESTAMP WHERE id=?',
            (json.dumps(checklist_data) if checklist_data else row['checklist_data'],
             json.dumps(findings), inspector, status, score, total, passed, failed, insp_id)
        )
        db.commit()
        return jsonify({'status': 'updated', 'score': score, 'passed': passed, 'failed': failed})
    finally:
        db.close()


def _inspection_templates():
    return jsonify({'templates': {k: v for k, v in INSPECTION_TEMPLATES.items()}})


def _inspection_dashboard():
    db = get_db()
    try:
        total = db.execute('SELECT COUNT(*) as c FROM arb_inspections').fetchone()['c']
        completed = db.execute("SELECT COUNT(*) as c FROM arb_inspections WHERE status='completed'").fetchone()['c']
        by_type = {r['workplace_type']: r['c'] for r in db.execute('SELECT workplace_type, COUNT(*) as c FROM arb_inspections GROUP BY workplace_type')}
        avg_score_row = db.execute("SELECT AVG(score) as avg FROM arb_inspections WHERE status='completed'").fetchone()
        avg_score = round(avg_score_row['avg'], 1) if avg_score_row and avg_score_row['avg'] else 0
        open_findings = db.execute("SELECT COUNT(*) as c FROM arb_inspections WHERE failed_items > 0 AND status='completed'").fetchone()['c']
        return jsonify({
            'total': total, 'completed': completed, 'by_type': by_type,
            'avg_score': avg_score, 'inspections_with_findings': open_findings
        })
    finally:
        db.close()


# ═══════════════════════════════════════════════════════════════════════════
# 5. ARBO JAARVERSLAG GENERATOR
# ═══════════════════════════════════════════════════════════════════════════

def _annual_report_generate():
    data = request.get_json() or {}
    year = data.get('year', datetime.now().year)
    company_name = data.get('company_name', 'Onbekend')
    sbi_code = data.get('sbi_code', '')
    employee_count = data.get('employee_count', 0)

    db = get_db()
    try:
        # Gather data from all arbo tables
        risk_stats = _risk_dashboard_json(db)
        inspection_stats = _inspection_dashboard_json(db)
        pbm_stats = _pbm_dashboard_json(db)

        # Incidents (from module 4)
        incidents_total = 0
        incidents_lost_time = 0
        incidents_this_year = 0
        try:
            inc_row = db.execute("SELECT COUNT(*) as c FROM incidents WHERE date_occurred >= ? AND date_occurred < ?", (f'{year}-01-01', f'{year+1}-01-01')).fetchone()
            incidents_this_year = inc_row['c'] if inc_row else 0
            lt_row = db.execute("SELECT COUNT(*) as c FROM incidents WHERE lost_time_injury=1 AND date_occurred >= ? AND date_occurred < ?", (f'{year}-01-01', f'{year+1}-01-01')).fetchone()
            incidents_lost_time = lt_row['c'] if lt_row else 0
            inc_total = db.execute("SELECT COUNT(*) as c FROM incidents").fetchone()
            incidents_total = inc_total['c'] if inc_total else 0
        except:
            pass

        # Risk assessments completed this year
        risk_total = risk_stats.get('total', 0)
        risk_extreme = risk_stats.get('by_level', {}).get('extreme', 0)
        risk_high = risk_stats.get('by_level', {}).get('high', 0)
        risk_closed = risk_stats.get('by_status', {}).get('closed', 0)

        # Inspections
        insp_total = inspection_stats.get('total', 0)
        insp_completed = inspection_stats.get('completed', 0)
        insp_avg_score = inspection_stats.get('avg_score', 0)

        # PBM
        pbm_total = pbm_stats.get('total', 0)
        pbm_needs_replacement = pbm_stats.get('needs_replacement', 0)

        report = {
            'year': year,
            'company_name': company_name,
            'sbi_code': sbi_code,
            'employee_count': employee_count,
            'generated_at': datetime.utcnow().isoformat(),
            'sections': {
                'risicoanalyse': {
                    'total_assessments': risk_total,
                    'extreme_risks': risk_extreme,
                    'high_risks': risk_high,
                    'closed': risk_closed,
                    'open_critical': risk_stats.get('critical_open', 0),
                    'overdue': risk_stats.get('overdue', 0),
                },
                'inspecties': {
                    'total': insp_total,
                    'completed': insp_completed,
                    'avg_score': insp_avg_score,
                    'with_findings': inspection_stats.get('inspections_with_findings', 0),
                },
                'pbm': {
                    'total_items': pbm_total,
                    'needs_replacement': pbm_needs_replacement,
                    'by_condition': pbm_stats.get('by_condition', {}),
                },
                'incidenten': {
                    'this_year': incidents_this_year,
                    'lost_time_injuries': incidents_lost_time,
                    'total': incidents_total,
                },
            },
            'trends': {
                'verbeterpunten': _generate_trend_recommendations(risk_stats, inspection_stats, pbm_stats, incidents_this_year),
            },
            'conclusion': _generate_conclusion(risk_extreme, risk_high, incidents_lost_time, insp_avg_score),
        }

        # Save to DB
        dlv_id = _create_dlv(f'Arbo Jaarverslag {company_name} {year}', 'audit_report', 'arbo', report, db)
        db.execute(
            'INSERT INTO arb_annual_reports (year, company_name, sbi_code, employee_count, report_data, dlv_lifecycle_id) VALUES (?,?,?,?,?,?)',
            (year, company_name, sbi_code, employee_count, json.dumps(report), dlv_id)
        )
        db.commit()

        return jsonify({'status': 'generated', 'dlv_id': dlv_id, 'report': report})
    finally:
        db.close()


def _risk_dashboard_json(db):
    try:
        total = db.execute('SELECT COUNT(*) as c FROM arb_risk_assessments').fetchone()['c']
        by_level = {r['risk_category_level']: r['c'] for r in db.execute('SELECT risk_category_level, COUNT(*) as c FROM arb_risk_assessments GROUP BY risk_category_level')}
        by_status = {r['status']: r['c'] for r in db.execute('SELECT status, COUNT(*) as c FROM arb_risk_assessments GROUP BY status')}
        open_items = db.execute("SELECT COUNT(*) as c FROM arb_risk_assessments WHERE status IN ('open','in_progress') AND risk_category_level IN ('extreme','high')").fetchone()['c']
        overdue = db.execute("SELECT COUNT(*) as c FROM arb_risk_assessments WHERE status='open' AND deadline < date('now')").fetchone()['c']
        return {'total': total, 'by_level': by_level, 'by_status': by_status, 'critical_open': open_items, 'overdue': overdue}
    except:
        return {'total': 0, 'by_level': {}, 'by_status': {}, 'critical_open': 0, 'overdue': 0}


def _inspection_dashboard_json(db):
    try:
        total = db.execute('SELECT COUNT(*) as c FROM arb_inspections').fetchone()['c']
        completed = db.execute("SELECT COUNT(*) as c FROM arb_inspections WHERE status='completed'").fetchone()['c']
        avg_row = db.execute("SELECT AVG(score) as avg FROM arb_inspections WHERE status='completed'").fetchone()
        avg_score = round(avg_row['avg'], 1) if avg_row and avg_row['avg'] else 0
        findings = db.execute("SELECT COUNT(*) as c FROM arb_inspections WHERE failed_items > 0 AND status='completed'").fetchone()['c']
        return {'total': total, 'completed': completed, 'avg_score': avg_score, 'inspections_with_findings': findings}
    except:
        return {'total': 0, 'completed': 0, 'avg_score': 0, 'inspections_with_findings': 0}


def _pbm_dashboard_json(db):
    try:
        total = db.execute('SELECT COUNT(*) as c FROM arb_pbm_items').fetchone()['c']
        needs_replacement = db.execute("SELECT COUNT(*) as c FROM arb_pbm_items WHERE condition IN ('worn','expired') OR replacement_date <= date('now', '+30 days')").fetchone()['c']
        by_condition = {r['condition']: r['c'] for r in db.execute('SELECT condition, COUNT(*) as c FROM arb_pbm_items GROUP BY condition')}
        return {'total': total, 'needs_replacement': needs_replacement, 'by_condition': by_condition}
    except:
        return {'total': 0, 'needs_replacement': 0, 'by_condition': {}}


def _generate_trend_recommendations(risk_s, insp_s, pbm_s, incidents):
    recs = []
    if risk_s.get('critical_open', 0) > 0:
        recs.append(f"Aanpakken van {risk_s['critical_open']} openstaande kritieke risico's heeft hoge prioriteit")
    if risk_s.get('overdue', 0) > 0:
        recs.append(f"{risk_s['overdue']} risicobeoordelingen zijn overschreden — direct actie vereist")
    if insp_s.get('avg_score', 100) < 85:
        recs.append(f"Gemiddelde inspectiescore ({insp_s['avg_score']}%) is onder target 85% — verbeterplan opstellen")
    if pbm_s.get('needs_replacement', 0) > 0:
        recs.append(f"{pbm_s['needs_replacement']} PBM-items moeten vervangen worden — planning maken")
    if incidents > 5:
        recs.append(f"Hoog aantal incidenten dit jaar ({incidents}) — root cause analyse uitvoeren")
    if not recs:
        recs.append("Geen kritieke verbeterpunten geïdentificeerd — ga door met periodieke monitoring")
    return recs


def _generate_conclusion(extreme, high, lti, avg_score):
    if extreme > 0 or high > 3 or lti > 2:
        return "De arbo-situatie vereist onmiddellijke verbeteracties op meerdere fronten. Prioriteit: extreme en high risico's aanpakken, incidenten reduceren."
    elif high > 0 or lti > 0:
        return "De arbo-situatie is over het algemeen bevredigend, maar verbetering is nodig op specifieke punten. Focus op high risks en preventie van letsel."
    elif avg_score < 85:
        return "De risicobeheersing is op orde, maar werkplekinspecties tonen structurele tekortkomingen. Verbetervoorstellen implementeren."
    else:
        return "De arbo-situatie is goed op orde. Risico's zijn beheersbaar, inspectiescores zijn boven target en er zijn geen structurele knelpunten."


def _annual_report_list():
    db = get_db()
    try:
        rows = db.execute('SELECT * FROM arb_annual_reports ORDER BY year DESC').fetchall()
        return jsonify([dict(r) for r in rows])
    finally:
        db.close()


# ═══════════════════════════════════════════════════════════════════════════
# ROUTE REGISTRATION
# ═══════════════════════════════════════════════════════════════════════════

def _arbo_page(page, BASE_PATH):
    return page(f'''
<div style="max-width:1400px;margin:0 auto;">
  <h1 style="font-size:24px;font-weight:700;color:#fff;margin-bottom:4px;">🛡️ Arbo & Veiligheid</h1>
  <p style="color:#94A3B8;margin-bottom:20px;">RI&E Generator · Risicoanalyse · PBM Checklists · Werkplekinspectie · Jaarverslag</p>

  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px;margin-bottom:24px">
    <div class="card" style="border-left:4px solid #3B82F6;cursor:pointer" onclick="location.href=BASE+'/api/arbo/rie'">
      <h3 style="font-size:15px;color:#003366;margin:0 0 4px">📋 RI&E Generator</h3>
      <p style="font-size:12px;color:#868E96;margin:0">Genereer een volledige RI&E met AI-ondersteuning</p>
    </div>
    <div class="card" style="border-left:4px solid #10B981;cursor:pointer" onclick="location.href=BASE+'/api/arbo/risk-assessments/dashboard'">
      <h3 style="font-size:15px;color:#003366;margin:0 0 4px">📊 Risicoanalyse Dashboard</h3>
      <p style="font-size:12px;color:#868E96;margin:0">5x5 risicomatrix, acties, trends</p>
    </div>
    <div class="card" style="border-left:4px solid #F59E0B;cursor:pointer" onclick="location.href=BASE+'/api/arbo/pbm/dashboard'">
      <h3 style="font-size:15px;color:#003366;margin:0 0 4px">🥽 PBM Beleid</h3>
      <p style="font-size:12px;color:#868E96;margin:0">PBM checklists, generatie, dashboard</p>
    </div>
    <div class="card" style="border-left:4px solid #8B5CF6;cursor:pointer" onclick="location.href=BASE+'/api/arbo/inspections/dashboard'">
      <h3 style="font-size:15px;color:#003366;margin:0 0 4px">🔍 Werkplekinspecties</h3>
      <p style="font-size:12px;color:#868E96;margin:0">Templates, planning, uitvoering</p>
    </div>
    <div class="card" style="border-left:4px solid #EF4444;cursor:pointer" onclick="location.href=BASE+'/api/arbo/annual-report'">
      <h3 style="font-size:15px;color:#003366;margin:0 0 4px">📝 Arbo Jaarverslag</h3>
      <p style="font-size:12px;color:#868E96;margin:0">Genereer en beheer arbo jaarverslagen</p>
    </div>
  </div>

  <!-- Risk Dashboard Preview -->
  <div class="card">
    <h3 style="margin-bottom:12px">📊 Risicoanalyse Overview</h3>
    <div id="risk-overview"><p style="color:#94A3B8">Laden...</p></div>
  </div>

  <!-- PBM Dashboard Preview -->
  <div class="card" style="margin-top:16px">
    <h3 style="margin-bottom:12px">🥽 PBM Overview</h3>
    <div id="pbm-overview"><p style="color:#94A3B8">Laden...</p></div>
  </div>

  <!-- Inspection Dashboard Preview -->
  <div class="card" style="margin-top:16px">
    <h3 style="margin-bottom:12px">🔍 Inspectie Overview</h3>
    <div id="insp-overview"><p style="color:#94A3B8">Laden...</p></div>
  </div>
</div>
<script>
var BASE = '__BASE_PATH_PLACEHOLDER__';
fetch(BASE+'/api/arbo/risk-assessments/dashboard').then(r=>r.json()).then(d=>{{
  if(!d.total) return document.getElementById('risk-overview').innerHTML='<p style="color:#94A3B8">Geen risicoanalyses</p>';
  var h='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px">';
  h+='<div><span style="font-size:22px;font-weight:700">'+d.total+'</span><br><span style="font-size:11px;color:#94A3B8">Totaal</span></div>';
  h+='<div><span style="font-size:22px;font-weight:700;color:#EF4444">'+(d.extreme||0)+'</span><br><span style="font-size:11px;color:#94A3B8">Extreem</span></div>';
  h+='<div><span style="font-size:22px;font-weight:700;color:#F59E0B">'+(d.high||0)+'</span><br><span style="font-size:11px;color:#94A3B8">Hoog</span></div>';
  h+='<div><span style="font-size:22px;font-weight:700;color:#10B981">'+(d.low||0)+'</span><br><span style="font-size:11px;color:#94A3B8">Laag</span></div>';
  h+='</div>';
  document.getElementById('risk-overview').innerHTML=h;
}}).catch(()=>{{}});
fetch(BASE+'/api/arbo/pbm/dashboard').then(r=>r.json()).then(d=>{{
  if(!d.total) return document.getElementById('pbm-overview').innerHTML='<p style="color:#94A3B8">Geen PBM items</p>';
  var h='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px">';
  h+='<div><span style="font-size:22px;font-weight:700">'+d.total+'</span><br><span style="font-size:11px;color:#94A3B8">Totaal</span></div>';
  h+='<div><span style="font-size:22px;font-weight:700;color:#3B82F6">'+(d.active||0)+'</span><br><span style="font-size:11px;color:#94A3B8">Actief</span></div>';
  h+='</div>';
  document.getElementById('pbm-overview').innerHTML=h;
}}).catch(()=>{{}});
fetch(BASE+'/api/arbo/inspections/dashboard').then(r=>r.json()).then(d=>{{
  if(!d.total) return document.getElementById('insp-overview').innerHTML='<p style="color:#94A3B8">Geen inspecties</p>';
  var h='<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px">';
  h+='<div><span style="font-size:22px;font-weight:700">'+d.total+'</span><br><span style="font-size:11px;color:#94A3B8">Totaal</span></div>';
  h+='<div><span style="font-size:22px;font-weight:700;color:#F59E0B">'+(d.open||0)+'</span><br><span style="font-size:11px;color:#94A3B8">Open</span></div>';
  h+='</div>';
  document.getElementById('insp-overview').innerHTML=h;
}}).catch(()=>{{}});
</script>
'''.replace('__BASE_PATH_PLACEHOLDER__', BASE_PATH), page_title='Arbo & Veiligheid', active='arbo')


def register_arbo_routes(app, page, BASE_PATH="/hseq-dashboard"):
    # Page route
    def _arbo_view():
        return _arbo_page(page, BASE_PATH)
    app.add_url_rule(BASE_PATH + '/arbo', view_func=_arbo_view, endpoint='arbo_page', methods=['GET'])

    # 1. RI&E Generator
    app.add_url_rule(BASE_PATH + '/api/arbo/rie/generate', view_func=_rie_generate, methods=['POST'])
    app.add_url_rule(BASE_PATH + '/api/arbo/rie', view_func=_rie_list, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/rie/<int:rie_id>', view_func=_rie_get, methods=['GET'])

    # 2. Risk Assessment
    app.add_url_rule(BASE_PATH + '/api/arbo/risk-assessments/dashboard', view_func=_risk_dashboard, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/risk-assessments', view_func=_risk_list, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/risk-assessments', view_func=_risk_create, methods=['POST'])
    app.add_url_rule(BASE_PATH + '/api/arbo/risk-assessments/<int:rid>', view_func=_risk_update, methods=['PUT'])

    # 3. PBM
    app.add_url_rule(BASE_PATH + '/api/arbo/pbm/generate', view_func=_pbm_generate, methods=['POST'])
    app.add_url_rule(BASE_PATH + '/api/arbo/pbm/dashboard', view_func=_pbm_dashboard, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/pbm', view_func=_pbm_list, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/pbm', view_func=_pbm_create, methods=['POST'])
    app.add_url_rule(BASE_PATH + '/api/arbo/pbm/<int:pid>', view_func=_pbm_update, methods=['PUT'])

    # 4. Inspections
    app.add_url_rule(BASE_PATH + '/api/arbo/inspections/dashboard', view_func=_inspection_dashboard, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/inspections/templates', view_func=_inspection_templates, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/inspections', view_func=_inspection_list, methods=['GET'])
    app.add_url_rule(BASE_PATH + '/api/arbo/inspections', view_func=_inspection_create, methods=['POST'])
    app.add_url_rule(BASE_PATH + '/api/arbo/inspections/<int:insp_id>', view_func=_inspection_update, methods=['PUT'])

    # 5. Annual Report
    app.add_url_rule(BASE_PATH + '/api/arbo/annual-report/generate', view_func=_annual_report_generate, methods=['POST'])
    app.add_url_rule(BASE_PATH + '/api/arbo/annual-report', view_func=_annual_report_list, methods=['GET'])
