-- ATM Anomaly Detection Database Schema
-- PostgreSQL / SQLite compatible

-- Main ATM locations table
CREATE TABLE atm_locations (
    id SERIAL PRIMARY KEY,
    atm_id VARCHAR(50) UNIQUE NOT NULL,
    bank_name VARCHAR(100),
    branch_name VARCHAR(100),
    address TEXT,
    latitude DECIMAL(10, 8),
    longitude DECIMAL(11, 8),
    city VARCHAR(100),
    country VARCHAR(100),
    installation_date DATE,
    atm_model VARCHAR(100),
    camera_count INTEGER DEFAULT 1,
    status VARCHAR(20) DEFAULT 'active', -- active, inactive, maintenance, removed
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Image captures from ATMs
CREATE TABLE atm_captures (
    id SERIAL PRIMARY KEY,
    atm_id VARCHAR(50) NOT NULL REFERENCES atm_locations(atm_id),
    capture_timestamp TIMESTAMP NOT NULL,
    camera_angle VARCHAR(20), -- front, side, top, wide
    image_path VARCHAR(500) NOT NULL,
    image_hash VARCHAR(64), -- SHA-256 for deduplication
    file_size_bytes INTEGER,
    width_pixels INTEGER,
    height_pixels INTEGER,
    lighting_condition VARCHAR(20), -- day, night, indoor, outdoor
    weather_condition VARCHAR(50), -- clear, rain, snow, fog
    blur_score DECIMAL(5, 4), -- 0.0 to 1.0, higher is sharper
    quality_score DECIMAL(5, 4), -- overall image quality
    metadata JSONB, -- flexible metadata storage
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Anomaly categories/types
CREATE TABLE anomaly_types (
    id SERIAL PRIMARY KEY,
    type_code VARCHAR(50) UNIQUE NOT NULL,
    type_name VARCHAR(100) NOT NULL,
    description TEXT,
    severity_level INTEGER CHECK (severity_level BETWEEN 1 AND 5),
    category VARCHAR(50), -- physical, environmental, functional, security
    requires_immediate_action BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Detected anomalies
CREATE TABLE detected_anomalies (
    id SERIAL PRIMARY KEY,
    capture_id INTEGER NOT NULL REFERENCES atm_captures(id),
    anomaly_type_id INTEGER NOT NULL REFERENCES anomaly_types(id),
    confidence_score DECIMAL(5, 4) NOT NULL, -- 0.0 to 1.0
    bounding_box JSONB, -- {x, y, width, height} in normalized coordinates
    severity_score DECIMAL(5, 4), -- calculated severity
    model_version VARCHAR(50), -- which model detected this
    detection_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    verified_by_human BOOLEAN DEFAULT FALSE,
    human_verdict VARCHAR(20), -- confirmed, false_positive, uncertain
    human_notes TEXT,
    status VARCHAR(20) DEFAULT 'open', -- open, acknowledged, resolved, false_positive
    resolved_at TIMESTAMP,
    resolution_notes TEXT,
    assigned_to VARCHAR(100), -- technician or team
    priority INTEGER CHECK (priority BETWEEN 1 AND 5),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Baseline/reference images for comparison
CREATE TABLE baseline_images (
    id SERIAL PRIMARY KEY,
    atm_id VARCHAR(50) NOT NULL REFERENCES atm_locations(atm_id),
    camera_angle VARCHAR(20),
    baseline_type VARCHAR(20) DEFAULT 'normal', -- normal, maintenance, installation
    image_path VARCHAR(500) NOT NULL,
    established_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP, -- when baseline should be refreshed
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Change detection history
CREATE TABLE change_detections (
    id SERIAL PRIMARY KEY,
    atm_id VARCHAR(50) NOT NULL REFERENCES atm_locations(atm_id),
    camera_angle VARCHAR(20),
    reference_capture_id INTEGER REFERENCES atm_captures(id),
    current_capture_id INTEGER NOT NULL REFERENCES atm_captures(id),
    change_score DECIMAL(5, 4), -- overall change magnitude
    structural_similarity DECIMAL(5, 4), -- SSIM score
    pixel_difference DECIMAL(5, 4), -- percentage of changed pixels
    significant_change BOOLEAN DEFAULT FALSE,
    detected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    reviewed_by INTEGER,
    review_notes TEXT
);

-- Model training runs
CREATE TABLE model_training_runs (
    id SERIAL PRIMARY KEY,
    model_name VARCHAR(100) NOT NULL,
    model_version VARCHAR(50) NOT NULL,
    training_start TIMESTAMP,
    training_end TIMESTAMP,
    dataset_size INTEGER,
    epochs INTEGER,
    batch_size INTEGER,
    learning_rate DECIMAL(10, 8),
    final_loss DECIMAL(10, 6),
    validation_map DECIMAL(5, 4), -- mean average precision
    validation_accuracy DECIMAL(5, 4),
    model_path VARCHAR(500),
    config JSONB,
    status VARCHAR(20) DEFAULT 'running', -- running, completed, failed
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Alerting and notifications
CREATE TABLE alerts (
    id SERIAL PRIMARY KEY,
    anomaly_id INTEGER REFERENCES detected_anomalies(id),
    alert_type VARCHAR(50), -- email, sms, webhook, dashboard
    recipient VARCHAR(200),
    sent_at TIMESTAMP,
    delivered_at TIMESTAMP,
    read_at TIMESTAMP,
    status VARCHAR(20) DEFAULT 'pending', -- pending, sent, delivered, failed
    retry_count INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Maintenance logs
CREATE TABLE maintenance_logs (
    id SERIAL PRIMARY KEY,
    atm_id VARCHAR(50) NOT NULL REFERENCES atm_locations(atm_id),
    maintenance_type VARCHAR(50), -- repair, cleaning, inspection, upgrade
    technician_name VARCHAR(100),
    started_at TIMESTAMP,
    completed_at TIMESTAMP,
    description TEXT,
    parts_replaced JSONB,
    cost DECIMAL(10, 2),
    before_images JSONB,
    after_images JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Indexes for performance
CREATE INDEX idx_captures_atm_id ON atm_captures(atm_id);
CREATE INDEX idx_captures_timestamp ON atm_captures(capture_timestamp);
CREATE INDEX idx_anomalies_capture ON detected_anomalies(capture_id);
CREATE INDEX idx_anomalies_type ON detected_anomalies(anomaly_type_id);
CREATE INDEX idx_anomalies_status ON detected_anomalies(status);
CREATE INDEX idx_anomalies_created ON detected_anomalies(created_at);
CREATE INDEX idx_changes_atm ON change_detections(atm_id);
CREATE INDEX idx_alerts_anomaly ON alerts(anomaly_id);

-- Insert default anomaly types
INSERT INTO anomaly_types (type_code, type_name, description, severity_level, category, requires_immediate_action) VALUES
('physical_damage', 'Physical Damage', 'Visible damage to ATM structure, screen, or components', 4, 'physical', FALSE),
('vandalism', 'Vandalism', 'Intentional damage including scratches, dents, or broken parts', 4, 'physical', FALSE),
('graffiti', 'Graffiti', 'Unauthorized markings or paint on ATM surfaces', 2, 'environmental', FALSE),
('dirt_debris', 'Dirt and Debris', 'Excessive dirt, leaves, or debris blocking ATM or camera', 2, 'environmental', FALSE),
('obstruction', 'Obstruction', 'Objects blocking access to ATM or camera view', 3, 'environmental', FALSE),
('skimming_device', 'Skimming Device', 'Suspicious device attached to card reader or PIN pad', 5, 'security', TRUE),
('suspicious_attachment', 'Suspicious Attachment', 'Unknown device or object attached to ATM', 5, 'security', TRUE),
('out_of_service', 'Out of Service', 'ATM displaying out of service message or dark screen', 3, 'functional', FALSE),
('screen_damage', 'Screen Damage', 'Cracked, discolored, or non-functional display', 3, 'physical', FALSE),
('cash_jam', 'Cash Jam', 'Cash dispenser showing signs of jam or malfunction', 3, 'functional', FALSE),
('receipt_jam', 'Receipt Jam', 'Receipt printer showing signs of jam or empty', 2, 'functional', FALSE),
('lighting_failure', 'Lighting Failure', 'ATM area poorly lit or lights not functioning', 3, 'environmental', FALSE),
('camera_blind', 'Camera Blind', 'Security camera blocked, damaged, or misaligned', 4, 'security', FALSE),
('network_down', 'Network Down', 'ATM showing network connectivity issues', 3, 'functional', FALSE);
