-- =============================================================================
-- 17-field-service-schema.sql
-- MMD-012: Field Service / Bitácora Técnica Móvil
-- =============================================================================
-- Schema: field_service
-- Descripción: Checklist de servicio, registro de diagnóstico, control de mano
--              de obra, modo offline con sincronización
-- Sistema: ERP Mecánicas Diesel
-- Fecha: 2026-01-27
-- =============================================================================

-- Create schema
CREATE SCHEMA IF NOT EXISTS field_service;

-- =============================================================================
-- TYPES/ENUMS
-- =============================================================================

-- Tipo de item de checklist
CREATE TYPE field_service.checklist_item_type AS ENUM (
    'BOOLEAN',
    'TEXT',
    'NUMBER',
    'PHOTO',
    'SIGNATURE',
    'SELECT'
);

-- Tipo de diagnóstico
CREATE TYPE field_service.diagnosis_type AS ENUM (
    'VISUAL',
    'OBD',
    'ELECTRONIC',
    'MECHANICAL'
);

-- Estado de sincronización
CREATE TYPE field_service.sync_status AS ENUM (
    'PENDING',
    'IN_PROGRESS',
    'COMPLETED',
    'FAILED',
    'CONFLICT'
);

-- Estado de checklist response
CREATE TYPE field_service.checklist_status AS ENUM (
    'STARTED',
    'IN_PROGRESS',
    'COMPLETED',
    'CANCELLED'
);

-- Estado de work log
CREATE TYPE field_service.worklog_status AS ENUM (
    'ACTIVE',
    'PAUSED',
    'COMPLETED',
    'CANCELLED'
);

-- =============================================================================
-- TABLE: service_checklists (Plantillas de checklist)
-- =============================================================================
CREATE TABLE field_service.service_checklists (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- Identification
    name VARCHAR(150) NOT NULL,
    description TEXT,
    code VARCHAR(50),

    -- Scope
    service_type_code VARCHAR(50),         -- Aplica a tipo de servicio específico
    vehicle_type VARCHAR(50),              -- Aplica a tipo de vehículo
    is_default BOOLEAN DEFAULT FALSE,

    -- Status
    is_active BOOLEAN DEFAULT TRUE,
    version INTEGER DEFAULT 1,

    -- Audit
    created_by UUID,
    updated_by UUID,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: checklist_item_templates (Items de plantilla)
-- =============================================================================
CREATE TABLE field_service.checklist_item_templates (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    checklist_id UUID NOT NULL REFERENCES field_service.service_checklists(id) ON DELETE CASCADE,

    -- Item definition
    item_order INTEGER NOT NULL DEFAULT 0,
    text VARCHAR(500) NOT NULL,
    item_type field_service.checklist_item_type NOT NULL DEFAULT 'BOOLEAN',

    -- Configuration
    is_required BOOLEAN DEFAULT FALSE,
    options JSONB,                          -- Para tipo SELECT: ["Opción 1", "Opción 2"]
    unit VARCHAR(20),                       -- Para tipo NUMBER: 'km', 'hrs', 'psi', etc.
    min_value DECIMAL(12,2),               -- Validación para NUMBER
    max_value DECIMAL(12,2),

    -- Help
    help_text VARCHAR(500),
    photo_required BOOLEAN DEFAULT FALSE,  -- Requiere foto adicional

    -- Grouping
    section VARCHAR(100),                  -- Sección del checklist

    -- Status
    is_active BOOLEAN DEFAULT TRUE,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: checklist_responses (Respuestas de checklist en un servicio)
-- =============================================================================
CREATE TABLE field_service.checklist_responses (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- References
    incident_id UUID,                       -- Incidente/orden de servicio
    service_order_id UUID,                 -- Orden de servicio alternativa
    checklist_id UUID NOT NULL REFERENCES field_service.service_checklists(id),
    technician_id UUID NOT NULL,

    -- Status
    status field_service.checklist_status DEFAULT 'STARTED',

    -- Timing
    started_at TIMESTAMPTZ DEFAULT NOW(),
    completed_at TIMESTAMPTZ,

    -- Location at start/end
    start_latitude DECIMAL(10,7),
    start_longitude DECIMAL(10,7),
    end_latitude DECIMAL(10,7),
    end_longitude DECIMAL(10,7),

    -- Offline handling
    is_offline BOOLEAN DEFAULT FALSE,
    device_id VARCHAR(100),
    local_id VARCHAR(100),                 -- ID local del dispositivo
    synced_at TIMESTAMPTZ,

    -- Summary
    total_items INTEGER DEFAULT 0,
    completed_items INTEGER DEFAULT 0,
    passed_items INTEGER DEFAULT 0,
    failed_items INTEGER DEFAULT 0,

    -- Notes
    notes TEXT,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: checklist_item_responses (Respuestas individuales)
-- =============================================================================
CREATE TABLE field_service.checklist_item_responses (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    checklist_response_id UUID NOT NULL REFERENCES field_service.checklist_responses(id) ON DELETE CASCADE,
    item_template_id UUID NOT NULL REFERENCES field_service.checklist_item_templates(id),

    -- Response value
    value_boolean BOOLEAN,
    value_text TEXT,
    value_number DECIMAL(12,4),
    value_json JSONB,                      -- Para SELECT múltiple o datos complejos

    -- Evidence
    photo_url VARCHAR(500),
    photo_urls JSONB,                      -- Múltiples fotos
    signature_url VARCHAR(500),

    -- Status
    is_passed BOOLEAN,                     -- Pasó la verificación
    failure_reason TEXT,

    -- Timing
    captured_at TIMESTAMPTZ DEFAULT NOW(),

    -- Offline
    local_id VARCHAR(100),

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: work_logs (Registro de mano de obra)
-- =============================================================================
CREATE TABLE field_service.work_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- References
    incident_id UUID,
    service_order_id UUID,
    technician_id UUID NOT NULL,

    -- Activity
    activity_code VARCHAR(50) NOT NULL,    -- Código de catálogo
    activity_name VARCHAR(200),
    description TEXT,

    -- Timing
    start_time TIMESTAMPTZ NOT NULL,
    end_time TIMESTAMPTZ,
    duration_minutes INTEGER,

    -- Pause tracking
    pause_start TIMESTAMPTZ,
    total_pause_minutes INTEGER DEFAULT 0,

    -- Status
    status field_service.worklog_status DEFAULT 'ACTIVE',

    -- Labor calculation
    labor_rate DECIMAL(10,2),              -- Tarifa por hora
    labor_total DECIMAL(12,2),             -- Total calculado
    is_overtime BOOLEAN DEFAULT FALSE,
    overtime_multiplier DECIMAL(3,2) DEFAULT 1.5,

    -- Location
    latitude DECIMAL(10,7),
    longitude DECIMAL(10,7),

    -- Offline
    is_offline BOOLEAN DEFAULT FALSE,
    device_id VARCHAR(100),
    local_id VARCHAR(100),
    synced_at TIMESTAMPTZ,

    -- Notes
    notes TEXT,

    -- Audit
    created_by UUID,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: activity_catalog (Catálogo de actividades)
-- =============================================================================
CREATE TABLE field_service.activity_catalog (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- Activity definition
    code VARCHAR(50) NOT NULL,
    name VARCHAR(200) NOT NULL,
    description TEXT,

    -- Categorization
    category VARCHAR(100),
    service_type_code VARCHAR(50),

    -- Defaults
    default_duration_minutes INTEGER,
    default_rate DECIMAL(10,2),

    -- Status
    is_active BOOLEAN DEFAULT TRUE,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),

    CONSTRAINT uq_activity_tenant_code UNIQUE (tenant_id, code)
);

-- =============================================================================
-- TABLE: diagnosis_records (Registro de diagnóstico)
-- =============================================================================
CREATE TABLE field_service.diagnosis_records (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- References
    incident_id UUID,
    service_order_id UUID,
    vehicle_id UUID,
    technician_id UUID NOT NULL,

    -- Diagnosis type
    diagnosis_type field_service.diagnosis_type NOT NULL DEFAULT 'VISUAL',

    -- Symptoms
    symptoms TEXT NOT NULL,
    customer_complaint TEXT,

    -- Root cause
    root_cause_code VARCHAR(50),           -- Catálogo de causas raíz
    root_cause_category VARCHAR(100),
    root_cause_description TEXT,

    -- OBD-II (for vehicles)
    obd2_codes JSONB,                      -- ["P0300", "P0420", ...]
    obd2_raw_data JSONB,                   -- Datos crudos del escáner

    -- Readings
    odometer_reading DECIMAL(12,2),
    engine_hours DECIMAL(10,2),
    fuel_level INTEGER,                    -- Porcentaje

    -- Recommendation
    recommendation TEXT,
    severity VARCHAR(20),                  -- LOW, MEDIUM, HIGH, CRITICAL
    requires_immediate_action BOOLEAN DEFAULT FALSE,

    -- Evidence
    photo_urls JSONB,
    video_urls JSONB,

    -- Location
    latitude DECIMAL(10,7),
    longitude DECIMAL(10,7),

    -- Offline
    is_offline BOOLEAN DEFAULT FALSE,
    device_id VARCHAR(100),
    local_id VARCHAR(100),
    synced_at TIMESTAMPTZ,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: root_cause_catalog (Catálogo de causas raíz)
-- =============================================================================
CREATE TABLE field_service.root_cause_catalog (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- Definition
    code VARCHAR(50) NOT NULL,
    name VARCHAR(200) NOT NULL,
    description TEXT,

    -- Categorization
    category VARCHAR(100) NOT NULL,
    subcategory VARCHAR(100),

    -- Common for vehicle type
    vehicle_types JSONB,                   -- ["Diesel", "Gasolina", "Híbrido"]

    -- Recommendations
    standard_recommendation TEXT,
    estimated_repair_hours DECIMAL(5,2),

    -- Status
    is_active BOOLEAN DEFAULT TRUE,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),

    CONSTRAINT uq_root_cause_tenant_code UNIQUE (tenant_id, code)
);

-- =============================================================================
-- TABLE: field_evidence (Evidencias de campo: fotos, videos, firmas)
-- =============================================================================
CREATE TABLE field_service.field_evidence (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- References
    incident_id UUID,
    service_order_id UUID,
    checklist_response_id UUID,
    diagnosis_record_id UUID,

    -- Evidence type
    evidence_type VARCHAR(20) NOT NULL,    -- PHOTO, VIDEO, SIGNATURE, DOCUMENT

    -- File info
    file_url VARCHAR(500) NOT NULL,
    file_name VARCHAR(200),
    file_size INTEGER,
    mime_type VARCHAR(100),

    -- Metadata
    caption TEXT,
    tags JSONB,

    -- Photo specific
    is_before BOOLEAN,                     -- Foto antes del servicio
    is_after BOOLEAN,                      -- Foto después del servicio

    -- Signature specific
    signer_name VARCHAR(150),
    signer_role VARCHAR(50),               -- CUSTOMER, TECHNICIAN, SUPERVISOR

    -- Location
    latitude DECIMAL(10,7),
    longitude DECIMAL(10,7),

    -- Offline
    is_offline BOOLEAN DEFAULT FALSE,
    device_id VARCHAR(100),
    local_id VARCHAR(100),
    synced_at TIMESTAMPTZ,
    pending_upload BOOLEAN DEFAULT FALSE,

    -- Audit
    captured_by UUID,
    captured_at TIMESTAMPTZ DEFAULT NOW(),
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- TABLE: offline_queue_items (Cola de sincronización offline)
-- =============================================================================
CREATE TABLE field_service.offline_queue_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Device
    device_id VARCHAR(100) NOT NULL,
    technician_id UUID,

    -- Entity reference
    entity_type VARCHAR(50) NOT NULL,      -- ChecklistResponse, WorkLog, DiagnosisRecord, FieldEvidence
    entity_id VARCHAR(100) NOT NULL,       -- UUID o ID local
    local_id VARCHAR(100) NOT NULL,

    -- Payload
    payload JSONB NOT NULL,

    -- Sync status
    status field_service.sync_status DEFAULT 'PENDING',
    priority INTEGER DEFAULT 0,            -- Mayor = más prioritario

    -- Attempts
    sync_attempts INTEGER DEFAULT 0,
    max_attempts INTEGER DEFAULT 5,
    last_attempt_at TIMESTAMPTZ,
    next_attempt_at TIMESTAMPTZ,

    -- Result
    synced_at TIMESTAMPTZ,
    server_entity_id UUID,                 -- ID asignado por el servidor
    error_message TEXT,
    error_code VARCHAR(50),

    -- Conflict resolution
    has_conflict BOOLEAN DEFAULT FALSE,
    conflict_data JSONB,
    resolved_at TIMESTAMPTZ,
    resolution VARCHAR(20),                -- LOCAL, SERVER, MERGED

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),

    CONSTRAINT uq_offline_device_local_id UNIQUE (device_id, local_id)
);

-- =============================================================================
-- TABLE: field_checkins (Check-in/Check-out de técnicos)
-- =============================================================================
CREATE TABLE field_service.field_checkins (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- References
    incident_id UUID,
    service_order_id UUID,
    technician_id UUID NOT NULL,
    unit_id UUID,                          -- Unidad móvil

    -- Checkin
    checkin_time TIMESTAMPTZ NOT NULL,
    checkin_latitude DECIMAL(10,7),
    checkin_longitude DECIMAL(10,7),
    checkin_address TEXT,
    checkin_photo_url VARCHAR(500),

    -- Checkout
    checkout_time TIMESTAMPTZ,
    checkout_latitude DECIMAL(10,7),
    checkout_longitude DECIMAL(10,7),
    checkout_photo_url VARCHAR(500),

    -- Duration
    on_site_minutes INTEGER,

    -- Notes
    notes TEXT,

    -- Offline
    is_offline BOOLEAN DEFAULT FALSE,
    device_id VARCHAR(100),
    synced_at TIMESTAMPTZ,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- INDEXES
-- =============================================================================

-- service_checklists
CREATE INDEX idx_checklists_tenant ON field_service.service_checklists(tenant_id);
CREATE INDEX idx_checklists_service_type ON field_service.service_checklists(tenant_id, service_type_code);
CREATE INDEX idx_checklists_active ON field_service.service_checklists(tenant_id, is_active);

-- checklist_item_templates
CREATE INDEX idx_checklist_items_checklist ON field_service.checklist_item_templates(checklist_id);
CREATE INDEX idx_checklist_items_order ON field_service.checklist_item_templates(checklist_id, item_order);

-- checklist_responses
CREATE INDEX idx_checklist_resp_tenant ON field_service.checklist_responses(tenant_id);
CREATE INDEX idx_checklist_resp_incident ON field_service.checklist_responses(tenant_id, incident_id);
CREATE INDEX idx_checklist_resp_technician ON field_service.checklist_responses(tenant_id, technician_id);
CREATE INDEX idx_checklist_resp_status ON field_service.checklist_responses(tenant_id, status);
CREATE INDEX idx_checklist_resp_offline ON field_service.checklist_responses(is_offline, synced_at) WHERE is_offline = TRUE;

-- checklist_item_responses
CREATE INDEX idx_item_resp_response ON field_service.checklist_item_responses(checklist_response_id);

-- work_logs
CREATE INDEX idx_worklogs_tenant ON field_service.work_logs(tenant_id);
CREATE INDEX idx_worklogs_incident ON field_service.work_logs(tenant_id, incident_id);
CREATE INDEX idx_worklogs_technician ON field_service.work_logs(tenant_id, technician_id);
CREATE INDEX idx_worklogs_active ON field_service.work_logs(tenant_id, status) WHERE status = 'ACTIVE';
CREATE INDEX idx_worklogs_date ON field_service.work_logs(tenant_id, start_time);

-- activity_catalog
CREATE INDEX idx_activity_tenant ON field_service.activity_catalog(tenant_id);
CREATE INDEX idx_activity_code ON field_service.activity_catalog(tenant_id, code);

-- diagnosis_records
CREATE INDEX idx_diagnosis_tenant ON field_service.diagnosis_records(tenant_id);
CREATE INDEX idx_diagnosis_incident ON field_service.diagnosis_records(tenant_id, incident_id);
CREATE INDEX idx_diagnosis_vehicle ON field_service.diagnosis_records(tenant_id, vehicle_id);
CREATE INDEX idx_diagnosis_technician ON field_service.diagnosis_records(tenant_id, technician_id);
CREATE INDEX idx_diagnosis_date ON field_service.diagnosis_records(tenant_id, created_at);

-- root_cause_catalog
CREATE INDEX idx_root_cause_tenant ON field_service.root_cause_catalog(tenant_id);
CREATE INDEX idx_root_cause_category ON field_service.root_cause_catalog(tenant_id, category);

-- field_evidence
CREATE INDEX idx_evidence_tenant ON field_service.field_evidence(tenant_id);
CREATE INDEX idx_evidence_incident ON field_service.field_evidence(tenant_id, incident_id);
CREATE INDEX idx_evidence_type ON field_service.field_evidence(tenant_id, evidence_type);
CREATE INDEX idx_evidence_pending ON field_service.field_evidence(pending_upload) WHERE pending_upload = TRUE;

-- offline_queue_items
CREATE INDEX idx_offline_queue_device ON field_service.offline_queue_items(device_id);
CREATE INDEX idx_offline_queue_status ON field_service.offline_queue_items(status);
CREATE INDEX idx_offline_queue_pending ON field_service.offline_queue_items(status, next_attempt_at) WHERE status = 'PENDING';
CREATE INDEX idx_offline_queue_entity ON field_service.offline_queue_items(entity_type, entity_id);

-- field_checkins
CREATE INDEX idx_checkins_tenant ON field_service.field_checkins(tenant_id);
CREATE INDEX idx_checkins_incident ON field_service.field_checkins(tenant_id, incident_id);
CREATE INDEX idx_checkins_technician ON field_service.field_checkins(tenant_id, technician_id);
CREATE INDEX idx_checkins_date ON field_service.field_checkins(tenant_id, checkin_time);

-- =============================================================================
-- TRIGGERS
-- =============================================================================

-- Auto-update timestamps
CREATE TRIGGER update_service_checklists_updated_at
    BEFORE UPDATE ON field_service.service_checklists
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_checklist_item_templates_updated_at
    BEFORE UPDATE ON field_service.checklist_item_templates
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_checklist_responses_updated_at
    BEFORE UPDATE ON field_service.checklist_responses
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_work_logs_updated_at
    BEFORE UPDATE ON field_service.work_logs
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_activity_catalog_updated_at
    BEFORE UPDATE ON field_service.activity_catalog
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_diagnosis_records_updated_at
    BEFORE UPDATE ON field_service.diagnosis_records
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_root_cause_catalog_updated_at
    BEFORE UPDATE ON field_service.root_cause_catalog
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_field_checkins_updated_at
    BEFORE UPDATE ON field_service.field_checkins
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_offline_queue_items_updated_at
    BEFORE UPDATE ON field_service.offline_queue_items
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- =============================================================================
-- FUNCTIONS
-- =============================================================================

-- Calculate work log duration on stop
CREATE OR REPLACE FUNCTION field_service.calculate_worklog_duration()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.end_time IS NOT NULL AND OLD.end_time IS NULL THEN
        NEW.duration_minutes := EXTRACT(EPOCH FROM (NEW.end_time - NEW.start_time)) / 60 - COALESCE(NEW.total_pause_minutes, 0);
        IF NEW.labor_rate IS NOT NULL THEN
            NEW.labor_total := (NEW.duration_minutes / 60.0) * NEW.labor_rate;
            IF NEW.is_overtime THEN
                NEW.labor_total := NEW.labor_total * NEW.overtime_multiplier;
            END IF;
        END IF;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_calculate_worklog_duration
    BEFORE UPDATE ON field_service.work_logs
    FOR EACH ROW EXECUTE FUNCTION field_service.calculate_worklog_duration();

-- Update checklist response counts
CREATE OR REPLACE FUNCTION field_service.update_checklist_counts()
RETURNS TRIGGER AS $$
BEGIN
    UPDATE field_service.checklist_responses
    SET
        completed_items = (
            SELECT COUNT(*) FROM field_service.checklist_item_responses
            WHERE checklist_response_id = COALESCE(NEW.checklist_response_id, OLD.checklist_response_id)
        ),
        passed_items = (
            SELECT COUNT(*) FROM field_service.checklist_item_responses
            WHERE checklist_response_id = COALESCE(NEW.checklist_response_id, OLD.checklist_response_id)
            AND is_passed = TRUE
        ),
        failed_items = (
            SELECT COUNT(*) FROM field_service.checklist_item_responses
            WHERE checklist_response_id = COALESCE(NEW.checklist_response_id, OLD.checklist_response_id)
            AND is_passed = FALSE
        )
    WHERE id = COALESCE(NEW.checklist_response_id, OLD.checklist_response_id);

    RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_update_checklist_counts
    AFTER INSERT OR UPDATE OR DELETE ON field_service.checklist_item_responses
    FOR EACH ROW EXECUTE FUNCTION field_service.update_checklist_counts();

-- Calculate on-site time for checkins
CREATE OR REPLACE FUNCTION field_service.calculate_onsite_time()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.checkout_time IS NOT NULL AND OLD.checkout_time IS NULL THEN
        NEW.on_site_minutes := EXTRACT(EPOCH FROM (NEW.checkout_time - NEW.checkin_time)) / 60;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_calculate_onsite_time
    BEFORE UPDATE ON field_service.field_checkins
    FOR EACH ROW EXECUTE FUNCTION field_service.calculate_onsite_time();

-- =============================================================================
-- VIEWS
-- =============================================================================

-- Active work logs
CREATE OR REPLACE VIEW field_service.vw_active_work_logs AS
SELECT
    wl.id,
    wl.tenant_id,
    wl.technician_id,
    wl.incident_id,
    wl.service_order_id,
    wl.activity_code,
    wl.activity_name,
    wl.start_time,
    EXTRACT(EPOCH FROM (NOW() - wl.start_time)) / 60 AS elapsed_minutes,
    wl.labor_rate,
    wl.is_overtime
FROM field_service.work_logs wl
WHERE wl.status = 'ACTIVE';

-- Pending offline sync
CREATE OR REPLACE VIEW field_service.vw_pending_sync AS
SELECT
    oq.id,
    oq.device_id,
    oq.technician_id,
    oq.entity_type,
    oq.local_id,
    oq.status,
    oq.sync_attempts,
    oq.last_attempt_at,
    oq.error_message,
    oq.created_at
FROM field_service.offline_queue_items oq
WHERE oq.status IN ('PENDING', 'FAILED')
ORDER BY oq.priority DESC, oq.created_at ASC;

-- Technician field activity summary
CREATE OR REPLACE VIEW field_service.vw_technician_activity AS
SELECT
    fc.tenant_id,
    fc.technician_id,
    DATE(fc.checkin_time) AS work_date,
    COUNT(DISTINCT fc.id) AS checkins_count,
    SUM(fc.on_site_minutes) AS total_onsite_minutes,
    COUNT(DISTINCT cr.id) AS checklists_completed,
    COUNT(DISTINCT dr.id) AS diagnoses_created,
    SUM(wl.duration_minutes) AS total_labor_minutes
FROM field_service.field_checkins fc
LEFT JOIN field_service.checklist_responses cr
    ON cr.technician_id = fc.technician_id
    AND DATE(cr.completed_at) = DATE(fc.checkin_time)
    AND cr.status = 'COMPLETED'
LEFT JOIN field_service.diagnosis_records dr
    ON dr.technician_id = fc.technician_id
    AND DATE(dr.created_at) = DATE(fc.checkin_time)
LEFT JOIN field_service.work_logs wl
    ON wl.technician_id = fc.technician_id
    AND DATE(wl.start_time) = DATE(fc.checkin_time)
    AND wl.status = 'COMPLETED'
GROUP BY fc.tenant_id, fc.technician_id, DATE(fc.checkin_time);

-- Checklist completion summary
CREATE OR REPLACE VIEW field_service.vw_checklist_summary AS
SELECT
    cr.tenant_id,
    cr.checklist_id,
    sc.name AS checklist_name,
    COUNT(*) AS total_responses,
    COUNT(*) FILTER (WHERE cr.status = 'COMPLETED') AS completed_count,
    AVG(cr.completed_items::FLOAT / NULLIF(cr.total_items, 0) * 100) AS avg_completion_rate,
    AVG(EXTRACT(EPOCH FROM (cr.completed_at - cr.started_at)) / 60) FILTER (WHERE cr.status = 'COMPLETED') AS avg_completion_minutes
FROM field_service.checklist_responses cr
JOIN field_service.service_checklists sc ON sc.id = cr.checklist_id
GROUP BY cr.tenant_id, cr.checklist_id, sc.name;

-- =============================================================================
-- RLS POLICIES
-- =============================================================================

-- Enable RLS on all tables
ALTER TABLE field_service.service_checklists ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.checklist_item_templates ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.checklist_responses ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.checklist_item_responses ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.work_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.activity_catalog ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.diagnosis_records ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.root_cause_catalog ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.field_evidence ENABLE ROW LEVEL SECURITY;
ALTER TABLE field_service.field_checkins ENABLE ROW LEVEL SECURITY;

-- RLS Policies
CREATE POLICY tenant_isolation_service_checklists ON field_service.service_checklists
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_checklist_item_templates ON field_service.checklist_item_templates
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_checklist_responses ON field_service.checklist_responses
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_checklist_item_responses ON field_service.checklist_item_responses
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_work_logs ON field_service.work_logs
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_activity_catalog ON field_service.activity_catalog
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_diagnosis_records ON field_service.diagnosis_records
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_root_cause_catalog ON field_service.root_cause_catalog
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_field_evidence ON field_service.field_evidence
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

CREATE POLICY tenant_isolation_field_checkins ON field_service.field_checkins
    FOR ALL USING (tenant_id = current_setting('app.tenant_id')::UUID);

-- Note: offline_queue_items no tiene RLS ya que es por device, no por tenant

-- =============================================================================
-- COMMENTS
-- =============================================================================

COMMENT ON SCHEMA field_service IS 'MMD-012: Field Service / Bitácora Técnica Móvil';
COMMENT ON TABLE field_service.service_checklists IS 'Plantillas de checklist por tipo de servicio';
COMMENT ON TABLE field_service.checklist_item_templates IS 'Items de las plantillas de checklist';
COMMENT ON TABLE field_service.checklist_responses IS 'Respuestas de checklist capturadas en servicio';
COMMENT ON TABLE field_service.checklist_item_responses IS 'Respuestas individuales por item';
COMMENT ON TABLE field_service.work_logs IS 'Registro de mano de obra (timer)';
COMMENT ON TABLE field_service.activity_catalog IS 'Catálogo de actividades de mano de obra';
COMMENT ON TABLE field_service.diagnosis_records IS 'Registro de diagnósticos y causas raíz';
COMMENT ON TABLE field_service.root_cause_catalog IS 'Catálogo de causas raíz';
COMMENT ON TABLE field_service.field_evidence IS 'Evidencias: fotos, videos, firmas';
COMMENT ON TABLE field_service.offline_queue_items IS 'Cola de sincronización offline';
COMMENT ON TABLE field_service.field_checkins IS 'Check-in/Check-out de técnicos en sitio';

-- =============================================================================
-- END OF SCHEMA
-- =============================================================================
