import type { RowDataPacket } from 'mysql2';
import { getLearningPool } from '../config/faceVerify';
import type { FaceVerifyConfigRow } from '../types/faceVerify.types';

const PRESETS: Record<
  string,
  Pick<
    FaceVerifyConfigRow,
    | 'similarity_alert_below'
    | 'similarity_critical_below'
    | 'fail_count_before_notify'
    | 'check_interval_sec'
    | 'grace_period_start_min'
  >
> = {
  relaxed: {
    similarity_alert_below: 55,
    similarity_critical_below: 40,
    fail_count_before_notify: 4,
    check_interval_sec: 180,
    grace_period_start_min: 15,
  },
  standard: {
    similarity_alert_below: 65,
    similarity_critical_below: 45,
    fail_count_before_notify: 3,
    check_interval_sec: 120,
    grace_period_start_min: 10,
  },
  strict: {
    similarity_alert_below: 75,
    similarity_critical_below: 55,
    fail_count_before_notify: 2,
    check_interval_sec: 60,
    grace_period_start_min: 5,
  },
};

function rowToConfig(row: RowDataPacket): FaceVerifyConfigRow {
  const preset = String(row.preset || 'standard');
  const presetDefaults = PRESETS[preset] || PRESETS.standard;

  return {
    id: Number(row.id),
    scope: row.scope,
    course_id: row.course_id,
    recid: row.recid,
    itemid: row.itemid,
    enabled: Boolean(row.enabled),
    preset,
    similarity_alert_below: Number(
      row.similarity_alert_below ?? presetDefaults.similarity_alert_below,
    ),
    similarity_critical_below: Number(
      row.similarity_critical_below ?? presetDefaults.similarity_critical_below,
    ),
    fail_count_before_notify: Number(
      row.fail_count_before_notify ?? presetDefaults.fail_count_before_notify,
    ),
    check_interval_sec: Number(
      row.check_interval_sec ?? presetDefaults.check_interval_sec,
    ),
    grace_period_start_min: Number(
      row.grace_period_start_min ?? presetDefaults.grace_period_start_min,
    ),
    notify_level: row.notify_level || 'alert',
  };
}

const DEFAULT_CONFIG: FaceVerifyConfigRow = {
  id: 0,
  scope: 'global',
  course_id: null,
  recid: null,
  itemid: null,
  enabled: true,
  preset: 'standard',
  ...PRESETS.standard,
  notify_level: 'alert',
};

export async function resolveFaceVerifyConfig(
  courseId: string,
  recId: string,
  itemId: string,
): Promise<FaceVerifyConfigRow> {
  const pool = getLearningPool();

  const tryFetch = async (
    scope: string,
    c?: string,
    r?: string,
    i?: string,
  ): Promise<FaceVerifyConfigRow | null> => {
    const [rows] = await pool.query<RowDataPacket[]>(
      `SELECT * FROM tb_face_verify_config
       WHERE scope = ? AND course_id <=> ? AND recid <=> ? AND itemid <=> ?
       LIMIT 1`,
      [scope, c ?? null, r ?? null, i ?? null],
    );
    if (!rows.length) return null;
    return rowToConfig(rows[0]);
  };

  const exam = await tryFetch('exam', courseId, recId, itemId);
  if (exam) return exam;

  const course = await tryFetch('course', courseId, undefined, undefined);
  if (course) return course;

  const global = await tryFetch('global', undefined, undefined, undefined);
  return global || DEFAULT_CONFIG;
}

export function effectiveAlertThreshold(
  config: FaceVerifyConfigRow,
  inGracePeriod: boolean,
): number {
  const base = config.similarity_alert_below;
  return inGracePeriod ? Math.max(40, base - 10) : base;
}

export { PRESETS, DEFAULT_CONFIG };
