import bcryptjs from 'bcryptjs';
const { hash, compare } = bcryptjs;
import jwt from 'jsonwebtoken';
const { sign, verify } = jwt;
import { getPool } from './db.js';
import type { RowDataPacket } from 'mysql2';

const JWT_SECRET = process.env.JWT_SECRET ?? process.env.CREDENTIAL_ENCRYPTION_KEY ?? 'dev-secret-change-me';
const SALT_ROUNDS = 12;

export interface JWTPayload {
  sub: string;      // customer id
  email: string;
  plan: string;
  role?: string;
}

export async function hashPassword(password: string): Promise<string> {
  return hash(password, SALT_ROUNDS);
}

export async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return compare(password, hash);
}

export function signJWT(payload: JWTPayload): string {
  return sign(payload, JWT_SECRET, { expiresIn: '7d' });
}

export function verifyJWT(token: string): JWTPayload {
  return verify(token, JWT_SECRET) as JWTPayload;
}

interface CustomerRow extends RowDataPacket {
  id: string;
  email: string;
  plan: string;
  active: boolean;
  api_key: string;
  password_hash: string | null;
  role: string;
}

export async function findCustomerByEmail(email: string): Promise<CustomerRow | null> {
  const [rows] = await getPool().query<CustomerRow[]>(
    'SELECT id, email, plan, active, api_key, password_hash, role FROM customers WHERE email = ?',
    [email]
  );
  return rows[0] ?? null;
}

export async function findCustomerById(id: string): Promise<CustomerRow | null> {
  const [rows] = await getPool().query<CustomerRow[]>(
    'SELECT id, email, plan, active, api_key, password_hash, role FROM customers WHERE id = ?',
    [id]
  );
  return rows[0] ?? null;
}

export async function createCustomer(
  id: string,
  email: string,
  passwordHash: string,
  apiKey: string
): Promise<void> {
  await getPool().query(
    'INSERT INTO customers (id, email, password_hash, api_key, plan, active) VALUES (?, ?, ?, ?, ?, ?)',
    [id, email, passwordHash, apiKey, 'free', true]
  );
}

export async function setResetToken(email: string, token: string): Promise<boolean> {
  const [result] = await getPool().query<any>(
    'UPDATE customers SET reset_token = ?, reset_expires_at = DATE_ADD(NOW(), INTERVAL 1 HOUR) WHERE email = ?',
    [token, email]
  );
  return result.affectedRows > 0;
}

export async function findCustomerByResetToken(token: string) {
  const [rows] = await getPool().query<CustomerRow[]>(
    'SELECT id, email, plan, active, api_key, password_hash, role FROM customers WHERE reset_token = ? AND reset_expires_at > NOW()',
    [token]
  );
  return rows[0] ?? null;
}

export async function clearResetToken(customerId: string): Promise<void> {
  await getPool().query(
    'UPDATE customers SET reset_token = NULL, reset_expires_at = NULL WHERE id = ?',
    [customerId]
  );
}

export async function updatePassword(customerId: string, passwordHash: string): Promise<void> {
  await getPool().query(
    'UPDATE customers SET password_hash = ? WHERE id = ?',
    [passwordHash, customerId]
  );
}
