CREATE SCHEMA IF NOT EXISTS mv_hot;

CREATE TABLE IF NOT EXISTS mv_hot.edge_oee_stop_causes (
    cause_code TEXT PRIMARY KEY,
    cause_name TEXT NOT NULL,
    description TEXT,
    is_planned BOOLEAN NOT NULL DEFAULT false,
    is_active BOOLEAN NOT NULL DEFAULT true,
    sort_order INT NOT NULL DEFAULT 100
);

INSERT INTO mv_hot.edge_oee_stop_causes
(cause_code, cause_name, description, is_planned, sort_order)
VALUES
('cambio_bobina', 'Cambio de bobina', 'Paro por cambio de bobina o material.', false, 10),
('fallo_empalme', 'Fallo en empalme', 'Paro por fallo o ajuste en empalme de material.', false, 20),
('ajuste_sellado', 'Ajuste de sellado', 'Paro por ajuste de mordazas, temperatura, presión o teflón.', false, 30),
('falta_material', 'Falta de material', 'Paro por ausencia de bobina, material no preparado o espera logística.', false, 40),
('limpieza_fotocelula', 'Limpieza fotocélula', 'Paro por limpieza o ajuste de sensor/fotocélula.', false, 50),
('cambio_formato', 'Cambio de formato', 'Paro por cambio de medidas, producto o configuración.', false, 60),
('averia_mecanica', 'Avería mecánica', 'Paro por fallo mecánico de la máquina.', false, 70),
('espera_instrucciones', 'Espera de instrucciones', 'Paro por falta de definición, autorización o instrucción.', false, 80),
('pausa_cafe', 'Pausa café', 'Pausa del operario o descanso.', true, 90),
('otro', 'Otro', 'Causa no clasificada en el catálogo principal.', false, 999)
ON CONFLICT (cause_code) DO UPDATE SET
    cause_name = EXCLUDED.cause_name,
    description = EXCLUDED.description,
    is_planned = EXCLUDED.is_planned,
    sort_order = EXCLUDED.sort_order;

CREATE TABLE IF NOT EXISTS mv_hot.edge_oee_machine_stops (
    id BIGSERIAL PRIMARY KEY,

    tenant TEXT NOT NULL,
    site TEXT NOT NULL,
    vertical TEXT NOT NULL,
    asset TEXT NOT NULL,

    machine_id TEXT,
    order_id TEXT,

    started_at TIMESTAMPTZ NOT NULL,
    ended_at TIMESTAMPTZ,

    status TEXT NOT NULL DEFAULT 'OPEN',
    classification_status TEXT NOT NULL DEFAULT 'PENDING',

    cause_code TEXT REFERENCES mv_hot.edge_oee_stop_causes(cause_code),
    operator_note TEXT,

    value_hour_eur NUMERIC(10,2) NOT NULL DEFAULT 36.00,
    duration_s NUMERIC(14,2),
    cost_eur NUMERIC(14,2),

    start_event_name TEXT,
    end_event_name TEXT,

    start_payload_json JSONB NOT NULL DEFAULT '{}'::jsonb,
    end_payload_json JSONB NOT NULL DEFAULT '{}'::jsonb,

    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_edge_oee_machine_stops_asset_status
ON mv_hot.edge_oee_machine_stops(asset, status);

CREATE INDEX IF NOT EXISTS idx_edge_oee_machine_stops_started_at
ON mv_hot.edge_oee_machine_stops(started_at DESC);

CREATE INDEX IF NOT EXISTS idx_edge_oee_machine_stops_machine_started
ON mv_hot.edge_oee_machine_stops(machine_id, started_at DESC);

CREATE OR REPLACE VIEW mv_hot.edge_oee_open_stops AS
SELECT
    s.id,
    s.tenant,
    s.site,
    s.vertical,
    s.asset,
    s.machine_id,
    s.order_id,
    s.started_at,
    EXTRACT(EPOCH FROM (now() - s.started_at))::numeric(14,2) AS current_duration_s,
    ROUND((EXTRACT(EPOCH FROM (now() - s.started_at)) / 60.0)::numeric, 2) AS current_duration_min,
    ROUND(((EXTRACT(EPOCH FROM (now() - s.started_at)) / 3600.0) * s.value_hour_eur)::numeric, 2) AS current_cost_eur,
    s.status,
    s.classification_status,
    s.cause_code,
    c.cause_name,
    s.operator_note,
    s.value_hour_eur
FROM mv_hot.edge_oee_machine_stops s
LEFT JOIN mv_hot.edge_oee_stop_causes c ON c.cause_code = s.cause_code
WHERE s.status = 'OPEN'
ORDER BY s.started_at DESC;

CREATE OR REPLACE VIEW mv_hot.edge_oee_stops_recent AS
SELECT
    s.id,
    s.tenant,
    s.site,
    s.vertical,
    s.asset,
    s.machine_id,
    s.order_id,
    s.started_at,
    s.ended_at,
    COALESCE(
        s.duration_s,
        EXTRACT(EPOCH FROM (now() - s.started_at))::numeric(14,2)
    ) AS duration_s,
    ROUND((
        COALESCE(s.duration_s, EXTRACT(EPOCH FROM (now() - s.started_at))::numeric) / 60.0
    )::numeric, 2) AS duration_min,
    COALESCE(
        s.cost_eur,
        ROUND(((EXTRACT(EPOCH FROM (now() - s.started_at)) / 3600.0) * s.value_hour_eur)::numeric, 2)
    ) AS cost_eur,
    s.status,
    s.classification_status,
    s.cause_code,
    c.cause_name,
    c.is_planned,
    s.operator_note,
    s.value_hour_eur,
    s.start_event_name,
    s.end_event_name,
    s.created_at,
    s.updated_at
FROM mv_hot.edge_oee_machine_stops s
LEFT JOIN mv_hot.edge_oee_stop_causes c ON c.cause_code = s.cause_code
ORDER BY s.started_at DESC;

CREATE OR REPLACE VIEW mv_hot.edge_oee_stop_summary_demo AS
SELECT
    COALESCE(c.cause_name, 'Pendiente de clasificar') AS cause_name,
    COALESCE(s.cause_code, 'pending') AS cause_code,
    COUNT(*) AS stop_count,
    ROUND(SUM(COALESCE(s.duration_s, EXTRACT(EPOCH FROM (now() - s.started_at))::numeric)) / 60.0, 2) AS total_min,
    ROUND(SUM(COALESCE(s.cost_eur, ((EXTRACT(EPOCH FROM (now() - s.started_at)) / 3600.0) * s.value_hour_eur)))::numeric, 2) AS total_cost_eur
FROM mv_hot.edge_oee_machine_stops s
LEFT JOIN mv_hot.edge_oee_stop_causes c ON c.cause_code = s.cause_code
GROUP BY COALESCE(c.cause_name, 'Pendiente de clasificar'), COALESCE(s.cause_code, 'pending')
ORDER BY total_cost_eur DESC;

CREATE OR REPLACE VIEW mv_hot.edge_oee_stop_cause_options AS
SELECT
    cause_code,
    cause_name,
    description,
    is_planned,
    sort_order
FROM mv_hot.edge_oee_stop_causes
WHERE is_active = true
ORDER BY sort_order, cause_name;
