import { scryptSync, timingSafeEqual } from "node:crypto";
import { getPool } from "../db/pool";

export type MerchantUserEntity = {
  id: string;
  merchant_id: string;
  name: string;
  email: string;
  password_hash: string;
  role_name: "owner" | "finance" | "ops" | "viewer";
  status: "active" | "inactive";
  created_at: string;
  updated_at: string;
};

function mapMerchantUser(row: any): MerchantUserEntity {
  return {
    id: row.id,
    merchant_id: row.merchant_id,
    name: row.name,
    email: row.email,
    password_hash: row.password_hash,
    role_name: row.role_name,
    status: row.status,
    created_at: row.created_at,
    updated_at: row.updated_at
  };
}

export async function getMerchantUserByEmail(email: string): Promise<MerchantUserEntity | null> {
  const { rows } = await getPool().query(
    "SELECT * FROM merchant_users WHERE LOWER(email) = LOWER($1) LIMIT 1",
    [email]
  );
  return rows[0] ? mapMerchantUser(rows[0]) : null;
}

function verifyScryptPassword(stored: string, password: string) {
  const parts = stored.split("$");
  if (parts.length !== 4 || parts[0] !== "scrypt") {
    return false;
  }
  const [, salt, keyLengthRaw, expectedHex] = parts;
  const keyLength = Number(keyLengthRaw);
  if (!salt || !Number.isFinite(keyLength) || keyLength <= 0 || !expectedHex) {
    return false;
  }
  const expected = Buffer.from(expectedHex, "hex");
  const actual = scryptSync(password, salt, keyLength);
  return expected.length === actual.length && timingSafeEqual(expected, actual);
}

export function verifyMerchantPassword(stored: string, password: string) {
  if (stored.startsWith("scrypt$")) {
    return verifyScryptPassword(stored, password);
  }

  return stored === password;
}

export function toMerchantUserPayload(user: MerchantUserEntity) {
  return {
    id: user.id,
    merchant_id: user.merchant_id,
    name: user.name,
    email: user.email,
    role_name: user.role_name,
    status: user.status,
    created_at: user.created_at,
    updated_at: user.updated_at
  };
}
