-- =====================================================
-- SCHEMA: infonavit
-- PROPOSITO: Cumplimiento INFONAVIT, derechohabientes, actas
-- MODULOS: MAI-010 (CRM Derechohabientes), MAI-011 (INFONAVIT)
-- FECHA: 2025-11-24
-- ESPECIFICO: 100% Mexico - INFONAVIT
-- =====================================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS infonavit;

-- =====================================================
-- TYPES (ENUMs)
-- =====================================================

CREATE TYPE infonavit.derechohabiente_status AS ENUM (
  'prospect',        -- Prospecto
  'pre_qualified',   -- Precalificado
  'qualified',       -- Calificado (credito aprobado)
  'assigned',        -- Asignado a vivienda
  'in_process',      -- En proceso de escrituracion
  'owner',           -- Propietario (escriturado)
  'cancelled'        -- Cancelado
);

CREATE TYPE infonavit.credit_type AS ENUM (
  'infonavit_tradicional', -- Credito INFONAVIT tradicional
  'infonavit_total',       -- INFONAVIT Total
  'cofinavit',             -- Cofinavit (INFONAVIT + banco)
  'mejoravit',             -- Mejoravit
  'fovissste',             -- FOVISSSTE
  'fovissste_infonavit',   -- FOVISSSTE + INFONAVIT
  'bank_credit',           -- Credito bancario
  'cash'                   -- Contado
);

CREATE TYPE infonavit.acta_type AS ENUM (
  'inicio_obra',           -- Acta de inicio de obra
  'verificacion_avance',   -- Acta de verificacion de avance
  'entrega_recepcion',     -- Acta de entrega-recepcion
  'conclusion_obra',       -- Acta de conclusion de obra
  'liberacion_vivienda'    -- Liberacion de vivienda
);

CREATE TYPE infonavit.acta_status AS ENUM (
  'draft',           -- Borrador
  'pending',         -- Pendiente firma
  'signed',          -- Firmada
  'submitted',       -- Enviada a INFONAVIT
  'approved',        -- Aprobada
  'rejected',        -- Rechazada
  'cancelled'        -- Cancelada
);

CREATE TYPE infonavit.report_type AS ENUM (
  'avance_fisico',         -- Reporte de avance fisico
  'avance_financiero',     -- Reporte de avance financiero
  'inventario_viviendas',  -- Inventario de viviendas
  'asignaciones',          -- Reporte de asignaciones
  'escrituraciones',       -- Reporte de escrituraciones
  'cartera_vencida'        -- Cartera vencida
);

-- =====================================================
-- TABLES - REGISTRO INFONAVIT
-- =====================================================

-- Tabla: registro_infonavit (registro del constructor ante INFONAVIT)
CREATE TABLE infonavit.registro_infonavit (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  company_id UUID NOT NULL REFERENCES auth.companies(id),
  registro_number VARCHAR(50) NOT NULL, -- Numero de registro INFONAVIT
  registro_date DATE NOT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  vigencia_start DATE,
  vigencia_end DATE,
  responsable_tecnico VARCHAR(255),
  cedula_profesional VARCHAR(50),
  metadata JSONB DEFAULT '{}',

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id),
  updated_at TIMESTAMP,
  updated_by UUID REFERENCES auth.users(id),
  deleted_at TIMESTAMP,
  deleted_by UUID REFERENCES auth.users(id),

  CONSTRAINT uq_registro_infonavit_tenant UNIQUE (tenant_id, registro_number)
);

-- Tabla: oferta_vivienda (oferta de viviendas ante INFONAVIT)
CREATE TABLE infonavit.oferta_vivienda (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  registro_id UUID NOT NULL REFERENCES infonavit.registro_infonavit(id),
  fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
  oferta_number VARCHAR(50) NOT NULL,
  submission_date DATE NOT NULL,
  approval_date DATE,
  total_units INTEGER NOT NULL DEFAULT 0,
  approved_units INTEGER DEFAULT 0,
  price_range_min DECIMAL(14,2),
  price_range_max DECIMAL(14,2),
  status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending, approved, rejected
  rejection_reason TEXT,
  metadata JSONB DEFAULT '{}',

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id),
  updated_at TIMESTAMP,
  updated_by UUID REFERENCES auth.users(id),
  deleted_at TIMESTAMP,
  deleted_by UUID REFERENCES auth.users(id),

  CONSTRAINT uq_oferta_vivienda_tenant UNIQUE (tenant_id, oferta_number)
);

-- =====================================================
-- TABLES - DERECHOHABIENTES
-- =====================================================

-- Tabla: derechohabientes (compradores con credito INFONAVIT)
CREATE TABLE infonavit.derechohabientes (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  partner_id UUID, -- FK a core.partners

  -- Datos personales
  nss VARCHAR(15) NOT NULL, -- Numero de Seguro Social
  curp VARCHAR(18),
  rfc VARCHAR(13),
  full_name VARCHAR(255) NOT NULL,
  first_name VARCHAR(100),
  last_name VARCHAR(100),
  second_last_name VARCHAR(100),
  birth_date DATE,
  gender VARCHAR(10),
  marital_status VARCHAR(20),
  nationality VARCHAR(50) DEFAULT 'Mexicana',

  -- Contacto
  email VARCHAR(255),
  phone VARCHAR(20),
  mobile VARCHAR(20),
  address TEXT,
  city VARCHAR(100),
  state VARCHAR(100),
  zip_code VARCHAR(10),

  -- Datos laborales
  employer_name VARCHAR(255),
  employer_rfc VARCHAR(13),
  employment_start_date DATE,
  salary DECIMAL(12,2),
  cotization_weeks INTEGER, -- Semanas cotizadas

  -- Credito
  credit_type infonavit.credit_type,
  credit_number VARCHAR(50),
  credit_amount DECIMAL(14,2),
  puntos_infonavit DECIMAL(10,2),
  subcuenta_vivienda DECIMAL(14,2),
  precalificacion_date DATE,
  precalificacion_amount DECIMAL(14,2),

  -- Estado
  status infonavit.derechohabiente_status NOT NULL DEFAULT 'prospect',

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id),
  updated_at TIMESTAMP,
  updated_by UUID REFERENCES auth.users(id),
  deleted_at TIMESTAMP,
  deleted_by UUID REFERENCES auth.users(id),

  CONSTRAINT uq_derechohabientes_nss_tenant UNIQUE (tenant_id, nss)
);

-- Tabla: asignacion_vivienda (asignacion de vivienda a derechohabiente)
CREATE TABLE infonavit.asignacion_vivienda (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  derechohabiente_id UUID NOT NULL REFERENCES infonavit.derechohabientes(id),
  lote_id UUID REFERENCES construction.lotes(id),
  departamento_id UUID REFERENCES construction.departamentos(id),
  oferta_id UUID REFERENCES infonavit.oferta_vivienda(id),

  -- Asignacion
  assignment_date DATE NOT NULL,
  assignment_number VARCHAR(50),
  status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending, confirmed, cancelled

  -- Precios
  sale_price DECIMAL(14,2) NOT NULL,
  credit_amount DECIMAL(14,2),
  down_payment DECIMAL(14,2),
  subsidy_amount DECIMAL(14,2), -- Subsidio (si aplica)

  -- Escrituracion
  notary_name VARCHAR(255),
  notary_number VARCHAR(50),
  deed_date DATE, -- Fecha de escritura
  deed_number VARCHAR(50),
  public_registry_number VARCHAR(50),
  public_registry_date DATE,

  -- Entrega
  scheduled_delivery_date DATE,
  actual_delivery_date DATE,
  delivery_act_id UUID, -- FK a acta de entrega

  notes TEXT,

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id),
  updated_at TIMESTAMP,
  updated_by UUID REFERENCES auth.users(id),
  deleted_at TIMESTAMP,
  deleted_by UUID REFERENCES auth.users(id),

  CONSTRAINT chk_asignacion_lote_or_depto CHECK (
    (lote_id IS NOT NULL AND departamento_id IS NULL) OR
    (lote_id IS NULL AND departamento_id IS NOT NULL)
  )
);

-- =====================================================
-- TABLES - ACTAS
-- =====================================================

-- Tabla: actas (actas INFONAVIT)
CREATE TABLE infonavit.actas (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
  acta_type infonavit.acta_type NOT NULL,
  acta_number VARCHAR(50) NOT NULL,
  acta_date DATE NOT NULL,
  status infonavit.acta_status NOT NULL DEFAULT 'draft',

  -- Participantes
  infonavit_representative VARCHAR(255),
  constructor_representative VARCHAR(255),
  perito_name VARCHAR(255),
  perito_cedula VARCHAR(50),

  -- Contenido
  description TEXT,
  observations TEXT,
  agreements TEXT,

  -- Avance reportado (para actas de verificacion)
  physical_advance_percentage DECIMAL(5,2),
  financial_advance_percentage DECIMAL(5,2),

  -- Firmas
  signed_at TIMESTAMP,
  submitted_to_infonavit_at TIMESTAMP,
  infonavit_response_at TIMESTAMP,
  infonavit_folio VARCHAR(50),

  -- Documentos
  document_url VARCHAR(500),
  signed_document_url VARCHAR(500),

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id),
  updated_at TIMESTAMP,
  updated_by UUID REFERENCES auth.users(id),
  deleted_at TIMESTAMP,
  deleted_by UUID REFERENCES auth.users(id),

  CONSTRAINT uq_actas_number_tenant UNIQUE (tenant_id, acta_number)
);

-- Tabla: acta_viviendas (viviendas incluidas en acta)
CREATE TABLE infonavit.acta_viviendas (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  acta_id UUID NOT NULL REFERENCES infonavit.actas(id) ON DELETE CASCADE,
  lote_id UUID REFERENCES construction.lotes(id),
  departamento_id UUID REFERENCES construction.departamentos(id),
  advance_percentage DECIMAL(5,2),
  observations TEXT,

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id)
);

-- =====================================================
-- TABLES - REPORTES INFONAVIT
-- =====================================================

-- Tabla: reportes_infonavit (reportes enviados a INFONAVIT)
CREATE TABLE infonavit.reportes_infonavit (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
  report_type infonavit.report_type NOT NULL,
  report_number VARCHAR(50) NOT NULL,
  period_start DATE NOT NULL,
  period_end DATE NOT NULL,
  submission_date DATE,
  status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft, submitted, acknowledged
  infonavit_folio VARCHAR(50),

  -- Datos del reporte
  total_units INTEGER,
  units_in_progress INTEGER,
  units_completed INTEGER,
  units_delivered INTEGER,
  physical_advance_percentage DECIMAL(5,2),
  financial_advance_percentage DECIMAL(5,2),

  -- Archivos
  document_url VARCHAR(500),
  acknowledgment_url VARCHAR(500),

  notes TEXT,

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id),
  updated_at TIMESTAMP,
  updated_by UUID REFERENCES auth.users(id),
  deleted_at TIMESTAMP,
  deleted_by UUID REFERENCES auth.users(id),

  CONSTRAINT uq_reportes_number_tenant UNIQUE (tenant_id, report_number)
);

-- Tabla: historico_puntos (historico de puntos INFONAVIT)
CREATE TABLE infonavit.historico_puntos (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
  derechohabiente_id UUID NOT NULL REFERENCES infonavit.derechohabientes(id),
  query_date DATE NOT NULL,
  puntos DECIMAL(10,2),
  subcuenta_vivienda DECIMAL(14,2),
  cotization_weeks INTEGER,
  credit_capacity DECIMAL(14,2),
  source VARCHAR(50), -- API, manual, file_import

  -- Auditoria
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID REFERENCES auth.users(id)
);

-- =====================================================
-- INDICES
-- =====================================================

-- Registro INFONAVIT
CREATE INDEX idx_registro_infonavit_tenant_id ON infonavit.registro_infonavit(tenant_id);
CREATE INDEX idx_registro_infonavit_company_id ON infonavit.registro_infonavit(company_id);

-- Oferta Vivienda
CREATE INDEX idx_oferta_vivienda_tenant_id ON infonavit.oferta_vivienda(tenant_id);
CREATE INDEX idx_oferta_vivienda_registro_id ON infonavit.oferta_vivienda(registro_id);
CREATE INDEX idx_oferta_vivienda_fraccionamiento_id ON infonavit.oferta_vivienda(fraccionamiento_id);
CREATE INDEX idx_oferta_vivienda_status ON infonavit.oferta_vivienda(status);

-- Derechohabientes
CREATE INDEX idx_derechohabientes_tenant_id ON infonavit.derechohabientes(tenant_id);
CREATE INDEX idx_derechohabientes_nss ON infonavit.derechohabientes(nss);
CREATE INDEX idx_derechohabientes_curp ON infonavit.derechohabientes(curp);
CREATE INDEX idx_derechohabientes_status ON infonavit.derechohabientes(status);
CREATE INDEX idx_derechohabientes_credit_type ON infonavit.derechohabientes(credit_type);
CREATE INDEX idx_derechohabientes_full_name ON infonavit.derechohabientes(full_name);

-- Asignacion Vivienda
CREATE INDEX idx_asignacion_tenant_id ON infonavit.asignacion_vivienda(tenant_id);
CREATE INDEX idx_asignacion_derechohabiente_id ON infonavit.asignacion_vivienda(derechohabiente_id);
CREATE INDEX idx_asignacion_lote_id ON infonavit.asignacion_vivienda(lote_id);
CREATE INDEX idx_asignacion_departamento_id ON infonavit.asignacion_vivienda(departamento_id);
CREATE INDEX idx_asignacion_status ON infonavit.asignacion_vivienda(status);

-- Actas
CREATE INDEX idx_actas_tenant_id ON infonavit.actas(tenant_id);
CREATE INDEX idx_actas_fraccionamiento_id ON infonavit.actas(fraccionamiento_id);
CREATE INDEX idx_actas_type ON infonavit.actas(acta_type);
CREATE INDEX idx_actas_status ON infonavit.actas(status);
CREATE INDEX idx_actas_date ON infonavit.actas(acta_date);

-- Acta Viviendas
CREATE INDEX idx_acta_viviendas_tenant_id ON infonavit.acta_viviendas(tenant_id);
CREATE INDEX idx_acta_viviendas_acta_id ON infonavit.acta_viviendas(acta_id);

-- Reportes
CREATE INDEX idx_reportes_tenant_id ON infonavit.reportes_infonavit(tenant_id);
CREATE INDEX idx_reportes_fraccionamiento_id ON infonavit.reportes_infonavit(fraccionamiento_id);
CREATE INDEX idx_reportes_type ON infonavit.reportes_infonavit(report_type);
CREATE INDEX idx_reportes_status ON infonavit.reportes_infonavit(status);

-- Historico Puntos
CREATE INDEX idx_historico_puntos_tenant_id ON infonavit.historico_puntos(tenant_id);
CREATE INDEX idx_historico_puntos_derechohabiente_id ON infonavit.historico_puntos(derechohabiente_id);
CREATE INDEX idx_historico_puntos_query_date ON infonavit.historico_puntos(query_date);

-- =====================================================
-- ROW LEVEL SECURITY (RLS)
-- =====================================================

-- Habilitar RLS
ALTER TABLE infonavit.registro_infonavit ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.oferta_vivienda ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.derechohabientes ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.asignacion_vivienda ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.actas ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.acta_viviendas ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.reportes_infonavit ENABLE ROW LEVEL SECURITY;
ALTER TABLE infonavit.historico_puntos ENABLE ROW LEVEL SECURITY;

-- Policies
CREATE POLICY tenant_isolation_registro_infonavit ON infonavit.registro_infonavit
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_oferta_vivienda ON infonavit.oferta_vivienda
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_derechohabientes ON infonavit.derechohabientes
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_asignacion_vivienda ON infonavit.asignacion_vivienda
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_actas ON infonavit.actas
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_acta_viviendas ON infonavit.acta_viviendas
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_reportes_infonavit ON infonavit.reportes_infonavit
  USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation_historico_puntos ON infonavit.historico_puntos
  USING (tenant_id = get_current_tenant_id());

-- =====================================================
-- COMENTARIOS
-- =====================================================

COMMENT ON SCHEMA infonavit IS 'Schema de cumplimiento INFONAVIT y gestion de derechohabientes';
COMMENT ON TABLE infonavit.registro_infonavit IS 'Registro del constructor ante INFONAVIT';
COMMENT ON TABLE infonavit.oferta_vivienda IS 'Oferta de viviendas registrada ante INFONAVIT';
COMMENT ON TABLE infonavit.derechohabientes IS 'Derechohabientes INFONAVIT/compradores';
COMMENT ON TABLE infonavit.asignacion_vivienda IS 'Asignacion de vivienda a derechohabiente';
COMMENT ON TABLE infonavit.actas IS 'Actas oficiales INFONAVIT (inicio, verificacion, entrega)';
COMMENT ON TABLE infonavit.acta_viviendas IS 'Viviendas incluidas en cada acta';
COMMENT ON TABLE infonavit.reportes_infonavit IS 'Reportes periodicos enviados a INFONAVIT';
COMMENT ON TABLE infonavit.historico_puntos IS 'Historico de consulta de puntos INFONAVIT';

-- =====================================================
-- FIN DEL SCHEMA INFONAVIT
-- =====================================================
