CREATE DATABASE IF NOT EXISTS finanzas_personales
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_unicode_ci;

USE finanzas_personales;

CREATE TABLE estados_usuario (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(50) NOT NULL UNIQUE
) ENGINE=InnoDB;

INSERT INTO estados_usuario (nombre) VALUES
('ACTIVO'),
('INACTIVO'),
('BLOQUEADO');

CREATE TABLE tipos_transaccion (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(50) NOT NULL UNIQUE,
    descripcion VARCHAR(255)
) ENGINE=InnoDB;

INSERT INTO tipos_transaccion (nombre, descripcion) VALUES
('INGRESO', 'Dinero que entra a la cuenta'),
('EGRESO', 'Dinero que sale de la cuenta');

CREATE TABLE monedas (
    id INT AUTO_INCREMENT PRIMARY KEY,
    codigo CHAR(3) NOT NULL UNIQUE,
    nombre VARCHAR(50) NOT NULL,
    simbolo VARCHAR(10),
    pais VARCHAR(50)
) ENGINE=InnoDB;

INSERT INTO monedas (codigo, nombre, simbolo, pais) VALUES
('USD', 'Dólar Estadounidense', '$', 'Estados Unidos'),
('EUR', 'Euro', '€', 'Unión Europea'),
('MXN', 'Peso Mexicano', '$', 'México'),
('COP', 'Peso Colombiano', '$', 'Colombia'),
('GTQ', 'Quetzal', 'Q', 'Guatemala');

CREATE TABLE periodos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(20) NOT NULL UNIQUE,
    descripcion VARCHAR(255)
) ENGINE=InnoDB;

INSERT INTO periodos (nombre, descripcion) VALUES
('MENSUAL', 'Cada mes'),
('ANUAL', 'Cada año');

CREATE TABLE tipos_cuenta (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(50) NOT NULL UNIQUE,
    descripcion VARCHAR(255)
) ENGINE=InnoDB;

INSERT INTO tipos_cuenta (nombre, descripcion) VALUES
('EFECTIVO', 'Dinero en efectivo'),
('BANCARIA', 'Cuenta bancaria'),
('INVERSION', 'Cuenta de inversión'),
('CREDITO', 'Tarjeta de crédito');

CREATE TABLE usuarios (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(100) NOT NULL,
    email VARCHAR(150) NOT NULL UNIQUE,
    contraseña VARCHAR(255) NOT NULL,
    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    ultima_conexion TIMESTAMP NULL,
    estado_id INT NOT NULL DEFAULT 1,
    FOREIGN KEY (estado_id) REFERENCES estados_usuario(id),
    INDEX (email)
) ENGINE=InnoDB;

CREATE TABLE categorias (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(100) NOT NULL,
    descripcion VARCHAR(255),
    tipo_transaccion_id INT NOT NULL,
    FOREIGN KEY (tipo_transaccion_id) REFERENCES tipos_transaccion(id),
    UNIQUE (nombre, tipo_transaccion_id),
    INDEX (tipo_transaccion_id)
) ENGINE=InnoDB;

INSERT INTO categorias (nombre, descripcion, tipo_transaccion_id) VALUES
('SALARIO', 'Ingresos por salario', 1),
('VENTA', 'Ingresos por ventas', 1),
('ALQUILER', 'Gasto en alquiler', 2),
('COMIDA', 'Gasto en alimentos', 2),
('TRANSPORTE', 'Gasto en transporte', 2),
('ENTRETENIMIENTO', 'Gasto en entretenimiento', 2);

CREATE TABLE cuentas (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    usuario_id BIGINT UNSIGNED NOT NULL,
    nombre VARCHAR(100) NOT NULL,
    tipo_cuenta_id INT NOT NULL,
    moneda_id INT NOT NULL,
    saldo DECIMAL(20, 4) NOT NULL DEFAULT 0.0000,
    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE CASCADE,
    FOREIGN KEY (tipo_cuenta_id) REFERENCES tipos_cuenta(id),
    FOREIGN KEY (moneda_id) REFERENCES monedas(id),
    INDEX (usuario_id),
    INDEX (tipo_cuenta_id),
    INDEX (moneda_id)
) ENGINE=InnoDB;

CREATE TABLE transacciones (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    usuario_id BIGINT UNSIGNED NOT NULL,
    tipo_transaccion_id INT NOT NULL,
    categoria_id INT NOT NULL,
    monto DECIMAL(10, 2) NOT NULL,
    moneda_id INT NOT NULL,
    fecha DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    descripcion VARCHAR(255),
    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    fecha_actualizacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE CASCADE,
    FOREIGN KEY (tipo_transaccion_id) REFERENCES tipos_transaccion(id),
    FOREIGN KEY (categoria_id) REFERENCES categorias(id),
    FOREIGN KEY (moneda_id) REFERENCES monedas(id),
    INDEX (usuario_id),
    INDEX (tipo_transaccion_id),
    INDEX (categoria_id),
    INDEX (moneda_id),
    INDEX (fecha)
) ENGINE=InnoDB;

CREATE TABLE presupuestos (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    usuario_id BIGINT UNSIGNED NOT NULL,
    categoria_id INT NOT NULL,
    monto DECIMAL(10, 2) NOT NULL,
    periodo_id INT NOT NULL,
    fecha_inicio DATE NOT NULL,
    fecha_fin DATE NOT NULL,
    fecha_creacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    fecha_actualizacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE CASCADE,
    FOREIGN KEY (categoria_id) REFERENCES categorias(id),
    FOREIGN KEY (periodo_id) REFERENCES periodos(id),
    INDEX (usuario_id),
    INDEX (categoria_id),
    INDEX (periodo_id),
    INDEX (fecha_inicio),
    INDEX (fecha_fin)
) ENGINE=InnoDB;

-- ============================================
--    Índices Adicionales para Optimización
-- ============================================

-- Índice para consultas de transacciones por usuario y fecha
CREATE INDEX idx_transacciones_usuario_fecha ON transacciones(usuario_id, fecha);

-- Índice para consultas de transacciones por categoría y monto
CREATE INDEX idx_transacciones_categoria_monto ON transacciones(categoria_id, monto);

-- Índice para consultas de presupuestos por usuario y periodo
CREATE INDEX idx_presupuestos_usuario_periodo ON presupuestos(usuario_id, periodo_id);

-- Optimiza búsquedas por fechas de inicio y fin de presupuestos
CREATE INDEX idx_presupuestos_fechas ON presupuestos(fecha_inicio, fecha_fin);

-- Índice para consultas de transacciones por moneda
CREATE INDEX idx_transacciones_moneda ON transacciones(moneda_id);

-- Optimiza búsquedas por estado y fecha de última conexión
CREATE INDEX idx_usuarios_estado ON usuarios(estado_id, ultima_conexion);

-- Optimiza búsquedas por fecha de creación
CREATE INDEX idx_usuarios_fecha_creacion ON usuarios(fecha_creacion);

-- Optimiza búsquedas de cuentas por tipo y saldo
CREATE INDEX idx_cuentas_tipo_saldo ON cuentas(tipo_cuenta_id, saldo);

-- Optimiza búsquedas por fecha de creación y saldo
CREATE INDEX idx_cuentas_fecha_saldo ON cuentas(fecha_creacion, saldo);