/**
 * db.js — PostgreSQL connection pool + schema initialisation for Curio HMS.
 * Tables: tenants, users, pending_registrations
 */

const { Pool } = require('pg');
const bcrypt = require('bcryptjs');

const pool = new Pool({
    connectionString: process.env.DATABASE_URL || 'postgres://postgres:curio_secret@curio-db:5432/curio',
    ssl: false,
});

// ── Schema ──────────────────────────────────────────────────────────────────

const SCHEMA_SQL = `
CREATE TABLE IF NOT EXISTS tenants (
    id                TEXT PRIMARY KEY,
    name              TEXT NOT NULL,
    logo              TEXT DEFAULT 'C',
    primary_color     TEXT DEFAULT '#0F172A',
    secondary_color   TEXT DEFAULT '#38BDF8',
    consultation_fee  INTEGER DEFAULT 500,
    currency          TEXT DEFAULT '₹',
    plan              TEXT DEFAULT 'basic',
    status            TEXT DEFAULT 'active',
    whatsapp_number   TEXT,
    specialty         TEXT,
    city              TEXT,
    working_hours     JSONB DEFAULT '[{"start":"09:00","end":"13:00"},{"start":"17:00","end":"22:00"}]',
    days_off          JSONB DEFAULT '[0]',
    holidays          JSONB DEFAULT '[]',
    services_catalog  JSONB DEFAULT '[]',
    created_at        TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS users (
    id            SERIAL PRIMARY KEY,
    tenant_id     TEXT REFERENCES tenants(id) ON DELETE CASCADE,
    email         TEXT UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    name          TEXT NOT NULL,
    role          TEXT NOT NULL CHECK (role IN ('SUPER_ADMIN','OWNER','DOCTOR','RECEPTIONIST','PHARMACIST','LAB_TECH','PATIENT')),
    profile_media JSONB DEFAULT '{}',
    q_and_a       JSONB DEFAULT '[]',
    blocked_dates JSONB DEFAULT '[]',
    status        TEXT DEFAULT 'active',
    created_at    TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS pending_registrations (
    id               SERIAL PRIMARY KEY,
    owner_name       TEXT NOT NULL,
    clinic_name      TEXT NOT NULL,
    specialty        TEXT,
    city             TEXT,
    whatsapp_number  TEXT NOT NULL,
    email            TEXT NOT NULL,
    password_hash    TEXT NOT NULL,
    plan             TEXT DEFAULT 'basic',
    status           TEXT DEFAULT 'pending',
    created_at       TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS transactions (
    id            SERIAL PRIMARY KEY,
    order_id      TEXT NOT NULL UNIQUE,
    payment_id    TEXT,
    amount        INTEGER NOT NULL,
    currency      TEXT DEFAULT 'INR',
    status        TEXT DEFAULT 'created',
    tenant_id     TEXT REFERENCES tenants(id),
    user_id       INTEGER REFERENCES users(id),
    created_at    TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS agent_configs (
    id            SERIAL PRIMARY KEY,
    tenant_id     TEXT REFERENCES tenants(id) ON DELETE CASCADE,
    agent_type    TEXT NOT NULL CHECK (agent_type IN ('BILLING', 'TRIAGE', 'FOLLOWUP', 'INVENTORY', 'CDSS', 'RX_VISION', 'DOC_INTELLIGENCE')),
    is_active     BOOLEAN DEFAULT false,
    config        JSONB DEFAULT '{}',
    created_at    TIMESTAMPTZ DEFAULT now(),
    UNIQUE(tenant_id, agent_type)
);

CREATE TABLE IF NOT EXISTS prescriptions (
    id            TEXT PRIMARY KEY,
    tenant_id     TEXT REFERENCES tenants(id) ON DELETE CASCADE,
    doctor_id     INTEGER REFERENCES users(id),
    patient_id    TEXT NOT NULL,
    patient_name  TEXT NOT NULL,
    diagnosis     TEXT,
    medicines     JSONB DEFAULT '[]',
    lab_tests     JSONB DEFAULT '[]',
    status        TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'ready', 'dispensed')),
    created_at    TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS patients (
    id                SERIAL PRIMARY KEY,
    tenant_id         TEXT REFERENCES tenants(id) ON DELETE CASCADE,
    display_id        TEXT NOT NULL,
    name              TEXT NOT NULL,
    whatsapp_number   TEXT NOT NULL,
    age               INTEGER,
    gender            TEXT,
    created_at        TIMESTAMPTZ DEFAULT now(),
    UNIQUE(tenant_id, whatsapp_number)
);

CREATE TABLE IF NOT EXISTS visits (
    id                SERIAL PRIMARY KEY,
    tenant_id         TEXT REFERENCES tenants(id) ON DELETE CASCADE,
    patient_id        INTEGER REFERENCES patients(id) ON DELETE CASCADE,
    token_number      TEXT NOT NULL,
    status            TEXT DEFAULT 'waiting' CHECK (status IN ('waiting', 'in-room', 'completed', 'cancelled')),
    type              TEXT DEFAULT 'walk-in' CHECK (type IN ('walk-in', 'online')),
    triage_category   TEXT DEFAULT 'Routine',
    payment_status    TEXT DEFAULT 'unpaid' CHECK (payment_status IN ('unpaid', 'paid')),
    fee               INTEGER DEFAULT 0,
    notes             TEXT,
    created_at        TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_users_tenant   ON users(tenant_id);
CREATE INDEX IF NOT EXISTS idx_users_email    ON users(email);
CREATE INDEX IF NOT EXISTS idx_pending_status ON pending_registrations(status);
CREATE INDEX IF NOT EXISTS idx_transactions_order ON transactions(order_id);
CREATE INDEX IF NOT EXISTS idx_agent_configs_tenant ON agent_configs(tenant_id);
CREATE INDEX IF NOT EXISTS idx_prescriptions_tenant_status ON prescriptions(tenant_id, status);


-- Migrations for existing DBs
ALTER TABLE tenants ADD COLUMN IF NOT EXISTS services_catalog JSONB DEFAULT '[]';
ALTER TABLE users ADD COLUMN IF NOT EXISTS profile_media JSONB DEFAULT '{}';
ALTER TABLE users ADD COLUMN IF NOT EXISTS q_and_a JSONB DEFAULT '[]';
ALTER TABLE users ADD COLUMN IF NOT EXISTS blocked_dates JSONB DEFAULT '[]';
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_role_check;
ALTER TABLE users ADD CONSTRAINT users_role_check CHECK (role IN ('SUPER_ADMIN','OWNER','DOCTOR','RECEPTIONIST','PHARMACIST','LAB_TECH','PATIENT'));
ALTER TABLE agent_configs DROP CONSTRAINT IF EXISTS agent_configs_agent_type_check;
ALTER TABLE agent_configs ADD CONSTRAINT agent_configs_agent_type_check CHECK (agent_type IN ('BILLING', 'TRIAGE', 'FOLLOWUP', 'INVENTORY', 'CDSS', 'RX_VISION', 'DOC_INTELLIGENCE'));
`;

// ── Seed super admin ─────────────────────────────────────────────────────────

async function seedSuperAdmin() {
    const email    = process.env.SUPER_ADMIN_EMAIL    || 'admin@curio.app';
    const password = process.env.SUPER_ADMIN_PASSWORD || 'superadmin';

    const existing = await pool.query('SELECT id FROM users WHERE email = $1', [email]);
    if (existing.rows.length > 0) return;

    const hash = await bcrypt.hash(password, 10);
    await pool.query(
        `INSERT INTO users (tenant_id, email, password_hash, name, role)
         VALUES (NULL, $1, $2, 'Super Admin', 'SUPER_ADMIN')`,
        [email, hash]
    );
    console.log(`[DB] Super admin seeded: ${email}`);
}

async function seedDemoUsers() {
    const defaultPassword = 'password';
    const hash = await bcrypt.hash(defaultPassword, 10);
    const demoUsers = [
        { email: 'doctor@curio.app', name: 'Dr. Sharma', role: 'DOCTOR', tenant_id: 'default' },
        { email: 'reception@curio.app', name: 'Front Desk', role: 'RECEPTIONIST', tenant_id: 'default' },
        { email: 'pharmacy@curio.app', name: 'Pharmacist', role: 'PHARMACIST', tenant_id: 'default' },
    ];

    for (const u of demoUsers) {
        const existing = await pool.query('SELECT id FROM users WHERE email = $1', [u.email]);
        if (existing.rows.length === 0) {
            await pool.query(
                `INSERT INTO users (tenant_id, email, password_hash, name, role)
                 VALUES ($1, $2, $3, $4, $5)`,
                [u.tenant_id, u.email, hash, u.name, u.role]
            );
            console.log(`[DB] Demo user seeded: ${u.email}`);
        }
    }
}

// ── Seed legacy in-memory tenants into DB ─────────────────────────────────────

async function seedLegacyTenants() {
    const legacy = [
        {
            id: 'default',
            name: 'Curio Clinic',
            logo: 'C',
            primary_color: '#0F172A',
            secondary_color: '#38BDF8',
            consultation_fee: 500,
            plan: 'basic',
            working_hours: JSON.stringify([{ start: '09:00', end: '13:00' }, { start: '17:00', end: '22:00' }]),
            days_off: JSON.stringify([0]),
        },
        {
            id: 'sharma-clinic',
            name: "Dr. Sharma's Cardiology",
            logo: 'S',
            primary_color: '#1E3A8A',
            secondary_color: '#60A5FA',
            consultation_fee: 800,
            plan: 'pro',
            working_hours: JSON.stringify([{ start: '10:00', end: '14:00' }, { start: '18:00', end: '21:00' }]),
            days_off: JSON.stringify([0, 6]),
        },
        {
            id: 'apollo-hospitals',
            name: 'Apollo Multispecialty',
            logo: 'A',
            primary_color: '#065F46',
            secondary_color: '#34D399',
            consultation_fee: 1200,
            plan: 'enterprise',
            working_hours: JSON.stringify([{ start: '09:00', end: '22:00' }]),
            days_off: JSON.stringify([]),
        },
    ];

    for (const t of legacy) {
        await pool.query(
            `INSERT INTO tenants (id, name, logo, primary_color, secondary_color, consultation_fee, plan, working_hours, days_off)
             VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9::jsonb)
             ON CONFLICT (id) DO NOTHING`,
            [t.id, t.name, t.logo, t.primary_color, t.secondary_color, t.consultation_fee, t.plan, t.working_hours, t.days_off]
        );
    }
    console.log('[DB] Legacy tenants seeded.');
}

// ── Init ──────────────────────────────────────────────────────────────────────

async function initSchema() {
    try {
        await pool.query(SCHEMA_SQL);
        console.log('[DB] Schema ready.');
        await seedSuperAdmin();
        await seedLegacyTenants();
        await seedDemoUsers();
    } catch (err) {
        console.error('[DB] Schema init failed:', err.message);
        // Don't crash — let server start even if DB is temporarily unavailable
    }
}

// ── Exports ───────────────────────────────────────────────────────────────────

function query(sql, params) {
    return pool.query(sql, params);
}

module.exports = { query, pool, initSchema };
