import express from 'express';
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
import bcrypt from 'bcrypt';
import nodemailer from 'nodemailer';
import dotenv from 'dotenv';
import fs, { stat } from 'fs';

dotenv.config();

const transporter = nodemailer.createTransport({
  host: 'email.thepenguinontheweb.tech',
  port: 587,
  secure: false, // false pour STARTTLS
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS
  }
});

function sendMail(to, subject, html) {
  const mailOptions = {
    from: process.env.EMAIL_USER,
    to: to,
    subject: subject,
    html: html
  };

  return transporter.sendMail(mailOptions)
    .then(() => console.log('Email sent successfully'))
    .catch(error => console.error('Error sending email:', error));
}

const db = await open({
  filename: './db/database.db',
  driver: sqlite3.Database
});

function initializeDatabase() {
  db.exec(`
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      username TEXT NOT NULL UNIQUE,
      email TEXT NOT NULL UNIQUE,
      password TEXT NOT NULL,
      historyToDefault INTEGER DEFAULT 0
    );
  `);

  db.exec(`
    CREATE TABLE IF NOT EXISTS verify (
      id INTEGER PRIMARY KEY,
      token TEXT NOT NULL UNIQUE,
      username TEXT NOT NULL UNIQUE,
      email TEXT NOT NULL UNIQUE,
      password TEXT NOT NULL,
      createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
    );
  `);
}

initializeDatabase();

const app = express();
const port = 20909;

app.use(express.json());
app.use(express.static('public'));

app.get('/login', (req, res) => {
  res.sendFile('index.html', { root: 'public' });
}
);
app.get('/register', (req, res) => {
  res.sendFile('register.html', { root: 'public' });
}
);
app.get('/', (req, res) => {
  // redirect to login page
  res.redirect('/login');
}
);

app.post('/api/login', (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).json({ message: 'Username and password are required' });
  }

  db.get('SELECT * FROM users WHERE username = ? OR email = ?', [username, username])
    .then(user => {
      if (!user) {
        return res.status(401).json({ message: 'Invalid username or password' });
      }

      // Check password (replace with real password check logic)
      const isPasswordValid = bcrypt.compareSync(password, user.password);
      if (!isPasswordValid) {
        return res.status(401).json({ message: 'Invalid username or password' });
      }

      res.status(200).json({ message: 'Login successful' });
    })
    .catch(err => {
      console.error('Database error:', err);
      res.status(500).json({ message: 'Internal server error' });
    });
}
);

app.post('/api/register', (req, res) => {
  const { username, email, password } = req.body;

  if (!username || !email || !password) {
    return res.status(400).json({ message: 'Username, email, and password are required' });
  }

  const hashedPassword = bcrypt.hashSync(password, 10);

  let isAlreadyRegistered = false;
  db.get('SELECT * FROM users WHERE username = ? OR email = ?', [username, email])
    .then(user => {
      if (user) {
        isAlreadyRegistered = true;
        return res.status(409).json({ message: 'Username or email already exists' });
      }
    })
    .catch(err => {
      console.error('Database error:', err);
      return res.status(500).json({ message: 'Internal server error' });
    });

  if (isAlreadyRegistered) {
    return;
  }

  db.get('SELECT * FROM verify WHERE username = ? OR email = ?', [username, email])
    .then(verify => {
      if (verify) {
        // Verify if the last verification token is still valid
        if (Date.now() - new Date(verify.createdAt).getTime() < 24 * 60 * 60 * 1000) {
          isAlreadyRegistered = true;
          return res.status(409).json({ message: 'Verification already sent, please check your email' });
        }
        else {
          // If the token is expired, delete it
          db.run('DELETE FROM verify WHERE id = ?', [verify.id])
            .catch(err => {
              console.error('Database error:', err);
              return res.status(500).json({ message: 'Internal server error' });
            });
        }
      }
    })
    .catch(err => {
      console.error('Database error:', err);
      return res.status(500).json({ message: 'Internal server error' });
    });

  if (isAlreadyRegistered) {
    return;
  }

  const verificationToken = Math.random().toString(36).substring(2, 15);
  db.run('INSERT INTO verify (token, username, email, password) VALUES (?, ?, ?, ?)', [verificationToken, username, email, hashedPassword])
    .then(() => {
      // read the email template
      const emailTemplate = fs.readFileSync('mailFile/mail.html', 'utf8');

      // replace placeholders in the email template
      const emailContent = emailTemplate.replace('{{verification_link}}', `${process.env.URL}/verify?token=${verificationToken}`);

      sendMail(email, 'Welcome to Our Service', emailContent);
      res.status(201).json({ message: 'email send' });
    })
    .catch(err => {
      console.error('Database error:', err);
      return res.status(500).json({ message: 'Internal server error' });
    });
}
);

app.get('/verify', (req, res) => {
  const { token } = req.query;

  if (!token) {
    return res.status(400).json({ message: 'Token is required' });
  }

    res.sendFile('verify.html', { root: 'public' });
}
);

app.post('/api/verify', (req, res) => {
  const { token } = req.body;

  if (!token) {
    return res.status(400).json({ message: 'Token is required' });
  }

  db.get('SELECT * FROM verify WHERE token = ?', [token])
    .then(verify => {
      if (!verify) {
        return res.status(404).json({ message: 'Invalid or expired token' });
      }

      // Insert user into users table
      db.run('INSERT INTO users (username, email, password) VALUES (?, ?, ?)', [verify.username, verify.email, verify.password])
        .then(() => {
          // Delete the verification record
          db.run('DELETE FROM verify WHERE id = ?', [verify.id])
            .then(() => {
              res.status(200).json({ message: 'Email verified successfully' });
            })
            .catch(err => {
              console.error('Database error:', err);
              res.status(500).json({ message: 'Internal server error' });
            });
        })
        .catch(err => {
          console.error('Database error:', err);
          res.status(500).json({ message: 'Internal server error' });
        });
    })
    .catch(err => {
      console.error('Database error:', err);
      res.status(500).json({ message: 'Internal server error' });
    });
}
);

app.listen(port, "127.0.0.1", () => {
  console.log(`Server is running on localhost:${port}`);
}
);