-- =============================================
-- AgendaPRO SaaS - Database Schema
-- PostgreSQL 16+
-- =============================================

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- =============================================
-- 1. PLANOS DE ASSINATURA
-- =============================================
CREATE TABLE IF NOT EXISTS plans (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name VARCHAR(100) NOT NULL,
  slug VARCHAR(100) UNIQUE NOT NULL,
  description TEXT,
  price NUMERIC(10,2) NOT NULL DEFAULT 0,
  price_monthly NUMERIC(10,2) NOT NULL DEFAULT 0,
  price_yearly NUMERIC(10,2) NOT NULL DEFAULT 0,
  max_professionals INT NOT NULL DEFAULT 1,
  max_services INT NOT NULL DEFAULT 5,
  max_appointments_month INT DEFAULT NULL, -- NULL = unlimited
  features JSONB DEFAULT '[]',
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 2. TENANTS (ESTABELECIMENTOS)
-- =============================================
CREATE TABLE IF NOT EXISTS tenants (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  plan_id UUID REFERENCES plans(id),
  name VARCHAR(200) NOT NULL,
  slug VARCHAR(200) UNIQUE NOT NULL,
  business_type VARCHAR(50) NOT NULL DEFAULT 'barbearia', -- barbearia, manicure, massagem, estetica, outro
  logo_url TEXT,
  cover_url TEXT,
  phone VARCHAR(20),
  email VARCHAR(200),
  address TEXT,
  city VARCHAR(100),
  state VARCHAR(2),
  zip_code VARCHAR(10),
  description TEXT,
  settings JSONB DEFAULT '{
    "timezone": "America/Sao_Paulo",
    "currency": "BRL",
    "booking_advance_min": 60,
    "booking_advance_max": 43200,
    "cancellation_limit_min": 120,
    "allow_online_booking": true,
    "require_confirmation": false,
    "send_reminders": true,
    "reminder_minutes_before": 60,
    "theme_color": "#6C63FF",
    "working_days": [1,2,3,4,5,6]
  }',
  subscription_status VARCHAR(20) DEFAULT 'trial', -- trial, active, past_due, cancelled, suspended
  trial_ends_at TIMESTAMPTZ,
  subscription_ends_at TIMESTAMPTZ,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 3. USUÁRIOS (OWNERS, ADMINS, PROFISSIONAIS)
-- =============================================
CREATE TABLE IF NOT EXISTS users (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  name VARCHAR(200) NOT NULL,
  email VARCHAR(200) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  phone VARCHAR(20),
  avatar_url TEXT,
  role VARCHAR(20) NOT NULL DEFAULT 'professional', -- owner, admin, professional
  is_active BOOLEAN DEFAULT true,
  last_login_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(email, tenant_id)
);

-- =============================================
-- 4. CATEGORIAS DE SERVIÇO
-- =============================================
CREATE TABLE IF NOT EXISTS service_categories (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  name VARCHAR(100) NOT NULL,
  description TEXT,
  icon VARCHAR(50),
  sort_order INT DEFAULT 0,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 5. SERVIÇOS
-- =============================================
CREATE TABLE IF NOT EXISTS services (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  category_id UUID REFERENCES service_categories(id) ON DELETE SET NULL,
  name VARCHAR(200) NOT NULL,
  description TEXT,
  duration_minutes INT NOT NULL DEFAULT 30,
  price NUMERIC(10,2) NOT NULL DEFAULT 0,
  price_type VARCHAR(20) DEFAULT 'fixed', -- fixed, starting_at, per_hour
  image_url TEXT,
  is_active BOOLEAN DEFAULT true,
  sort_order INT DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 6. PROFISSIONAIS <-> SERVIÇOS
-- =============================================
CREATE TABLE IF NOT EXISTS professional_services (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  professional_id UUID REFERENCES users(id) ON DELETE CASCADE,
  service_id UUID REFERENCES services(id) ON DELETE CASCADE,
  custom_price NUMERIC(10,2),
  custom_duration INT,
  commission_percent NUMERIC(5,2) DEFAULT 0,
  UNIQUE(professional_id, service_id)
);

-- =============================================
-- 7. HORÁRIOS DE TRABALHO
-- =============================================
CREATE TABLE IF NOT EXISTS working_hours (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  professional_id UUID REFERENCES users(id) ON DELETE CASCADE,
  day_of_week INT NOT NULL CHECK (day_of_week BETWEEN 0 AND 6), -- 0=domingo
  start_time TIME NOT NULL,
  end_time TIME NOT NULL,
  break_start TIME,
  break_end TIME,
  is_active BOOLEAN DEFAULT true,
  UNIQUE(professional_id, day_of_week)
);

-- =============================================
-- 8. BLOQUEIOS / FOLGAS
-- =============================================
CREATE TABLE IF NOT EXISTS schedule_blocks (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  professional_id UUID REFERENCES users(id) ON DELETE CASCADE,
  title VARCHAR(200),
  start_at TIMESTAMPTZ NOT NULL,
  end_at TIMESTAMPTZ NOT NULL,
  is_all_day BOOLEAN DEFAULT false,
  recurrence VARCHAR(20) DEFAULT 'none', -- none, daily, weekly, monthly
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 9. CLIENTES
-- =============================================
CREATE TABLE IF NOT EXISTS clients (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  name VARCHAR(200) NOT NULL,
  email VARCHAR(200),
  phone VARCHAR(20),
  cpf VARCHAR(14),
  birth_date DATE,
  gender VARCHAR(20),
  notes TEXT,
  avatar_url TEXT,
  total_visits INT DEFAULT 0,
  total_spent NUMERIC(10,2) DEFAULT 0,
  last_visit_at TIMESTAMPTZ,
  tags JSONB DEFAULT '[]',
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 10. AGENDAMENTOS
-- =============================================
CREATE TABLE IF NOT EXISTS appointments (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  client_id UUID REFERENCES clients(id) ON DELETE SET NULL,
  professional_id UUID REFERENCES users(id) ON DELETE SET NULL,
  service_id UUID REFERENCES services(id) ON DELETE SET NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending, confirmed, in_progress, completed, cancelled, no_show
  date DATE NOT NULL,
  start_time TIME NOT NULL,
  end_time TIME NOT NULL,
  price NUMERIC(10,2) NOT NULL DEFAULT 0,
  discount NUMERIC(10,2) DEFAULT 0,
  notes TEXT,
  client_name VARCHAR(200), -- for walk-ins
  client_phone VARCHAR(20),
  client_email VARCHAR(200),
  source VARCHAR(20) DEFAULT 'manual', -- manual, online, whatsapp
  cancelled_at TIMESTAMPTZ,
  cancellation_reason TEXT,
  completed_at TIMESTAMPTZ,
  reminder_sent BOOLEAN DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 11. PAGAMENTOS
-- =============================================
CREATE TABLE IF NOT EXISTS payments (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  appointment_id UUID REFERENCES appointments(id) ON DELETE SET NULL,
  client_id UUID REFERENCES clients(id) ON DELETE SET NULL,
  amount NUMERIC(10,2) NOT NULL,
  method VARCHAR(30) NOT NULL DEFAULT 'cash', -- cash, credit, debit, pix, transfer
  status VARCHAR(20) DEFAULT 'completed', -- pending, completed, refunded
  notes TEXT,
  paid_at TIMESTAMPTZ DEFAULT NOW(),
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 12. ASSINATURAS SaaS
-- =============================================
CREATE TABLE IF NOT EXISTS subscriptions (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  plan_id UUID REFERENCES plans(id),
  status VARCHAR(20) DEFAULT 'active', -- active, past_due, cancelled, suspended
  billing_cycle VARCHAR(10) DEFAULT 'monthly', -- monthly, yearly
  current_period_start TIMESTAMPTZ,
  current_period_end TIMESTAMPTZ,
  payment_method VARCHAR(30),
  payment_gateway VARCHAR(30), -- stripe, asaas, manual
  gateway_subscription_id VARCHAR(200),
  amount NUMERIC(10,2),
  last_payment_at TIMESTAMPTZ,
  next_payment_at TIMESTAMPTZ,
  cancelled_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 13. HISTÓRICO DE PAGAMENTOS SaaS
-- =============================================
CREATE TABLE IF NOT EXISTS subscription_payments (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  subscription_id UUID REFERENCES subscriptions(id) ON DELETE CASCADE,
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  amount NUMERIC(10,2) NOT NULL,
  status VARCHAR(20) DEFAULT 'paid', -- paid, failed, refunded
  gateway_payment_id VARCHAR(200),
  paid_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- 14. NOTIFICAÇÕES
-- =============================================
CREATE TABLE IF NOT EXISTS notifications (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
  user_id UUID REFERENCES users(id) ON DELETE CASCADE,
  type VARCHAR(50) NOT NULL,
  title VARCHAR(200) NOT NULL,
  message TEXT,
  data JSONB DEFAULT '{}',
  is_read BOOLEAN DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================
-- INDEXES
-- =============================================
CREATE INDEX IF NOT EXISTS idx_appointments_tenant_date ON appointments(tenant_id, date);
CREATE INDEX IF NOT EXISTS idx_appointments_professional ON appointments(professional_id, date);
CREATE INDEX IF NOT EXISTS idx_appointments_client ON appointments(client_id);
CREATE INDEX IF NOT EXISTS idx_appointments_status ON appointments(status);
CREATE INDEX IF NOT EXISTS idx_clients_tenant ON clients(tenant_id);
CREATE INDEX IF NOT EXISTS idx_clients_phone ON clients(phone);
CREATE INDEX IF NOT EXISTS idx_services_tenant ON services(tenant_id);
CREATE INDEX IF NOT EXISTS idx_payments_tenant ON payments(tenant_id);
CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id, is_read);
CREATE INDEX IF NOT EXISTS idx_users_tenant ON users(tenant_id);
CREATE INDEX IF NOT EXISTS idx_tenants_slug ON tenants(slug);

-- =============================================
-- SEED: DEFAULT PLANS
-- =============================================
INSERT INTO plans (name, slug, description, price_monthly, price_yearly, max_professionals, max_services, max_appointments_month, features) VALUES
  ('Starter', 'starter', 'Ideal para profissionais autônomos', 49.90, 479.00, 1, 10, 200, '["Agendamento online", "Página de reservas", "Lembretes por e-mail", "Relatórios básicos"]'),
  ('Professional', 'professional', 'Para pequenos estabelecimentos', 99.90, 959.00, 5, 30, NULL, '["Tudo do Starter", "Múltiplos profissionais", "Comissionamento", "Relatórios avançados", "Personalização da marca"]'),
  ('Business', 'business', 'Para estabelecimentos em crescimento', 199.90, 1919.00, 15, 100, NULL, '["Tudo do Professional", "API de integração", "Suporte prioritário", "Multi-unidades", "Automações avançadas"]'),
  ('Enterprise', 'enterprise', 'Solução completa e personalizada', 399.90, 3839.00, 999, 999, NULL, '["Tudo do Business", "Gerente de conta dedicado", "SLA garantido", "Integrações customizadas", "White-label"]')
ON CONFLICT (slug) DO NOTHING;

-- =============================================
-- SEED: DEMO TENANT
-- =============================================
DO $$
DECLARE
  v_plan_id UUID;
  v_tenant_id UUID;
  v_owner_id UUID;
  v_cat_barba_id UUID;
  v_cat_cabelo_id UUID;
  v_cat_combo_id UUID;
  v_svc1_id UUID;
  v_svc2_id UUID;
  v_svc3_id UUID;
  v_svc4_id UUID;
  v_svc5_id UUID;
  v_prof1_id UUID;
  v_prof2_id UUID;
BEGIN
  SELECT id INTO v_plan_id FROM plans WHERE slug = 'professional';
  
  INSERT INTO tenants (id, plan_id, name, slug, business_type, phone, email, description, subscription_status, trial_ends_at)
  VALUES (
    uuid_generate_v4(), v_plan_id, 'Barbearia Premium', 'barbearia-premium', 'barbearia',
    '(11) 99999-1234', 'contato@barbeariapremium.com.br',
    'A melhor barbearia da cidade. Cortes modernos, barbas impecáveis e ambiente premium.',
    'active', NOW() + INTERVAL '30 days'
  )
  ON CONFLICT (slug) DO NOTHING
  RETURNING id INTO v_tenant_id;

  IF v_tenant_id IS NOT NULL THEN
    -- Owner
    INSERT INTO users (id, tenant_id, name, email, password_hash, role)
    VALUES (uuid_generate_v4(), v_tenant_id, 'Admin Demo', 'admin@demo.com', crypt('admin123', gen_salt('bf')), 'owner')
    RETURNING id INTO v_owner_id;

    -- Professionals
    INSERT INTO users (id, tenant_id, name, email, password_hash, role, phone)
    VALUES (uuid_generate_v4(), v_tenant_id, 'Carlos Silva', 'carlos@demo.com', crypt('prof123', gen_salt('bf')), 'professional', '(11) 98888-1111')
    RETURNING id INTO v_prof1_id;

    INSERT INTO users (id, tenant_id, name, email, password_hash, role, phone)
    VALUES (uuid_generate_v4(), v_tenant_id, 'Rafael Santos', 'rafael@demo.com', crypt('prof123', gen_salt('bf')), 'professional', '(11) 98888-2222')
    RETURNING id INTO v_prof2_id;

    -- Categories
    INSERT INTO service_categories (id, tenant_id, name, icon, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, 'Cabelo', 'scissors', 1) RETURNING id INTO v_cat_cabelo_id;
    INSERT INTO service_categories (id, tenant_id, name, icon, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, 'Barba', 'sparkles', 2) RETURNING id INTO v_cat_barba_id;
    INSERT INTO service_categories (id, tenant_id, name, icon, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, 'Combos', 'star', 3) RETURNING id INTO v_cat_combo_id;

    -- Services
    INSERT INTO services (id, tenant_id, category_id, name, description, duration_minutes, price, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, v_cat_cabelo_id, 'Corte Masculino', 'Corte moderno com lavagem e finalização', 40, 55.00, 1) RETURNING id INTO v_svc1_id;
    INSERT INTO services (id, tenant_id, category_id, name, description, duration_minutes, price, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, v_cat_cabelo_id, 'Corte Infantil', 'Corte para crianças até 12 anos', 30, 40.00, 2) RETURNING id INTO v_svc2_id;
    INSERT INTO services (id, tenant_id, category_id, name, description, duration_minutes, price, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, v_cat_barba_id, 'Barba Completa', 'Aparar, modelar e hidratação', 30, 40.00, 3) RETURNING id INTO v_svc3_id;
    INSERT INTO services (id, tenant_id, category_id, name, description, duration_minutes, price, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, v_cat_barba_id, 'Design de Sobrancelha', 'Alinhamento com navalha', 15, 25.00, 4) RETURNING id INTO v_svc4_id;
    INSERT INTO services (id, tenant_id, category_id, name, description, duration_minutes, price, sort_order) VALUES
      (uuid_generate_v4(), v_tenant_id, v_cat_combo_id, 'Combo Corte + Barba', 'Corte masculino + barba completa', 60, 85.00, 5) RETURNING id INTO v_svc5_id;

    -- Professional <-> Services
    INSERT INTO professional_services (professional_id, service_id, commission_percent) VALUES
      (v_prof1_id, v_svc1_id, 40), (v_prof1_id, v_svc2_id, 40), (v_prof1_id, v_svc3_id, 40),
      (v_prof1_id, v_svc4_id, 40), (v_prof1_id, v_svc5_id, 40),
      (v_prof2_id, v_svc1_id, 35), (v_prof2_id, v_svc3_id, 35), (v_prof2_id, v_svc5_id, 35);

    -- Working Hours (Mon-Sat for both professionals)
    FOR i IN 1..6 LOOP
      INSERT INTO working_hours (tenant_id, professional_id, day_of_week, start_time, end_time, break_start, break_end) VALUES
        (v_tenant_id, v_prof1_id, i, '09:00', '19:00', '12:00', '13:00'),
        (v_tenant_id, v_prof2_id, i, '10:00', '20:00', '13:00', '14:00');
    END LOOP;

    -- Sample Clients
    INSERT INTO clients (tenant_id, name, email, phone, total_visits) VALUES
      (v_tenant_id, 'João Mendes', 'joao@email.com', '(11) 97777-1111', 12),
      (v_tenant_id, 'Pedro Oliveira', 'pedro@email.com', '(11) 97777-2222', 8),
      (v_tenant_id, 'Lucas Ferreira', 'lucas@email.com', '(11) 97777-3333', 5),
      (v_tenant_id, 'Mateus Costa', 'mateus@email.com', '(11) 97777-4444', 3),
      (v_tenant_id, 'Gabriel Souza', 'gabriel@email.com', '(11) 97777-5555', 15);

    -- Sample appointments for today
    INSERT INTO appointments (tenant_id, client_id, professional_id, service_id, status, date, start_time, end_time, price, source)
    SELECT v_tenant_id, c.id, v_prof1_id, v_svc1_id, 'confirmed', CURRENT_DATE, '10:00', '10:40', 55.00, 'online'
    FROM clients c WHERE c.name = 'João Mendes' AND c.tenant_id = v_tenant_id LIMIT 1;

    INSERT INTO appointments (tenant_id, client_id, professional_id, service_id, status, date, start_time, end_time, price, source)
    SELECT v_tenant_id, c.id, v_prof1_id, v_svc5_id, 'confirmed', CURRENT_DATE, '11:00', '12:00', 85.00, 'manual'
    FROM clients c WHERE c.name = 'Pedro Oliveira' AND c.tenant_id = v_tenant_id LIMIT 1;

    INSERT INTO appointments (tenant_id, client_id, professional_id, service_id, status, date, start_time, end_time, price, source)
    SELECT v_tenant_id, c.id, v_prof2_id, v_svc3_id, 'pending', CURRENT_DATE, '14:00', '14:30', 40.00, 'online'
    FROM clients c WHERE c.name = 'Lucas Ferreira' AND c.tenant_id = v_tenant_id LIMIT 1;

    INSERT INTO appointments (tenant_id, client_id, professional_id, service_id, status, date, start_time, end_time, price, source)
    SELECT v_tenant_id, c.id, v_prof2_id, v_svc1_id, 'completed', CURRENT_DATE, '10:00', '10:40', 55.00, 'manual'
    FROM clients c WHERE c.name = 'Gabriel Souza' AND c.tenant_id = v_tenant_id LIMIT 1;

    -- Subscription record
    INSERT INTO subscriptions (tenant_id, plan_id, status, billing_cycle, current_period_start, current_period_end, amount, next_payment_at)
    VALUES (v_tenant_id, v_plan_id, 'active', 'monthly', NOW(), NOW() + INTERVAL '30 days', 99.90, NOW() + INTERVAL '30 days');
  END IF;
END $$;
