-- ============================================================================
-- DENTAL SCHEMA - Especialización de ERP-Clínicas
-- Clínica Dental
-- ============================================================================
-- Fecha: 2026-01-04
-- Versión: 1.0
-- Hereda de: erp-clinicas FASE-8
-- ============================================================================

-- Schema
CREATE SCHEMA IF NOT EXISTS dental;

-- ============================================================================
-- ENUMS
-- ============================================================================

DO $$ BEGIN
    CREATE TYPE dental.estado_pieza AS ENUM (
        'sano', 'caries', 'obturacion', 'endodoncia', 'corona',
        'puente', 'implante', 'ausente', 'extraccion_indicada',
        'diente_temporal', 'fractura', 'movilidad'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
    CREATE TYPE dental.cara_dental AS ENUM (
        'mesial', 'distal', 'oclusal', 'incisal',
        'vestibular', 'bucal', 'lingual', 'palatino'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
    CREATE TYPE dental.estado_tratamiento AS ENUM (
        'pendiente', 'en_proceso', 'completado', 'cancelado'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
    CREATE TYPE dental.tipo_ortodoncia AS ENUM (
        'brackets_metalicos', 'brackets_esteticos', 'brackets_linguales',
        'alineadores', 'removible', 'retenedor'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- ============================================================================
-- CATÁLOGOS
-- ============================================================================

-- Piezas dentales
CREATE TABLE IF NOT EXISTS dental.piezas_dentales (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    numero VARCHAR(10) NOT NULL UNIQUE, -- '11', '12', ... '48', '51'...'85'
    nombre VARCHAR(50) NOT NULL,
    cuadrante INTEGER NOT NULL CHECK (cuadrante BETWEEN 1 AND 8),
    es_temporal BOOLEAN DEFAULT false,
    descripcion TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.piezas_dentales IS 'Catálogo de piezas dentales (nomenclatura FDI)';

-- Tratamientos dentales
CREATE TABLE IF NOT EXISTS dental.tratamientos_catalogo (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    codigo VARCHAR(20) NOT NULL,
    nombre VARCHAR(100) NOT NULL,
    categoria VARCHAR(50), -- 'prevencion', 'restauracion', 'endodoncia', etc.
    descripcion TEXT,
    duracion_minutos INTEGER DEFAULT 30,
    precio_base NUMERIC(10,2),
    requiere_rx BOOLEAN DEFAULT false,
    requiere_anestesia BOOLEAN DEFAULT false,
    active BOOLEAN DEFAULT true,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    CONSTRAINT uq_tratamientos_tenant_codigo UNIQUE(tenant_id, codigo)
);

COMMENT ON TABLE dental.tratamientos_catalogo IS 'Catálogo de tratamientos dentales';

-- ============================================================================
-- TABLAS PRINCIPALES
-- ============================================================================

-- Odontograma
CREATE TABLE IF NOT EXISTS dental.odontogramas (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    patient_id UUID NOT NULL, -- Referencia a clinica.patients
    fecha_creacion DATE NOT NULL DEFAULT CURRENT_DATE,
    fecha_actualizacion DATE,
    notas TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.odontogramas IS 'Odontogramas de pacientes';

-- Estado de piezas dentales por odontograma
CREATE TABLE IF NOT EXISTS dental.odontograma_piezas (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    odontograma_id UUID NOT NULL REFERENCES dental.odontogramas(id) ON DELETE CASCADE,
    pieza_id UUID NOT NULL REFERENCES dental.piezas_dentales(id),
    -- Estado general
    estado dental.estado_pieza DEFAULT 'sano',
    -- Estados por cara (JSONB para flexibilidad)
    caras_afectadas JSONB, -- {"mesial": "caries", "oclusal": "obturacion"}
    -- Notas
    observaciones TEXT,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    CONSTRAINT uq_odontograma_pieza UNIQUE(odontograma_id, pieza_id)
);

COMMENT ON TABLE dental.odontograma_piezas IS 'Estado de cada pieza dental en el odontograma';

-- Tratamientos de paciente
CREATE TABLE IF NOT EXISTS dental.tratamientos_paciente (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    patient_id UUID NOT NULL,
    odontograma_id UUID REFERENCES dental.odontogramas(id),
    tratamiento_id UUID REFERENCES dental.tratamientos_catalogo(id),
    odontologo_id UUID, -- Referencia a clinica.doctors
    consultation_id UUID, -- Referencia a clinica.consultations
    -- Pieza(s) tratada(s)
    pieza_id UUID REFERENCES dental.piezas_dentales(id),
    caras_tratadas dental.cara_dental[],
    -- Datos del tratamiento
    fecha_inicio DATE NOT NULL DEFAULT CURRENT_DATE,
    fecha_fin DATE,
    estado dental.estado_tratamiento DEFAULT 'pendiente',
    -- Costo
    precio NUMERIC(10,2),
    descuento NUMERIC(5,2) DEFAULT 0,
    precio_final NUMERIC(10,2),
    -- Notas
    notas TEXT,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.tratamientos_paciente IS 'Tratamientos realizados a pacientes';

-- Ortodoncia
CREATE TABLE IF NOT EXISTS dental.ortodoncia (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    patient_id UUID NOT NULL,
    odontologo_id UUID,
    -- Tipo de tratamiento
    tipo dental.tipo_ortodoncia NOT NULL,
    marca VARCHAR(100),
    -- Fechas
    fecha_inicio DATE NOT NULL,
    fecha_estimada_fin DATE,
    fecha_real_fin DATE,
    -- Estado
    estado dental.estado_tratamiento DEFAULT 'en_proceso',
    meses_estimados INTEGER,
    -- Costo
    costo_total NUMERIC(10,2),
    enganche NUMERIC(10,2),
    mensualidad NUMERIC(10,2),
    -- Notas
    notas TEXT,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.ortodoncia IS 'Tratamientos de ortodoncia';

-- Citas de ortodoncia (seguimiento)
CREATE TABLE IF NOT EXISTS dental.ortodoncia_citas (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    ortodoncia_id UUID NOT NULL REFERENCES dental.ortodoncia(id) ON DELETE CASCADE,
    appointment_id UUID, -- Referencia a clinica.appointments
    -- Datos de la cita
    fecha DATE NOT NULL,
    numero_cita INTEGER,
    -- Procedimiento
    procedimiento TEXT,
    arco_superior VARCHAR(50),
    arco_inferior VARCHAR(50),
    ligas VARCHAR(50),
    -- Observaciones
    observaciones TEXT,
    proxima_cita DATE,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.ortodoncia_citas IS 'Citas de seguimiento de ortodoncia';

-- Prótesis
CREATE TABLE IF NOT EXISTS dental.protesis (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    patient_id UUID NOT NULL,
    odontologo_id UUID,
    -- Tipo
    tipo VARCHAR(50) NOT NULL, -- 'corona', 'puente', 'parcial', 'total', 'implante'
    -- Piezas involucradas
    piezas_involucradas TEXT[], -- ['11', '12', '13']
    -- Laboratorio
    laboratorio_id UUID, -- Referencia a proveedor
    fecha_envio_lab DATE,
    fecha_recepcion_lab DATE,
    -- Material
    material VARCHAR(100),
    color VARCHAR(50),
    -- Estado
    estado dental.estado_tratamiento DEFAULT 'en_proceso',
    fecha_colocacion DATE,
    -- Garantía
    tiene_garantia BOOLEAN DEFAULT false,
    meses_garantia INTEGER,
    -- Costo
    costo_laboratorio NUMERIC(10,2),
    precio_paciente NUMERIC(10,2),
    -- Notas
    notas TEXT,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.protesis IS 'Registro de prótesis dentales';

-- Radiografías
CREATE TABLE IF NOT EXISTS dental.radiografias (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    patient_id UUID NOT NULL,
    consultation_id UUID,
    -- Tipo
    tipo VARCHAR(50) NOT NULL, -- 'periapical', 'panoramica', 'cefalometrica', 'oclusal'
    pieza_id UUID REFERENCES dental.piezas_dentales(id),
    -- Archivo
    fecha DATE NOT NULL DEFAULT CURRENT_DATE,
    url_imagen VARCHAR(255),
    -- Interpretación
    interpretacion TEXT,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.radiografias IS 'Registro de radiografías dentales';

-- Presupuestos
CREATE TABLE IF NOT EXISTS dental.presupuestos (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    patient_id UUID NOT NULL,
    odontologo_id UUID,
    -- Datos
    numero VARCHAR(20),
    fecha DATE NOT NULL DEFAULT CURRENT_DATE,
    fecha_vencimiento DATE,
    -- Estado
    estado VARCHAR(20) DEFAULT 'pendiente', -- 'pendiente', 'aprobado', 'rechazado', 'vencido'
    -- Totales
    subtotal NUMERIC(12,2) DEFAULT 0,
    descuento_porcentaje NUMERIC(5,2) DEFAULT 0,
    descuento_monto NUMERIC(12,2) DEFAULT 0,
    total NUMERIC(12,2) DEFAULT 0,
    -- Plan de pago
    requiere_financiamiento BOOLEAN DEFAULT false,
    enganche NUMERIC(12,2),
    numero_pagos INTEGER,
    monto_pago NUMERIC(12,2),
    -- Notas
    notas TEXT,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.presupuestos IS 'Presupuestos de tratamiento';

-- Líneas de presupuesto
CREATE TABLE IF NOT EXISTS dental.presupuesto_lineas (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    presupuesto_id UUID NOT NULL REFERENCES dental.presupuestos(id) ON DELETE CASCADE,
    tratamiento_id UUID REFERENCES dental.tratamientos_catalogo(id),
    -- Pieza
    pieza_id UUID REFERENCES dental.piezas_dentales(id),
    descripcion TEXT,
    -- Cantidades
    cantidad INTEGER DEFAULT 1,
    precio_unitario NUMERIC(10,2),
    descuento NUMERIC(5,2) DEFAULT 0,
    subtotal NUMERIC(10,2),
    -- Secuencia
    sequence INTEGER DEFAULT 10,
    -- Control
    created_at TIMESTAMPTZ DEFAULT NOW()
);

COMMENT ON TABLE dental.presupuesto_lineas IS 'Líneas de presupuesto';

-- ============================================================================
-- EXTENSIONES A TABLAS DE ERP-CLINICAS
-- ============================================================================

DO $$
BEGIN
    -- Extensión a clinica.patients
    IF EXISTS (SELECT 1 FROM information_schema.tables
               WHERE table_schema = 'clinica' AND table_name = 'patients') THEN

        IF NOT EXISTS (SELECT 1 FROM information_schema.columns
                       WHERE table_schema = 'clinica' AND table_name = 'patients'
                       AND column_name = 'odontograma_activo_id') THEN
            ALTER TABLE clinica.patients ADD COLUMN odontograma_activo_id UUID;
        END IF;

        IF NOT EXISTS (SELECT 1 FROM information_schema.columns
                       WHERE table_schema = 'clinica' AND table_name = 'patients'
                       AND column_name = 'tiene_ortodoncia') THEN
            ALTER TABLE clinica.patients ADD COLUMN tiene_ortodoncia BOOLEAN DEFAULT false;
        END IF;

        IF NOT EXISTS (SELECT 1 FROM information_schema.columns
                       WHERE table_schema = 'clinica' AND table_name = 'patients'
                       AND column_name = 'tiene_protesis') THEN
            ALTER TABLE clinica.patients ADD COLUMN tiene_protesis BOOLEAN DEFAULT false;
        END IF;

    END IF;
END $$;

-- ============================================================================
-- SEED: Piezas dentales (catálogo global)
-- ============================================================================

INSERT INTO dental.piezas_dentales (numero, nombre, cuadrante, es_temporal) VALUES
-- Cuadrante 1 - Superior derecho (permanentes)
('18', 'Tercer molar superior derecho', 1, false),
('17', 'Segundo molar superior derecho', 1, false),
('16', 'Primer molar superior derecho', 1, false),
('15', 'Segundo premolar superior derecho', 1, false),
('14', 'Primer premolar superior derecho', 1, false),
('13', 'Canino superior derecho', 1, false),
('12', 'Incisivo lateral superior derecho', 1, false),
('11', 'Incisivo central superior derecho', 1, false),
-- Cuadrante 2 - Superior izquierdo (permanentes)
('21', 'Incisivo central superior izquierdo', 2, false),
('22', 'Incisivo lateral superior izquierdo', 2, false),
('23', 'Canino superior izquierdo', 2, false),
('24', 'Primer premolar superior izquierdo', 2, false),
('25', 'Segundo premolar superior izquierdo', 2, false),
('26', 'Primer molar superior izquierdo', 2, false),
('27', 'Segundo molar superior izquierdo', 2, false),
('28', 'Tercer molar superior izquierdo', 2, false),
-- Cuadrante 3 - Inferior izquierdo (permanentes)
('31', 'Incisivo central inferior izquierdo', 3, false),
('32', 'Incisivo lateral inferior izquierdo', 3, false),
('33', 'Canino inferior izquierdo', 3, false),
('34', 'Primer premolar inferior izquierdo', 3, false),
('35', 'Segundo premolar inferior izquierdo', 3, false),
('36', 'Primer molar inferior izquierdo', 3, false),
('37', 'Segundo molar inferior izquierdo', 3, false),
('38', 'Tercer molar inferior izquierdo', 3, false),
-- Cuadrante 4 - Inferior derecho (permanentes)
('41', 'Incisivo central inferior derecho', 4, false),
('42', 'Incisivo lateral inferior derecho', 4, false),
('43', 'Canino inferior derecho', 4, false),
('44', 'Primer premolar inferior derecho', 4, false),
('45', 'Segundo premolar inferior derecho', 4, false),
('46', 'Primer molar inferior derecho', 4, false),
('47', 'Segundo molar inferior derecho', 4, false),
('48', 'Tercer molar inferior derecho', 4, false),
-- Cuadrante 5 - Superior derecho (temporales)
('55', 'Segundo molar temporal superior derecho', 5, true),
('54', 'Primer molar temporal superior derecho', 5, true),
('53', 'Canino temporal superior derecho', 5, true),
('52', 'Incisivo lateral temporal superior derecho', 5, true),
('51', 'Incisivo central temporal superior derecho', 5, true),
-- Cuadrante 6 - Superior izquierdo (temporales)
('61', 'Incisivo central temporal superior izquierdo', 6, true),
('62', 'Incisivo lateral temporal superior izquierdo', 6, true),
('63', 'Canino temporal superior izquierdo', 6, true),
('64', 'Primer molar temporal superior izquierdo', 6, true),
('65', 'Segundo molar temporal superior izquierdo', 6, true),
-- Cuadrante 7 - Inferior izquierdo (temporales)
('71', 'Incisivo central temporal inferior izquierdo', 7, true),
('72', 'Incisivo lateral temporal inferior izquierdo', 7, true),
('73', 'Canino temporal inferior izquierdo', 7, true),
('74', 'Primer molar temporal inferior izquierdo', 7, true),
('75', 'Segundo molar temporal inferior izquierdo', 7, true),
-- Cuadrante 8 - Inferior derecho (temporales)
('81', 'Incisivo central temporal inferior derecho', 8, true),
('82', 'Incisivo lateral temporal inferior derecho', 8, true),
('83', 'Canino temporal inferior derecho', 8, true),
('84', 'Primer molar temporal inferior derecho', 8, true),
('85', 'Segundo molar temporal inferior derecho', 8, true)
ON CONFLICT (numero) DO NOTHING;

-- ============================================================================
-- ÍNDICES
-- ============================================================================

CREATE INDEX IF NOT EXISTS idx_tratamientos_catalogo_tenant ON dental.tratamientos_catalogo(tenant_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_catalogo_categoria ON dental.tratamientos_catalogo(tenant_id, categoria);

CREATE INDEX IF NOT EXISTS idx_odontogramas_tenant ON dental.odontogramas(tenant_id);
CREATE INDEX IF NOT EXISTS idx_odontogramas_patient ON dental.odontogramas(patient_id);

CREATE INDEX IF NOT EXISTS idx_odontograma_piezas_odontograma ON dental.odontograma_piezas(odontograma_id);
CREATE INDEX IF NOT EXISTS idx_odontograma_piezas_pieza ON dental.odontograma_piezas(pieza_id);

CREATE INDEX IF NOT EXISTS idx_tratamientos_paciente_tenant ON dental.tratamientos_paciente(tenant_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_paciente_patient ON dental.tratamientos_paciente(patient_id);
CREATE INDEX IF NOT EXISTS idx_tratamientos_paciente_estado ON dental.tratamientos_paciente(tenant_id, estado);

CREATE INDEX IF NOT EXISTS idx_ortodoncia_tenant ON dental.ortodoncia(tenant_id);
CREATE INDEX IF NOT EXISTS idx_ortodoncia_patient ON dental.ortodoncia(patient_id);
CREATE INDEX IF NOT EXISTS idx_ortodoncia_estado ON dental.ortodoncia(tenant_id, estado);

CREATE INDEX IF NOT EXISTS idx_ortodoncia_citas_ortodoncia ON dental.ortodoncia_citas(ortodoncia_id);

CREATE INDEX IF NOT EXISTS idx_protesis_tenant ON dental.protesis(tenant_id);
CREATE INDEX IF NOT EXISTS idx_protesis_patient ON dental.protesis(patient_id);

CREATE INDEX IF NOT EXISTS idx_radiografias_tenant ON dental.radiografias(tenant_id);
CREATE INDEX IF NOT EXISTS idx_radiografias_patient ON dental.radiografias(patient_id);

CREATE INDEX IF NOT EXISTS idx_presupuestos_tenant ON dental.presupuestos(tenant_id);
CREATE INDEX IF NOT EXISTS idx_presupuestos_patient ON dental.presupuestos(patient_id);
CREATE INDEX IF NOT EXISTS idx_presupuestos_estado ON dental.presupuestos(tenant_id, estado);

CREATE INDEX IF NOT EXISTS idx_presupuesto_lineas_presupuesto ON dental.presupuesto_lineas(presupuesto_id);

-- ============================================================================
-- RLS
-- ============================================================================

ALTER TABLE dental.tratamientos_catalogo ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.odontogramas ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.odontograma_piezas ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.tratamientos_paciente ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.ortodoncia ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.ortodoncia_citas ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.protesis ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.radiografias ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.presupuestos ENABLE ROW LEVEL SECURITY;
ALTER TABLE dental.presupuesto_lineas ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS tenant_isolation_tratamientos_cat ON dental.tratamientos_catalogo;
CREATE POLICY tenant_isolation_tratamientos_cat ON dental.tratamientos_catalogo
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_odontogramas ON dental.odontogramas;
CREATE POLICY tenant_isolation_odontogramas ON dental.odontogramas
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_odontograma_piezas ON dental.odontograma_piezas;
CREATE POLICY tenant_isolation_odontograma_piezas ON dental.odontograma_piezas
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_tratamientos_pac ON dental.tratamientos_paciente;
CREATE POLICY tenant_isolation_tratamientos_pac ON dental.tratamientos_paciente
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_ortodoncia ON dental.ortodoncia;
CREATE POLICY tenant_isolation_ortodoncia ON dental.ortodoncia
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_ortodoncia_citas ON dental.ortodoncia_citas;
CREATE POLICY tenant_isolation_ortodoncia_citas ON dental.ortodoncia_citas
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_protesis ON dental.protesis;
CREATE POLICY tenant_isolation_protesis ON dental.protesis
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_radiografias ON dental.radiografias;
CREATE POLICY tenant_isolation_radiografias ON dental.radiografias
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_presupuestos ON dental.presupuestos;
CREATE POLICY tenant_isolation_presupuestos ON dental.presupuestos
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

DROP POLICY IF EXISTS tenant_isolation_presupuesto_lineas ON dental.presupuesto_lineas;
CREATE POLICY tenant_isolation_presupuesto_lineas ON dental.presupuesto_lineas
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- ============================================================================
-- FIN DENTAL SCHEMA
-- ============================================================================
