import { ApplicationListRow, ApplicationRow, CommentRow } from "@app/shared/types/application";
import pool from "../../db";
import { error } from "console";
import * as mariadb from 'mariadb';


/**
 * Create an application in the db
 * @param memberID 
 * @param appVersion 
 * @param app 
 * @returns ID of the created application
 */
export async function createApplication(memberID: number, appVersion: number, app: string): Promise<number> {
  const sql = `INSERT INTO applications (member_id, app_version, app_data) VALUES (?, ?, ?);`;
  const params = [memberID, appVersion, JSON.stringify(app)]

  let result = await pool.query(sql, params);
  return Number(result.insertId);
}

export async function getMemberApplication(memberID: number): Promise<ApplicationRow> {
  const sql = `SELECT app.*,
          member.name AS member_name
      FROM applications AS app
          INNER JOIN members AS member ON member.id = app.member_id
      WHERE app.member_id = ? ORDER BY submitted_at DESC LIMIT 1;`;

  let app: ApplicationRow[] = await pool.query(sql, [memberID]);
  return app[0];
}


export async function getApplicationByID(appID: number): Promise<ApplicationRow> {
  const sql =
    `SELECT app.*,
          member.name AS member_name
      FROM applications AS app
          INNER JOIN members AS member ON member.id = app.member_id
      WHERE app.id = ?;`;
  let app: ApplicationRow[] = await pool.query(sql, [appID]);
  return app[0];
}

export async function getApplicationList(page: number = 1, pageSize: number = 25): Promise<ApplicationListRow[]> {
  const offset = (page - 1) * pageSize;

  const sql = `SELECT
      member.name AS member_name,
      app.id,
      app.member_id,
      app.submitted_at,
      app.app_status
    FROM applications AS app
    LEFT JOIN members AS member
      ON member.id = app.member_id
    ORDER BY app.submitted_at DESC
    LIMIT ? OFFSET ?;`

  const rows: ApplicationListRow[] = await pool.query(sql, [pageSize, offset]);
  return rows;
}

export async function getAllMemberApplications(memberID: number): Promise<ApplicationListRow[]> {
  const sql = `SELECT
      app.id,
      app.member_id,
      app.submitted_at,
      app.app_status
      FROM applications AS app WHERE app.member_id = ? ORDER BY submitted_at DESC;`;

  const rows: ApplicationListRow[] = await pool.query(sql, [memberID])
  return rows;
}


export async function approveApplication(id: number, approver: number, con: mariadb.Connection | mariadb.Pool = pool) {
  const sql = `
      UPDATE applications
         SET approved_at = NOW(), approved_by = ?
       WHERE id = ?
        AND approved_at IS NULL
        AND denied_at IS NULL
      `;

  const result = await con.query(sql, [approver, id]);
  if (result.affectedRows == 1) {
    return
  } else {
    throw new Error(`"Something went wrong approving application with ID ${id}`);
  }
}

export async function denyApplication(id: number, approver: number) {
  const sql = `
      UPDATE applications
         SET denied_at = NOW(), approved_by = ?
       WHERE id = ?
        AND approved_at IS NULL
        AND denied_at IS NULL
      `;

  const result = await pool.execute(sql, [approver, id]);
  if (result.affectedRows == 1) {
    return
  } else {
    throw new Error(`"Something went wrong denying application with ID ${id}`);
  }
}

export async function getApplicationComments(appID: number, admin: boolean = false): Promise<CommentRow[]> {
  const excludeAdmin = ' AND app.admin_only = false';

  const whereClause = `WHERE app.application_id = ?${!admin ? excludeAdmin : ''}`;

  return await pool.query(`SELECT app.id AS comment_id,
          app.post_content,
          app.poster_id,
          app.post_time,
          app.last_modified,
          app.admin_only,
          member.name AS poster_name
        FROM application_comments AS app
          INNER JOIN members AS member ON member.id = app.poster_id
        ${whereClause}`,
    [appID]);
}