-- ================================================================
--  SCHEMA - App Recolección Inteligente · Hackathon Celaya 2026
-- ================================================================

CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- ----------------------------------------------------------------
-- 1. USERS
-- ----------------------------------------------------------------
CREATE TABLE users (
    id            UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
    email         VARCHAR(255) UNIQUE,
    phone         VARCHAR(20)  UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    fcm_token     VARCHAR(500),
    rol           VARCHAR(20)  NOT NULL DEFAULT 'ciudadano',
    activo        BOOLEAN      NOT NULL DEFAULT TRUE,
    created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    updated_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    CONSTRAINT chk_contacto CHECK (email IS NOT NULL OR phone IS NOT NULL)
);

-- ----------------------------------------------------------------
-- 2. RUTAS
-- ----------------------------------------------------------------
CREATE TABLE rutas (
    id           SERIAL       PRIMARY KEY,
    route_id     VARCHAR(20)  NOT NULL UNIQUE,
    nombre       VARCHAR(255) NOT NULL,
    truck_id     SMALLINT     NOT NULL,
    hora_inicio  TIME         NOT NULL,
    hora_fin_ref TIME         NOT NULL,
    activa       BOOLEAN      NOT NULL DEFAULT TRUE,
    created_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- ----------------------------------------------------------------
-- 3. RUTA_POSICIONES
-- ----------------------------------------------------------------
CREATE TABLE ruta_posiciones (
    id            BIGSERIAL    PRIMARY KEY,
    ruta_id       INT          NOT NULL REFERENCES rutas(id) ON DELETE CASCADE,
    position_id   SMALLINT     NOT NULL,
    lat           DECIMAL(9,6) NOT NULL,
    lng           DECIMAL(9,6) NOT NULL,
    speed_kmh     SMALLINT     NOT NULL DEFAULT 0,
    ts_referencia TIMESTAMPTZ  NOT NULL,
    offset_seg    INT          NOT NULL DEFAULT 0,
    punto         GEOGRAPHY(POINT, 4326) NOT NULL,
    CONSTRAINT uq_ruta_posicion UNIQUE (ruta_id, position_id)
);

CREATE INDEX idx_ruta_pos_ruta  ON ruta_posiciones (ruta_id, position_id);
CREATE INDEX idx_ruta_pos_punto ON ruta_posiciones USING GIST (punto);

-- ----------------------------------------------------------------
-- 4. COLONIAS
-- ----------------------------------------------------------------
CREATE TABLE colonias (
    id              SERIAL       PRIMARY KEY,
    nombre          VARCHAR(255) NOT NULL UNIQUE,
    ruta_id         INT          NOT NULL REFERENCES rutas(id),
    horario_turno   VARCHAR(20)  NOT NULL,
    hora_inicio_est TIME         NOT NULL,
    hora_fin_est    TIME         NOT NULL,
    poligono        GEOGRAPHY(POLYGON, 4326),
    created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_colonias_ruta ON colonias (ruta_id);
CREATE INDEX idx_colonias_pol  ON colonias USING GIST (poligono) WHERE poligono IS NOT NULL;

-- ----------------------------------------------------------------
-- 5. DOMICILIOS
-- ----------------------------------------------------------------
CREATE TABLE domicilios (
    id              UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         UUID         NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    alias           VARCHAR(50)  NOT NULL,
    direccion_texto TEXT         NOT NULL,
    lat             DECIMAL(9,6) NOT NULL,
    lng             DECIMAL(9,6) NOT NULL,
    coordenada      GEOGRAPHY(POINT, 4326) NOT NULL,
    colonia_id      INT          REFERENCES colonias(id) ON DELETE SET NULL,
    validado        BOOLEAN      NOT NULL DEFAULT FALSE,
    created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    CONSTRAINT uq_domicilio_alias UNIQUE (user_id, alias)
);

CREATE INDEX idx_domicilios_user  ON domicilios (user_id);
CREATE INDEX idx_domicilios_col   ON domicilios (colonia_id);
CREATE INDEX idx_domicilios_coord ON domicilios USING GIST (coordenada);

-- ----------------------------------------------------------------
-- 6. ESTADO_RUTA  (actualizado por el simulador/cron)
-- ----------------------------------------------------------------
CREATE TABLE estado_ruta (
    ruta_id            INT         PRIMARY KEY REFERENCES rutas(id) ON DELETE CASCADE,
    estado             VARCHAR(20) NOT NULL DEFAULT 'INACTIVA',
    position_id_actual SMALLINT    NOT NULL DEFAULT 1,
    lat_actual         DECIMAL(9,6),
    lng_actual         DECIMAL(9,6),
    hora_real_inicio   TIMESTAMPTZ,
    hora_estim_fin     TIMESTAMPTZ,
    minutos_retraso    SMALLINT    NOT NULL DEFAULT 0,
    motivo_retraso     TEXT,
    actualizado_at     TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ----------------------------------------------------------------
-- 7. NOTIFICACION_TEMPLATES
-- ----------------------------------------------------------------
CREATE TABLE notificacion_templates (
    id                  SERIAL       PRIMARY KEY,
    trigger_event       VARCHAR(30)  NOT NULL UNIQUE,
    position_id_trigger SMALLINT     NOT NULL,
    titulo              VARCHAR(150) NOT NULL,
    cuerpo              TEXT         NOT NULL,
    activo              BOOLEAN      NOT NULL DEFAULT TRUE,
    created_at          TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- ----------------------------------------------------------------
-- 8. NOTIFICACIONES
-- ----------------------------------------------------------------
CREATE TABLE notificaciones (
    id           UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id      UUID         NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    domicilio_id UUID         REFERENCES domicilios(id) ON DELETE SET NULL,
    template_id  INT          REFERENCES notificacion_templates(id),
    ruta_id      INT          REFERENCES rutas(id),
    titulo       VARCHAR(150) NOT NULL,
    mensaje      TEXT         NOT NULL,
    enviada_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    leida        BOOLEAN      NOT NULL DEFAULT FALSE,
    leida_at     TIMESTAMPTZ
);

CREATE INDEX idx_notif_user     ON notificaciones (user_id, enviada_at DESC);
CREATE INDEX idx_notif_no_leida ON notificaciones (user_id) WHERE leida = FALSE;

-- ----------------------------------------------------------------
-- 9. REPORTES
-- ----------------------------------------------------------------
CREATE TABLE reportes (
    id           UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id      UUID        NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    domicilio_id UUID        REFERENCES domicilios(id) ON DELETE SET NULL,
    ruta_id      INT         REFERENCES rutas(id),
    tipo         VARCHAR(40) NOT NULL,
    descripcion  TEXT,
    calificacion SMALLINT    CHECK (calificacion BETWEEN 1 AND 5),
    estado       VARCHAR(20) NOT NULL DEFAULT 'abierto',
    creado_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_reportes_user ON reportes (user_id);
CREATE INDEX idx_reportes_ruta ON reportes (ruta_id, creado_at);

-- ----------------------------------------------------------------
-- 10. GUÍA DE SEPARACIÓN
-- ----------------------------------------------------------------
CREATE TABLE residuos_categorias (
    id          SERIAL      PRIMARY KEY,
    nombre      VARCHAR(50) NOT NULL,
    descripcion TEXT,
    color_hex   CHAR(7),
    icono       VARCHAR(100)
);

CREATE TABLE residuos_ejemplos (
    id           SERIAL       PRIMARY KEY,
    categoria_id INT          NOT NULL REFERENCES residuos_categorias(id) ON DELETE CASCADE,
    nombre       VARCHAR(255) NOT NULL,
    descripcion  TEXT
);

-- ----------------------------------------------------------------
-- TRIGGERS
-- ----------------------------------------------------------------
CREATE OR REPLACE FUNCTION fn_set_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$;

CREATE TRIGGER trg_users_updated_at
    BEFORE UPDATE ON users
    FOR EACH ROW EXECUTE FUNCTION fn_set_updated_at();
