/**
 * Form 16 admin config reader for server-side use (notifications, cron).
 * Reads FORM16_ADMIN_CONFIG from admin_configurations and returns merged config with defaults.
 */

import { sequelize } from '../config/database';
import { QueryTypes } from 'sequelize';
import logger from '@utils/logger';

const FORM16_CONFIG_KEY = 'FORM16_ADMIN_CONFIG';

function normalizeRunAtTime(s: string): string {
  const [h, m] = s.split(':').map((x) => parseInt(x, 10));
  if (Number.isNaN(h) || Number.isNaN(m)) return '09:00';
  const hh = Math.max(0, Math.min(23, h));
  const mm = Math.max(0, Math.min(59, m));
  return `${String(hh).padStart(2, '0')}:${String(mm).padStart(2, '0')}`;
}

export interface Form16Notification26AsConfig {
  enabled: boolean;
  templateRe: string;
  templateDealers: string;
}

export interface Form16Config {
  notification26AsDataAdded: Form16Notification26AsConfig;
  /** RE reminder: prompt 26AS viewers to upload 26AS if missing for the most recently ended quarter. */
  reminder26AsUploadEnabled: boolean;
  reminder26AsUploadTemplate: string;
  /** Start reminders after quarter ends + N days. */
  reminder26AsUploadAfterQuarterEndDays: number;
  /** Repeat reminders every N days after start. */
  reminder26AsUploadEveryDays: number;
  notificationForm16SuccessCreditNote: { enabled: boolean; template: string };
  notificationForm16Unsuccessful: { enabled: boolean; template: string };
  reminderNotificationEnabled: boolean;
  reminderNotificationTemplate: string;
  /** When to run the reminder job daily (HH:mm, 24h, server timezone). Empty = no scheduled run. */
  reminderRunAtTime: string;
  alertSubmitForm16Enabled: boolean;
  alertSubmitForm16Template: string;
  /** When to run the alert job daily (HH:mm, 24h, server timezone). Empty = no scheduled run. */
  alertSubmitForm16RunAtTime: string;
  /** Dealer reminder: start after quarter ends + N days. */
  alertSubmitForm16AfterQuarterEndDays: number;
  /** Dealer reminder: repeat every N days after start. */
  alertSubmitForm16EveryDays: number;
  twentySixAsViewerEmails: string[];
}

const default26As = (): Form16Notification26AsConfig => ({
  enabled: true,
  templateRe: '26AS data has been added. Please review and use for matching dealer Form 16 submissions.',
  templateDealers: 'New 26AS data has been uploaded. You can now submit your Form 16 for the relevant quarter if you haven’t already.',
});

const defaults: Form16Config = {
  notification26AsDataAdded: default26As(),
  reminder26AsUploadEnabled: true,
  reminder26AsUploadTemplate: 'Reminder: 26AS data for [FinancialYear] [Quarter] is not uploaded yet. Please upload it in 26AS Management.',
  reminder26AsUploadAfterQuarterEndDays: 0,
  reminder26AsUploadEveryDays: 7,
  notificationForm16SuccessCreditNote: { enabled: true, template: 'Form 16 submitted successfully. Credit note: [CreditNoteRef].' },
  notificationForm16Unsuccessful: { enabled: true, template: 'Form 16 submission was unsuccessful. Issue: [Issue].' },
  reminderNotificationEnabled: true,
  reminderNotificationTemplate: 'Reminder: Dear [Name], your Form 16A submission is pending for request [Request ID]. Please complete it.',
  reminderRunAtTime: '10:00',
  alertSubmitForm16Enabled: true,
  alertSubmitForm16Template: 'Dear [Name], please submit Form 16A for the pending period. Due: [DueDate].',
  alertSubmitForm16RunAtTime: '09:00',
  alertSubmitForm16AfterQuarterEndDays: 0,
  alertSubmitForm16EveryDays: 7,
  twentySixAsViewerEmails: [],
};

/**
 * Load Form 16 config from admin_configurations for server-side use.
 */
export async function getForm16Config(): Promise<Form16Config> {
  try {
    const result = await sequelize.query<{ config_value: string }>(
      `SELECT config_value FROM admin_configurations WHERE config_key = :configKey LIMIT 1`,
      { replacements: { configKey: FORM16_CONFIG_KEY }, type: QueryTypes.SELECT }
    );
    if (!result?.length || !result[0].config_value) {
      return defaults;
    }
    const parsed = JSON.parse(result[0].config_value) as Record<string, unknown>;

    const merge26As = (): Form16Notification26AsConfig => {
      const v = parsed.notification26AsDataAdded;
      if (v && typeof v === 'object' && typeof (v as any).enabled === 'boolean') {
        const val = v as any;
        return {
          enabled: val.enabled,
          templateRe: typeof val.templateRe === 'string' ? val.templateRe : (typeof val.template === 'string' ? val.template : defaults.notification26AsDataAdded.templateRe),
          templateDealers: typeof val.templateDealers === 'string' ? val.templateDealers : defaults.notification26AsDataAdded.templateDealers,
        };
      }
      return defaults.notification26AsDataAdded;
    };

    return {
      notification26AsDataAdded: merge26As(),
      reminder26AsUploadEnabled: typeof parsed.reminder26AsUploadEnabled === 'boolean' ? parsed.reminder26AsUploadEnabled : defaults.reminder26AsUploadEnabled,
      reminder26AsUploadTemplate: typeof parsed.reminder26AsUploadTemplate === 'string' ? parsed.reminder26AsUploadTemplate : defaults.reminder26AsUploadTemplate,
      reminder26AsUploadAfterQuarterEndDays:
        typeof parsed.reminder26AsUploadAfterQuarterEndDays === 'number'
          ? Math.max(0, Math.min(365, parsed.reminder26AsUploadAfterQuarterEndDays))
          : defaults.reminder26AsUploadAfterQuarterEndDays,
      reminder26AsUploadEveryDays:
        typeof parsed.reminder26AsUploadEveryDays === 'number'
          ? Math.max(1, Math.min(365, parsed.reminder26AsUploadEveryDays))
          : defaults.reminder26AsUploadEveryDays,
      notificationForm16SuccessCreditNote:
        parsed.notificationForm16SuccessCreditNote && typeof (parsed.notificationForm16SuccessCreditNote as any).template === 'string'
          ? { enabled: (parsed.notificationForm16SuccessCreditNote as any).enabled !== false, template: (parsed.notificationForm16SuccessCreditNote as any).template }
          : defaults.notificationForm16SuccessCreditNote,
      notificationForm16Unsuccessful:
        parsed.notificationForm16Unsuccessful && typeof (parsed.notificationForm16Unsuccessful as any).template === 'string'
          ? { enabled: (parsed.notificationForm16Unsuccessful as any).enabled !== false, template: (parsed.notificationForm16Unsuccessful as any).template }
          : defaults.notificationForm16Unsuccessful,
      reminderNotificationEnabled: typeof parsed.reminderNotificationEnabled === 'boolean' ? parsed.reminderNotificationEnabled : defaults.reminderNotificationEnabled,
      reminderNotificationTemplate: typeof parsed.reminderNotificationTemplate === 'string' ? parsed.reminderNotificationTemplate : defaults.reminderNotificationTemplate,
      reminderRunAtTime: typeof parsed.reminderRunAtTime === 'string' && parsed.reminderRunAtTime.trim() ? (/^\d{1,2}:\d{2}$/.test(parsed.reminderRunAtTime.trim()) ? normalizeRunAtTime(parsed.reminderRunAtTime.trim()) : defaults.reminderRunAtTime) : '',
      alertSubmitForm16Enabled: typeof parsed.alertSubmitForm16Enabled === 'boolean' ? parsed.alertSubmitForm16Enabled : defaults.alertSubmitForm16Enabled,
      alertSubmitForm16Template: typeof parsed.alertSubmitForm16Template === 'string' ? parsed.alertSubmitForm16Template : defaults.alertSubmitForm16Template,
      alertSubmitForm16RunAtTime: typeof parsed.alertSubmitForm16RunAtTime === 'string' && parsed.alertSubmitForm16RunAtTime.trim() ? (/^\d{1,2}:\d{2}$/.test(parsed.alertSubmitForm16RunAtTime.trim()) ? normalizeRunAtTime(parsed.alertSubmitForm16RunAtTime.trim()) : defaults.alertSubmitForm16RunAtTime) : '',
      alertSubmitForm16AfterQuarterEndDays:
        typeof parsed.alertSubmitForm16AfterQuarterEndDays === 'number'
          ? Math.max(0, Math.min(365, parsed.alertSubmitForm16AfterQuarterEndDays))
          : defaults.alertSubmitForm16AfterQuarterEndDays,
      alertSubmitForm16EveryDays:
        typeof parsed.alertSubmitForm16EveryDays === 'number'
          ? Math.max(1, Math.min(365, parsed.alertSubmitForm16EveryDays))
          : defaults.alertSubmitForm16EveryDays,
      twentySixAsViewerEmails: Array.isArray(parsed.twentySixAsViewerEmails)
        ? (parsed.twentySixAsViewerEmails as string[]).map((e) => String(e).trim().toLowerCase()).filter(Boolean)
        : defaults.twentySixAsViewerEmails,
    };
  } catch (e) {
    logger.warn('[Form16Config] Failed to load config, using defaults:', e);
    return defaults;
  }
}
