// =====================================================
// INVESTMENT ACCOUNT CRUD API + AUTH (Node.js + Express + MySQL2)
// JSON API — Login redirects to dashboard route
// =====================================================

/*
INSTALL
npm init -y
npm install express mysql2 bcryptjs jsonwebtoken dotenv cors helmet express-rate-limit multer
npm install nodemon --save-dev
*/

// =====================================================
// FOLDER STRUCTURE
// =====================================================
/*
/config/db.js
/models/userModel.js
/controllers/authController.js
/controllers/investmentController.js
/middleware/authMiddleware.js
/middleware/uploadMiddleware.js
/routes/authRoutes.js
/routes/investmentRoutes.js
/server.js
*/


// =====================================================
// server.js
// =====================================================
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');

const authRoutes = require('./routes/authRoutes');
const investmentRoutes = require('./routes/investmentRoutes');

const app = express();

app.use(helmet());
app.use(cors());
app.use(express.json());
app.use('/uploads', express.static('uploads'));

app.use('/api/auth', authRoutes);
app.use('/api/investments', investmentRoutes);

app.get('/dashboard', (req,res)=>{
  res.json({message:'Investment Profile Dashboard'});
});

app.use((err,req,res,next)=>{
  console.error(err);
  res.status(500).json({message:'Server error'});
});

app.listen(process.env.PORT || 5000, ()=>
  console.log('Server running')
);


// =====================================================
// config/db.js
// =====================================================
const mysql = require('mysql2/promise');

module.exports = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
  connectionLimit: 10
});


// =====================================================
// middleware/authMiddleware.js
// =====================================================
const jwt = require('jsonwebtoken');

exports.verifyToken = (req,res,next)=>{
  const header = req.headers.authorization;
  if(!header) return res.status(401).json({message:'No token'});

  try{
    const token = header.split(' ')[1];
    req.user = jwt.verify(token, process.env.JWT_SECRET);
    next();
  }catch{
    res.status(401).json({message:'Invalid token'});
  }
};


// =====================================================
// middleware/uploadMiddleware.js
// =====================================================
const multer = require('multer');

const storage = multer.diskStorage({
  destination: 'uploads/',
  filename: (req,file,cb)=>{
    cb(null, Date.now() + '-' + file.originalname);
  }
});

exports.upload = multer({storage});


// =====================================================
// models/userModel.js
// =====================================================
const db = require('../config/db');

exports.createAccount = async data => {
  const sql = `
  INSERT INTO investment_accounts
  (firstname, lastname, username, email, phonenumber, password_hash,
   total_investment_amount, account_pin, bvn, dateofbirth, profile_picture)
  VALUES (?,?,?,?,?,?,?,?,?,?,?)`;

  const [r] = await db.execute(sql,[
    data.firstname,
    data.lastname,
    data.username,
    data.email,
    data.phonenumber,
    data.password_hash,
    0,        // total investment default
    null,     // pin later
    null,     // bvn later
    null,     // dob later
    null      // profile picture later
  ]);

  return r.insertId;
};

exports.findByEmail = async email => {
  const [r] = await db.execute(
    'SELECT * FROM investment_accounts WHERE email=?',
    [email]
  );
  return r[0];
};

exports.findById = async id => {
  const [r] = await db.execute(
    'SELECT * FROM investment_accounts WHERE id=?',
    [id]
  );
  return r[0];
};

exports.updateProfile = async (id,data)=>{
  const sql = `
  UPDATE investment_accounts SET
    total_investment_amount=?,
    account_pin=?,
    bvn=?,
    dateofbirth=?,
    profile_picture=?
  WHERE id=?`;

  await db.execute(sql,[
    data.total_investment_amount,
    data.account_pin,
    data.bvn,
    data.dateofbirth,
    data.profile_picture,
    id
  ]);
};

exports.getAll = async ()=>{
  const [r] = await db.execute('SELECT * FROM investment_accounts');
  return r;
};

exports.deleteById = async id => {
  await db.execute('DELETE FROM investment_accounts WHERE id=?',[id]);
};


// =====================================================
// controllers/authController.js
// =====================================================
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/userModel');

const sign = u => jwt.sign({id:u.id,email:u.email}, process.env.JWT_SECRET,{expiresIn:'1d'});

exports.register = async (req,res)=>{
  const {firstname,lastname,username,email,phonenumber,password} = req.body;

  if(!email || !password)
    return res.status(400).json({message:'Missing fields'});

  if(await User.findByEmail(email))
    return res.status(409).json({message:'Email exists'});

  const hash = await bcrypt.hash(password,12);

  const id = await User.createAccount({
    firstname,lastname,username,email,phonenumber,password_hash:hash
  });

  res.status(201).json({
    message:'Account created',
    token: sign({id,email}),
    redirect:'/dashboard'
  });
};


exports.login = async (req,res)=>{
  const {email,password} = req.body;

  const user = await User.findByEmail(email);
  if(!user) return res.status(401).json({message:'Invalid credentials'});

  const ok = await bcrypt.compare(password, user.password_hash);
  if(!ok) return res.status(401).json({message:'Invalid credentials'});

  res.json({
    message:'Login success',
    token: sign(user),
    redirect:'/dashboard'
  });
};


// =====================================================
// controllers/investmentController.js
// =====================================================
const UserModel = require('../models/userModel');

exports.getProfile = async (req,res)=>{
  const user = await UserModel.findById(req.user.id);
  res.json(user);
};

exports.updateProfile = async (req,res)=>{
  const file = req.file ? req.file.filename : null;

  await UserModel.updateProfile(req.user.id,{
    total_investment_amount: req.body.total_investment_amount,
    account_pin: req.body.account_pin,
    bvn: req.body.bvn,
    dateofbirth: req.body.dateofbirth,
    profile_picture: file
  });

  res.json({message:'Profile updated'});
};

exports.listAll = async (req,res)=>{
  res.json(await UserModel.getAll());
};

exports.remove = async (req,res)=>{
  await UserModel.deleteById(req.params.id);
  res.json({message:'Deleted'});
};


// =====================================================
// routes/authRoutes.js
// =====================================================
const express = require('express');
const rateLimit = require('express-rate-limit');
const ctrl = require('../controllers/authController');

const router = express.Router();
const limiter = rateLimit({windowMs:15*60*1000,max:100});

router.post('/register', limiter, ctrl.register);
router.post('/login', limiter, ctrl.login);

module.exports = router;


// =====================================================
// routes/investmentRoutes.js
// =====================================================
const express = require('express');
const ctrl = require('../controllers/investmentController');
const {verifyToken} = require('../middleware/authMiddleware');
const {upload} = require('../middleware/uploadMiddleware');

const router = express.Router();

router.get('/me', verifyToken, ctrl.getProfile);
router.put('/me', verifyToken, upload.single('profile_picture'), ctrl.updateProfile);
router.get('/', verifyToken, ctrl.listAll);
router.delete('/:id', verifyToken, ctrl.remove);

module.exports = router;


// =====================================================
// MYSQL TABLE
// =====================================================
/*
CREATE TABLE investment_accounts (
 id INT AUTO_INCREMENT PRIMARY KEY,
 firstname VARCHAR(100),
 lastname VARCHAR(100),
 username VARCHAR(100),
 email VARCHAR(150) UNIQUE,
 phonenumber VARCHAR(40),
 password_hash VARCHAR(255),
 total_investment_amount DECIMAL(15,2) DEFAULT 0,
 account_pin VARCHAR(20),
 bvn VARCHAR(30),
 dateofbirth DATE,
 profile_picture VARCHAR(255),
 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
*/


// =====================================================
// .env
// =====================================================
/*
PORT=5000
DB_HOST=localhost
DB_USER=root
DB_PASS=yourpass
DB_NAME=investdb
JWT_SECRET=supersecret
*/






// ==========================================
// FRONTEND FETCH API CLIENT
// Connects to Investment Auth CRUD Backend
// ==========================================

// ---- CONFIG ----
const API_BASE = "http://localhost:5000/api";

// ==========================================
// TOKEN STORAGE HELPERS
// ==========================================
function saveToken(token) {
  localStorage.setItem('auth_token', token);
}

function getToken() {
  return localStorage.getItem('auth_token');
}

function authHeader() {
  return {
    Authorization: `Bearer ${getToken()}`
  };
}


// ==========================================
// REGISTER ACCOUNT (Create Investment Account)
// form id="registerForm"
// ==========================================
document.getElementById('registerForm')?.addEventListener('submit', async (e) => {
  e.preventDefault();

  const btn = e.target.querySelector('button[type="submit"]');
  btn.disabled = true;
  btn.innerText = "Creating...";

  const formData = Object.fromEntries(new FormData(e.target));

  try {
    const res = await fetch(`${API_BASE}/auth/register`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(formData)
    });

    const data = await res.json();

    if (!res.ok) throw new Error(data.message);

    saveToken(data.token);
    alert('Account created');
    window.location.href = data.redirect;

  } catch (err) {
    alert(err.message);
  }

  btn.disabled = false;
  btn.innerText = "Register";
});


// ==========================================
// LOGIN
// form id="loginForm"
// ==========================================
document.getElementById('loginForm')?.addEventListener('submit', async (e) => {
  e.preventDefault();

  const btn = e.target.querySelector('button[type="submit"]');
  btn.disabled = true;
  btn.innerText = "Logging in...";

  const body = Object.fromEntries(new FormData(e.target));

  try {
    const res = await fetch(`${API_BASE}/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body)
    });

    const data = await res.json();

    if (!res.ok) throw new Error(data.message);

    saveToken(data.token);
    window.location.href = data.redirect;

  } catch (err) {
    alert(err.message);
  }

  btn.disabled = false;
  btn.innerText = "Login";
});


// ==========================================
// LOAD MY PROFILE DASHBOARD DATA
// call on dashboard page load
// ==========================================
async function loadMyProfile() {
  try {
    const res = await fetch(`${API_BASE}/investments/me`, {
      headers: authHeader()
    });

    if (res.status === 401) {
      alert('Session expired');
      return window.location.href = '/login.html';
    }

    const user = await res.json();

    // Example render
    document.getElementById('dashName').innerText =
      user.firstname + ' ' + user.lastname;

    document.getElementById('dashEmail').innerText = user.email;
    document.getElementById('dashAmount').innerText =
      user.total_investment_amount;

    if (user.profile_picture) {
      document.getElementById('dashPic').src =
        `/uploads/${user.profile_picture}`;
    }

  } catch (err) {
    console.error(err);
  }
}


// ==========================================
// UPDATE PROFILE (PIN, BVN, DOB, Amount, Picture)
// form id="profileForm"
// ==========================================
document.getElementById('profileForm')?.addEventListener('submit', async (e) => {
  e.preventDefault();

  const btn = e.target.querySelector('button[type="submit"]');
  btn.disabled = true;
  btn.innerText = "Updating...";

  const fd = new FormData(e.target); // includes file upload

  try {
    const res = await fetch(`${API_BASE}/investments/me`, {
      method: 'PUT',
      headers: authHeader(),
      body: fd
    });

    const data = await res.json();
    if (!res.ok) throw new Error(data.message);

    alert('Profile updated');
    loadMyProfile();

  } catch (err) {
    alert(err.message);
  }

  btn.disabled = false;
  btn.innerText = "Save Changes";
});


// ==========================================
// LIST ALL INVESTMENT ACCOUNTS (Admin table)
// ==========================================
async function loadAllAccounts() {
  const res = await fetch(`${API_BASE}/investments`, {
    headers: authHeader()
  });

  const list = await res.json();

  const tbody = document.getElementById('accountsTable');
  tbody.innerHTML = '';

  list.forEach(acc => {
    tbody.innerHTML += `
      <tr>
        <td>${acc.id}</td>
        <td>${acc.firstname}</td>
        <td>${acc.email}</td>
        <td>${acc.total_investment_amount}</td>
        <td>
          <button onclick="deleteAccount(${acc.id})">Delete</button>
        </td>
      </tr>`;
  });
}


// ==========================================
// DELETE ACCOUNT
// ==========================================
async function deleteAccount(id) {
  if (!confirm('Delete account?')) return;

  await fetch(`${API_BASE}/investments/${id}`, {
    method: 'DELETE',
    headers: authHeader()
  });

  loadAllAccounts();
}


// ==========================================
// LOGOUT
// ==========================================
function logout() {
  localStorage.removeItem('auth_token');
  window.location.href = '/login.html';
}
