-- =====================================================
-- SCHEMA: crm
-- PROPOSITO: Customer Relationship Management
-- MODULOS: MGN-CRM (CRM)
-- FECHA: 2025-11-24
-- =====================================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS crm;

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

CREATE TYPE crm.lead_status AS ENUM (
  'new',
  'contacted',
  'qualified',
  'converted',
  'lost'
);

CREATE TYPE crm.opportunity_status AS ENUM (
  'open',
  'won',
  'lost'
);

CREATE TYPE crm.activity_type AS ENUM (
  'call',
  'email',
  'meeting',
  'task',
  'note'
);

CREATE TYPE crm.lead_source AS ENUM (
  'website',
  'phone',
  'email',
  'referral',
  'social_media',
  'advertising',
  'event',
  'other'
);

-- =====================================================
-- TABLES
-- =====================================================

-- Tabla: lead_stages (Etapas del pipeline de leads)
CREATE TABLE crm.lead_stages (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

  name VARCHAR(100) NOT NULL,
  sequence INTEGER NOT NULL DEFAULT 10,
  is_won BOOLEAN DEFAULT FALSE,
  probability DECIMAL(5, 2) DEFAULT 0,
  requirements TEXT,

  active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,

  UNIQUE(tenant_id, name)
);

-- Tabla: opportunity_stages (Etapas del pipeline de oportunidades)
CREATE TABLE crm.opportunity_stages (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

  name VARCHAR(100) NOT NULL,
  sequence INTEGER NOT NULL DEFAULT 10,
  is_won BOOLEAN DEFAULT FALSE,
  probability DECIMAL(5, 2) DEFAULT 0,
  requirements TEXT,

  active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,

  UNIQUE(tenant_id, name)
);

-- Tabla: lost_reasons (Razones de perdida)
CREATE TABLE crm.lost_reasons (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

  name VARCHAR(100) NOT NULL,
  description TEXT,

  active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,

  UNIQUE(tenant_id, name)
);

-- Tabla: leads (Prospectos/Leads)
CREATE TABLE crm.leads (
  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) ON DELETE CASCADE,

  -- Numeracion
  name VARCHAR(255) NOT NULL,
  ref VARCHAR(100),

  -- Contacto
  contact_name VARCHAR(255),
  email VARCHAR(255),
  phone VARCHAR(50),
  mobile VARCHAR(50),
  website VARCHAR(255),

  -- Empresa del prospecto
  company_name VARCHAR(255),
  job_position VARCHAR(100),
  industry VARCHAR(100),
  employee_count VARCHAR(50),
  annual_revenue DECIMAL(15, 2),

  -- Direccion
  street VARCHAR(255),
  city VARCHAR(100),
  state VARCHAR(100),
  zip VARCHAR(20),
  country VARCHAR(100),

  -- Pipeline
  stage_id UUID REFERENCES crm.lead_stages(id),
  status crm.lead_status NOT NULL DEFAULT 'new',

  -- Asignacion
  user_id UUID REFERENCES auth.users(id),
  sales_team_id UUID REFERENCES sales.sales_teams(id),

  -- Origen
  source crm.lead_source,
  campaign_id UUID, -- Para futuro modulo marketing
  medium VARCHAR(100),

  -- Valoracion
  priority INTEGER DEFAULT 0 CHECK (priority >= 0 AND priority <= 3),
  probability DECIMAL(5, 2) DEFAULT 0,
  expected_revenue DECIMAL(15, 2),

  -- Fechas
  date_open TIMESTAMP WITH TIME ZONE,
  date_closed TIMESTAMP WITH TIME ZONE,
  date_deadline DATE,
  date_last_activity TIMESTAMP WITH TIME ZONE,

  -- Conversion
  partner_id UUID REFERENCES core.partners(id),
  opportunity_id UUID, -- Se llena al convertir

  -- Perdida
  lost_reason_id UUID REFERENCES crm.lost_reasons(id),
  lost_notes TEXT,

  -- Notas
  description TEXT,
  notes TEXT,
  tags VARCHAR(255)[],

  -- Auditoria
  created_by UUID REFERENCES auth.users(id),
  updated_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Tabla: opportunities (Oportunidades de venta)
CREATE TABLE crm.opportunities (
  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) ON DELETE CASCADE,

  -- Numeracion
  name VARCHAR(255) NOT NULL,
  ref VARCHAR(100),

  -- Cliente
  partner_id UUID NOT NULL REFERENCES core.partners(id),
  contact_name VARCHAR(255),
  email VARCHAR(255),
  phone VARCHAR(50),

  -- Pipeline
  stage_id UUID REFERENCES crm.opportunity_stages(id),
  status crm.opportunity_status NOT NULL DEFAULT 'open',

  -- Asignacion
  user_id UUID REFERENCES auth.users(id),
  sales_team_id UUID REFERENCES sales.sales_teams(id),

  -- Valoracion
  priority INTEGER DEFAULT 0 CHECK (priority >= 0 AND priority <= 3),
  probability DECIMAL(5, 2) DEFAULT 0,
  expected_revenue DECIMAL(15, 2),
  recurring_revenue DECIMAL(15, 2),
  recurring_plan VARCHAR(50),

  -- Fechas
  date_deadline DATE,
  date_closed TIMESTAMP WITH TIME ZONE,
  date_last_activity TIMESTAMP WITH TIME ZONE,

  -- Origen (si viene de lead)
  lead_id UUID REFERENCES crm.leads(id),
  source crm.lead_source,
  campaign_id UUID,
  medium VARCHAR(100),

  -- Cierre
  lost_reason_id UUID REFERENCES crm.lost_reasons(id),
  lost_notes TEXT,

  -- Relaciones
  quotation_id UUID REFERENCES sales.quotations(id),
  order_id UUID REFERENCES sales.sales_orders(id),

  -- Notas
  description TEXT,
  notes TEXT,
  tags VARCHAR(255)[],

  -- Auditoria
  created_by UUID REFERENCES auth.users(id),
  updated_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Actualizar referencia circular en leads
ALTER TABLE crm.leads ADD CONSTRAINT fk_leads_opportunity
  FOREIGN KEY (opportunity_id) REFERENCES crm.opportunities(id);

-- Tabla: crm_activities (Actividades CRM)
CREATE TABLE crm.activities (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

  -- Referencia polimorfica
  res_model VARCHAR(100) NOT NULL,
  res_id UUID NOT NULL,

  -- Actividad
  activity_type crm.activity_type NOT NULL,
  summary VARCHAR(255),
  description TEXT,

  -- Fechas
  date_deadline DATE,
  date_done TIMESTAMP WITH TIME ZONE,

  -- Asignacion
  user_id UUID REFERENCES auth.users(id),
  assigned_to UUID REFERENCES auth.users(id),

  -- Estado
  done BOOLEAN DEFAULT FALSE,

  -- Auditoria
  created_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- =====================================================
-- INDEXES
-- =====================================================

CREATE INDEX idx_lead_stages_tenant ON crm.lead_stages(tenant_id);
CREATE INDEX idx_opportunity_stages_tenant ON crm.opportunity_stages(tenant_id);
CREATE INDEX idx_lost_reasons_tenant ON crm.lost_reasons(tenant_id);

CREATE INDEX idx_leads_tenant ON crm.leads(tenant_id);
CREATE INDEX idx_leads_company ON crm.leads(company_id);
CREATE INDEX idx_leads_status ON crm.leads(status);
CREATE INDEX idx_leads_stage ON crm.leads(stage_id);
CREATE INDEX idx_leads_user ON crm.leads(user_id);
CREATE INDEX idx_leads_partner ON crm.leads(partner_id);
CREATE INDEX idx_leads_email ON crm.leads(email);

CREATE INDEX idx_opportunities_tenant ON crm.opportunities(tenant_id);
CREATE INDEX idx_opportunities_company ON crm.opportunities(company_id);
CREATE INDEX idx_opportunities_status ON crm.opportunities(status);
CREATE INDEX idx_opportunities_stage ON crm.opportunities(stage_id);
CREATE INDEX idx_opportunities_user ON crm.opportunities(user_id);
CREATE INDEX idx_opportunities_partner ON crm.opportunities(partner_id);

CREATE INDEX idx_crm_activities_tenant ON crm.activities(tenant_id);
CREATE INDEX idx_crm_activities_model ON crm.activities(res_model, res_id);
CREATE INDEX idx_crm_activities_user ON crm.activities(assigned_to);
CREATE INDEX idx_crm_activities_deadline ON crm.activities(date_deadline);

-- =====================================================
-- TRIGGERS
-- =====================================================

CREATE TRIGGER update_lead_stages_timestamp
  BEFORE UPDATE ON crm.lead_stages
  FOR EACH ROW EXECUTE FUNCTION core.update_timestamp();

CREATE TRIGGER update_opportunity_stages_timestamp
  BEFORE UPDATE ON crm.opportunity_stages
  FOR EACH ROW EXECUTE FUNCTION core.update_timestamp();

CREATE TRIGGER update_leads_timestamp
  BEFORE UPDATE ON crm.leads
  FOR EACH ROW EXECUTE FUNCTION core.update_timestamp();

CREATE TRIGGER update_opportunities_timestamp
  BEFORE UPDATE ON crm.opportunities
  FOR EACH ROW EXECUTE FUNCTION core.update_timestamp();

CREATE TRIGGER update_crm_activities_timestamp
  BEFORE UPDATE ON crm.activities
  FOR EACH ROW EXECUTE FUNCTION core.update_timestamp();

-- =====================================================
-- ROW LEVEL SECURITY
-- =====================================================

-- Habilitar RLS
ALTER TABLE crm.lead_stages ENABLE ROW LEVEL SECURITY;
ALTER TABLE crm.opportunity_stages ENABLE ROW LEVEL SECURITY;
ALTER TABLE crm.lost_reasons ENABLE ROW LEVEL SECURITY;
ALTER TABLE crm.leads ENABLE ROW LEVEL SECURITY;
ALTER TABLE crm.opportunities ENABLE ROW LEVEL SECURITY;
ALTER TABLE crm.activities ENABLE ROW LEVEL SECURITY;

-- Políticas de aislamiento por tenant
CREATE POLICY tenant_isolation_lead_stages ON crm.lead_stages
  USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

CREATE POLICY tenant_isolation_opportunity_stages ON crm.opportunity_stages
  USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

CREATE POLICY tenant_isolation_lost_reasons ON crm.lost_reasons
  USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

CREATE POLICY tenant_isolation_leads ON crm.leads
  USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

CREATE POLICY tenant_isolation_opportunities ON crm.opportunities
  USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

CREATE POLICY tenant_isolation_crm_activities ON crm.activities
  USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================================================
-- COMMENTS
-- =====================================================

COMMENT ON TABLE crm.lead_stages IS 'Etapas del pipeline de leads';
COMMENT ON TABLE crm.opportunity_stages IS 'Etapas del pipeline de oportunidades';
COMMENT ON TABLE crm.lost_reasons IS 'Razones de perdida de leads/oportunidades';
COMMENT ON TABLE crm.leads IS 'Prospectos/leads de ventas';
COMMENT ON TABLE crm.opportunities IS 'Oportunidades de venta';
COMMENT ON TABLE crm.activities IS 'Actividades CRM (llamadas, reuniones, etc.)';
