-- Migration: 001_initial_schema
-- Description: Full initial DDL for tenant databases (horux_<rfc>)
-- Created: 2026-04-13
-- Tables: rfcs, bancos, cfdis, cfdi_conceptos, conciliaciones, alertas, recordatorios

-- Extensions
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- Tables

CREATE TABLE IF NOT EXISTS rfcs (
  id SERIAL PRIMARY KEY,
  rfc VARCHAR(14) UNIQUE NOT NULL,
  razon_social VARCHAR(255),
  regimen_fiscal VARCHAR(3),
  codigo_postal VARCHAR(5)
);

CREATE TABLE IF NOT EXISTS bancos (
  id SERIAL PRIMARY KEY,
  banco VARCHAR(100) NOT NULL,
  terminacion_cuenta VARCHAR(4) NOT NULL,
  creado_en TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS cfdis (
  id SERIAL PRIMARY KEY,
  year VARCHAR(4),
  month VARCHAR(2),
  type VARCHAR(10),
  uuid VARCHAR(36) UNIQUE,
  serie VARCHAR(50),
  folio VARCHAR(50),
  status VARCHAR(20),
  fecha_emision TIMESTAMP,
  rfc_emisor_id INTEGER REFERENCES rfcs(id),
  rfc_emisor VARCHAR(13),
  nombre_emisor VARCHAR(255),
  rfc_receptor_id INTEGER REFERENCES rfcs(id),
  rfc_receptor VARCHAR(13),
  nombre_receptor VARCHAR(255),
  subtotal NUMERIC(18,4),
  subtotal_mxn NUMERIC(18,4),
  descuento NUMERIC(18,4),
  descuento_mxn NUMERIC(18,4),
  total NUMERIC(18,4),
  total_mxn NUMERIC(18,4),
  saldo_insoluto TEXT,
  moneda VARCHAR(3),
  tipo_cambio NUMERIC(18,6),
  tipo_comprobante VARCHAR(1),
  metodo_pago VARCHAR(3),
  forma_pago VARCHAR(2),
  uso_cfdi VARCHAR(5),
  pac VARCHAR(13),
  fecha_cert_sat TIMESTAMP,
  fecha_cancelacion TIMESTAMP,
  uuid_relacionado TEXT,
  isr_retencion NUMERIC(18,4),
  isr_retencion_mxn NUMERIC(18,4),
  iva_traslado NUMERIC(18,4),
  iva_traslado_mxn NUMERIC(18,4),
  iva_retencion NUMERIC(18,4),
  iva_retencion_mxn NUMERIC(18,4),
  ieps_traslado NUMERIC(18,4),
  ieps_traslado_mxn NUMERIC(18,4),
  ieps_retencion NUMERIC(18,4),
  ieps_retencion_mxn NUMERIC(18,4),
  impuestos_locales_trasladado NUMERIC(18,4),
  impuestos_locales_trasladado_mxn NUMERIC(18,4),
  impuestos_locales_retenidos NUMERIC(18,4),
  impuestos_locales_retenidos_mxn NUMERIC(18,4),
  monto_pago NUMERIC(18,4),
  monto_pago_mxn NUMERIC(18,4),
  fecha_pago_p TIMESTAMP,
  num_parcialidad TEXT,
  isr_retencion_pago NUMERIC(18,4),
  isr_retencion_pago_mxn NUMERIC(18,4),
  iva_traslado_pago NUMERIC(18,4),
  iva_traslado_pago_mxn NUMERIC(18,4),
  iva_retencion_pago NUMERIC(18,4),
  iva_retencion_pago_mxn NUMERIC(18,4),
  ieps_traslado_pago NUMERIC(18,4),
  ieps_traslado_pago_mxn NUMERIC(18,4),
  ieps_retencion_pago NUMERIC(18,4),
  ieps_retencion_pago_mxn NUMERIC(18,4),
  saldo_pendiente NUMERIC(18,4),
  saldo_pendiente_mxn NUMERIC(18,4),
  fecha_liquidacion TIMESTAMP,
  fecha_pago DATE,
  fecha_inicial_pago DATE,
  fecha_final_pago DATE,
  num_dias_pagados NUMERIC(10,2),
  num_seguro_social VARCHAR(50),
  puesto VARCHAR(255),
  salario_base_cot_apor NUMERIC(18,4),
  salario_base_cot_apor_mxn NUMERIC(18,4),
  salario_diario_integrado NUMERIC(18,4),
  salario_diario_integrado_mxn NUMERIC(18,4),
  total_percepciones NUMERIC(18,4),
  total_percepciones_mxn NUMERIC(18,4),
  total_deducciones NUMERIC(18,4),
  total_deducciones_mxn NUMERIC(18,4),
  imp_retenidos_nomina NUMERIC(18,4),
  imp_retenidos_nomina_mxn NUMERIC(18,4),
  otras_deducciones_nomina NUMERIC(18,4),
  otras_deducciones_nomina_mxn NUMERIC(18,4),
  subsidio_causado NUMERIC(18,4),
  subsidio_causado_mxn NUMERIC(18,4),
  conciliado VARCHAR(50),
  id_conciliacion INTEGER,
  xml_url TEXT,
  pdf_url TEXT,
  xml_original TEXT,
  last_sat_sync TIMESTAMP,
  sat_sync_job_id UUID,
  source VARCHAR(20) DEFAULT 'manual',
  facturapi_id VARCHAR(50),
  regimen_fiscal_emisor VARCHAR(3),
  regimen_fiscal_receptor VARCHAR(3),
  creado_en TIMESTAMP DEFAULT NOW(),
  actualizado_en TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS cfdi_conceptos (
  id SERIAL PRIMARY KEY,
  cfdi_id INTEGER REFERENCES cfdis(id) ON DELETE CASCADE,
  clave_prod_serv VARCHAR(10),
  no_identificacion VARCHAR(100),
  descripcion TEXT,
  cantidad NUMERIC(18,4),
  clave_unidad VARCHAR(10),
  unidad VARCHAR(100),
  valor_unitario NUMERIC(18,4),
  valor_unitario_mxn NUMERIC(18,4),
  importe NUMERIC(18,4),
  importe_mxn NUMERIC(18,4),
  descuento NUMERIC(18,4),
  descuento_mxn NUMERIC(18,4),
  isr_retencion NUMERIC(18,4),
  isr_retencion_mxn NUMERIC(18,4),
  iva_traslado NUMERIC(18,4),
  iva_traslado_mxn NUMERIC(18,4),
  iva_retencion NUMERIC(18,4),
  iva_retencion_mxn NUMERIC(18,4),
  ieps_traslado NUMERIC(18,4),
  ieps_traslado_mxn NUMERIC(18,4),
  ieps_retencion NUMERIC(18,4),
  ieps_retencion_mxn NUMERIC(18,4),
  impuestos_locales_trasladado NUMERIC(18,4),
  impuestos_locales_trasladado_mxn NUMERIC(18,4),
  impuestos_locales_retenidos NUMERIC(18,4),
  impuestos_locales_retenidos_mxn NUMERIC(18,4),
  total_percepciones NUMERIC(18,4),
  total_percepciones_mxn NUMERIC(18,4),
  total_deducciones NUMERIC(18,4),
  total_deducciones_mxn NUMERIC(18,4),
  imp_retenidos_nomina NUMERIC(18,4),
  imp_retenidos_nomina_mxn NUMERIC(18,4),
  otras_deducciones_nomina NUMERIC(18,4),
  otras_deducciones_nomina_mxn NUMERIC(18,4),
  subsidio_causado NUMERIC(18,4),
  subsidio_causado_mxn NUMERIC(18,4),
  creado_en TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS conciliaciones (
  id SERIAL PRIMARY KEY,
  anio VARCHAR(4) NOT NULL,
  mes VARCHAR(2) NOT NULL,
  id_cfdi INTEGER NOT NULL UNIQUE REFERENCES cfdis(id),
  fecha_de_pago DATE NOT NULL,
  id_banco INTEGER NOT NULL REFERENCES bancos(id),
  creado_en TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS alertas (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tipo VARCHAR(50) NOT NULL,
  titulo VARCHAR(200) NOT NULL,
  mensaje TEXT,
  prioridad VARCHAR(20) DEFAULT 'media',
  fecha_vencimiento TIMESTAMP,
  leida BOOLEAN DEFAULT FALSE,
  resuelta BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS recordatorios (
  id SERIAL PRIMARY KEY,
  titulo VARCHAR(200) NOT NULL,
  descripcion TEXT,
  fecha_limite DATE NOT NULL,
  notas TEXT,
  completado BOOLEAN DEFAULT FALSE,
  privado BOOLEAN DEFAULT FALSE,
  creado_por UUID NOT NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

-- =============================================
-- Columns that may be missing on older tenants
-- (CREATE TABLE IF NOT EXISTS won't add these if the table already existed)
-- =============================================

ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS id_conciliacion INTEGER;
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS conciliado VARCHAR(50);
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS source VARCHAR(20) DEFAULT 'manual';
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS facturapi_id VARCHAR(50);
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS regimen_fiscal_emisor VARCHAR(3);
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS regimen_fiscal_receptor VARCHAR(3);
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS last_sat_sync TIMESTAMP;
ALTER TABLE cfdis ADD COLUMN IF NOT EXISTS sat_sync_job_id UUID;

-- Indexes

CREATE INDEX IF NOT EXISTS idx_cfdis_fecha_emision ON cfdis(fecha_emision DESC);
CREATE INDEX IF NOT EXISTS idx_cfdis_type ON cfdis(type);
CREATE INDEX IF NOT EXISTS idx_cfdis_rfc_emisor ON cfdis(rfc_emisor);
CREATE INDEX IF NOT EXISTS idx_cfdis_rfc_receptor ON cfdis(rfc_receptor);
CREATE INDEX IF NOT EXISTS idx_cfdis_status ON cfdis(status);
CREATE INDEX IF NOT EXISTS idx_cfdis_year_month ON cfdis(year, month);
CREATE INDEX IF NOT EXISTS idx_cfdis_nombre_emisor_trgm ON cfdis USING gin(nombre_emisor gin_trgm_ops);
CREATE INDEX IF NOT EXISTS idx_cfdis_nombre_receptor_trgm ON cfdis USING gin(nombre_receptor gin_trgm_ops);

CREATE INDEX IF NOT EXISTS idx_cfdis_rfc_emisor_id ON cfdis(rfc_emisor_id);
CREATE INDEX IF NOT EXISTS idx_cfdis_rfc_receptor_id ON cfdis(rfc_receptor_id);

CREATE INDEX IF NOT EXISTS idx_cfdi_conceptos_cfdi_id ON cfdi_conceptos(cfdi_id);
CREATE INDEX IF NOT EXISTS idx_cfdi_conceptos_clave ON cfdi_conceptos(clave_prod_serv);

CREATE INDEX IF NOT EXISTS idx_conciliaciones_anio_mes ON conciliaciones(anio, mes);
CREATE INDEX IF NOT EXISTS idx_conciliaciones_id_cfdi ON conciliaciones(id_cfdi);
CREATE INDEX IF NOT EXISTS idx_cfdis_id_conciliacion ON cfdis(id_conciliacion);

-- Deferred FK: cfdis.id_conciliacion -> conciliaciones(id)
-- (cfdis is created before conciliaciones, so this constraint is added after both tables exist)

DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'cfdis_id_conciliacion_fkey') THEN
    ALTER TABLE cfdis ADD CONSTRAINT cfdis_id_conciliacion_fkey FOREIGN KEY (id_conciliacion) REFERENCES conciliaciones(id);
  END IF;
END $$;
